Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
35294 views
1
//===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
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
#include "MCTargetDesc/RISCVAsmBackend.h"
10
#include "MCTargetDesc/RISCVBaseInfo.h"
11
#include "MCTargetDesc/RISCVInstPrinter.h"
12
#include "MCTargetDesc/RISCVMCExpr.h"
13
#include "MCTargetDesc/RISCVMCTargetDesc.h"
14
#include "MCTargetDesc/RISCVMatInt.h"
15
#include "MCTargetDesc/RISCVTargetStreamer.h"
16
#include "TargetInfo/RISCVTargetInfo.h"
17
#include "llvm/ADT/STLExtras.h"
18
#include "llvm/ADT/SmallBitVector.h"
19
#include "llvm/ADT/SmallVector.h"
20
#include "llvm/ADT/Statistic.h"
21
#include "llvm/ADT/StringExtras.h"
22
#include "llvm/MC/MCAssembler.h"
23
#include "llvm/MC/MCContext.h"
24
#include "llvm/MC/MCExpr.h"
25
#include "llvm/MC/MCInst.h"
26
#include "llvm/MC/MCInstBuilder.h"
27
#include "llvm/MC/MCInstrInfo.h"
28
#include "llvm/MC/MCObjectFileInfo.h"
29
#include "llvm/MC/MCParser/MCAsmLexer.h"
30
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
31
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
32
#include "llvm/MC/MCRegisterInfo.h"
33
#include "llvm/MC/MCStreamer.h"
34
#include "llvm/MC/MCSubtargetInfo.h"
35
#include "llvm/MC/MCValue.h"
36
#include "llvm/MC/TargetRegistry.h"
37
#include "llvm/Support/Casting.h"
38
#include "llvm/Support/CommandLine.h"
39
#include "llvm/Support/MathExtras.h"
40
#include "llvm/Support/RISCVAttributes.h"
41
#include "llvm/TargetParser/RISCVISAInfo.h"
42
43
#include <limits>
44
45
using namespace llvm;
46
47
#define DEBUG_TYPE "riscv-asm-parser"
48
49
STATISTIC(RISCVNumInstrsCompressed,
50
"Number of RISC-V Compressed instructions emitted");
51
52
static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
53
cl::init(false));
54
55
namespace llvm {
56
extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
57
} // namespace llvm
58
59
namespace {
60
struct RISCVOperand;
61
62
struct ParserOptionsSet {
63
bool IsPicEnabled;
64
};
65
66
class RISCVAsmParser : public MCTargetAsmParser {
67
// This tracks the parsing of the 4 operands that make up the vtype portion
68
// of vset(i)vli instructions which are separated by commas. The state names
69
// represent the next expected operand with Done meaning no other operands are
70
// expected.
71
enum VTypeState {
72
VTypeState_SEW,
73
VTypeState_LMUL,
74
VTypeState_TailPolicy,
75
VTypeState_MaskPolicy,
76
VTypeState_Done,
77
};
78
79
SmallVector<FeatureBitset, 4> FeatureBitStack;
80
81
SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
82
ParserOptionsSet ParserOptions;
83
84
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
85
bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
86
bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); }
87
bool enableExperimentalExtension() const {
88
return getSTI().hasFeature(RISCV::Experimental);
89
}
90
91
RISCVTargetStreamer &getTargetStreamer() {
92
assert(getParser().getStreamer().getTargetStreamer() &&
93
"do not have a target streamer");
94
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
95
return static_cast<RISCVTargetStreamer &>(TS);
96
}
97
98
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
99
unsigned Kind) override;
100
unsigned checkTargetMatchPredicate(MCInst &Inst) override;
101
102
bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
103
int64_t Lower, int64_t Upper,
104
const Twine &Msg);
105
bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
106
const Twine &Msg);
107
108
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
109
OperandVector &Operands, MCStreamer &Out,
110
uint64_t &ErrorInfo,
111
bool MatchingInlineAsm) override;
112
113
MCRegister matchRegisterNameHelper(StringRef Name) const;
114
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
115
ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
116
SMLoc &EndLoc) override;
117
118
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
119
SMLoc NameLoc, OperandVector &Operands) override;
120
121
ParseStatus parseDirective(AsmToken DirectiveID) override;
122
123
bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew,
124
unsigned &Lmul, bool &Fractional, bool &TailAgnostic,
125
bool &MaskAgnostic);
126
bool generateVTypeError(SMLoc ErrorLoc);
127
128
// Helper to actually emit an instruction to the MCStreamer. Also, when
129
// possible, compression of the instruction is performed.
130
void emitToStreamer(MCStreamer &S, const MCInst &Inst);
131
132
// Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
133
// synthesize the desired immedate value into the destination register.
134
void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
135
136
// Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
137
// helpers such as emitLoadLocalAddress and emitLoadAddress.
138
void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
139
const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
140
unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
141
142
// Helper to emit pseudo instruction "lla" used in PC-rel addressing.
143
void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
144
145
// Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
146
void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147
148
// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
149
void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
150
151
// Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
152
// addressing.
153
void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
154
155
// Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
156
// addressing.
157
void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
158
159
// Helper to emit pseudo load/store instruction with a symbol.
160
void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
161
MCStreamer &Out, bool HasTmpReg);
162
163
// Helper to emit pseudo sign/zero extend instruction.
164
void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
165
SMLoc IDLoc, MCStreamer &Out);
166
167
// Helper to emit pseudo vmsge{u}.vx instruction.
168
void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
169
170
// Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
171
// Enforcing this using a restricted register class for the second input
172
// operand of PseudoAddTPRel results in a poor diagnostic due to the fact
173
// 'add' is an overloaded mnemonic.
174
bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
175
176
// Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
177
// Enforcing this using a restricted register class for the output
178
// operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
179
// 'jalr' is an overloaded mnemonic.
180
bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
181
182
// Check instruction constraints.
183
bool validateInstruction(MCInst &Inst, OperandVector &Operands);
184
185
/// Helper for processing MC instructions that have been successfully matched
186
/// by MatchAndEmitInstruction. Modifications to the emitted instructions,
187
/// like the expansion of pseudo instructions (e.g., "li"), can be performed
188
/// in this method.
189
bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
190
MCStreamer &Out);
191
192
// Auto-generated instruction matching functions
193
#define GET_ASSEMBLER_HEADER
194
#include "RISCVGenAsmMatcher.inc"
195
196
ParseStatus parseCSRSystemRegister(OperandVector &Operands);
197
ParseStatus parseFPImm(OperandVector &Operands);
198
ParseStatus parseImmediate(OperandVector &Operands);
199
ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
200
ParseStatus parseMemOpBaseReg(OperandVector &Operands);
201
ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
202
ParseStatus parseOperandWithModifier(OperandVector &Operands);
203
ParseStatus parseBareSymbol(OperandVector &Operands);
204
ParseStatus parseCallSymbol(OperandVector &Operands);
205
ParseStatus parsePseudoJumpSymbol(OperandVector &Operands);
206
ParseStatus parseJALOffset(OperandVector &Operands);
207
ParseStatus parseVTypeI(OperandVector &Operands);
208
ParseStatus parseMaskReg(OperandVector &Operands);
209
ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands);
210
ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands);
211
ParseStatus parseGPRAsFPR(OperandVector &Operands);
212
template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands);
213
ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
214
ParseStatus parseFRMArg(OperandVector &Operands);
215
ParseStatus parseFenceArg(OperandVector &Operands);
216
ParseStatus parseReglist(OperandVector &Operands);
217
ParseStatus parseRegReg(OperandVector &Operands);
218
ParseStatus parseRetval(OperandVector &Operands);
219
ParseStatus parseZcmpStackAdj(OperandVector &Operands,
220
bool ExpectNegative = false);
221
ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
222
return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
223
}
224
225
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
226
227
bool parseDirectiveOption();
228
bool parseDirectiveAttribute();
229
bool parseDirectiveInsn(SMLoc L);
230
bool parseDirectiveVariantCC();
231
232
/// Helper to reset target features for a new arch string. It
233
/// also records the new arch string that is expanded by RISCVISAInfo
234
/// and reports error for invalid arch string.
235
bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
236
bool FromOptionDirective);
237
238
void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
239
if (!(getSTI().hasFeature(Feature))) {
240
MCSubtargetInfo &STI = copySTI();
241
setAvailableFeatures(
242
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
243
}
244
}
245
246
void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
247
if (getSTI().hasFeature(Feature)) {
248
MCSubtargetInfo &STI = copySTI();
249
setAvailableFeatures(
250
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
251
}
252
}
253
254
void pushFeatureBits() {
255
assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
256
"These two stacks must be kept synchronized");
257
FeatureBitStack.push_back(getSTI().getFeatureBits());
258
ParserOptionsStack.push_back(ParserOptions);
259
}
260
261
bool popFeatureBits() {
262
assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
263
"These two stacks must be kept synchronized");
264
if (FeatureBitStack.empty())
265
return true;
266
267
FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
268
copySTI().setFeatureBits(FeatureBits);
269
setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
270
271
ParserOptions = ParserOptionsStack.pop_back_val();
272
273
return false;
274
}
275
276
std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
277
std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
278
std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const;
279
280
public:
281
enum RISCVMatchResultTy {
282
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
283
Match_RequiresEvenGPRs,
284
#define GET_OPERAND_DIAGNOSTIC_TYPES
285
#include "RISCVGenAsmMatcher.inc"
286
#undef GET_OPERAND_DIAGNOSTIC_TYPES
287
};
288
289
static bool classifySymbolRef(const MCExpr *Expr,
290
RISCVMCExpr::VariantKind &Kind);
291
static bool isSymbolDiff(const MCExpr *Expr);
292
293
RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
294
const MCInstrInfo &MII, const MCTargetOptions &Options)
295
: MCTargetAsmParser(Options, STI, MII) {
296
MCAsmParserExtension::Initialize(Parser);
297
298
Parser.addAliasForDirective(".half", ".2byte");
299
Parser.addAliasForDirective(".hword", ".2byte");
300
Parser.addAliasForDirective(".word", ".4byte");
301
Parser.addAliasForDirective(".dword", ".8byte");
302
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
303
304
auto ABIName = StringRef(Options.ABIName);
305
if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
306
errs() << "Hard-float 'f' ABI can't be used for a target that "
307
"doesn't support the F instruction set extension (ignoring "
308
"target-abi)\n";
309
} else if (ABIName.ends_with("d") &&
310
!getSTI().hasFeature(RISCV::FeatureStdExtD)) {
311
errs() << "Hard-float 'd' ABI can't be used for a target that "
312
"doesn't support the D instruction set extension (ignoring "
313
"target-abi)\n";
314
}
315
316
// Use computeTargetABI to check if ABIName is valid. If invalid, output
317
// error message.
318
RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),
319
ABIName);
320
321
const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
322
ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
323
324
if (AddBuildAttributes)
325
getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
326
}
327
};
328
329
/// RISCVOperand - Instances of this class represent a parsed machine
330
/// instruction
331
struct RISCVOperand final : public MCParsedAsmOperand {
332
333
enum class KindTy {
334
Token,
335
Register,
336
Immediate,
337
FPImmediate,
338
SystemRegister,
339
VType,
340
FRM,
341
Fence,
342
Rlist,
343
Spimm,
344
RegReg,
345
} Kind;
346
347
struct RegOp {
348
MCRegister RegNum;
349
bool IsGPRAsFPR;
350
};
351
352
struct ImmOp {
353
const MCExpr *Val;
354
bool IsRV64;
355
};
356
357
struct FPImmOp {
358
uint64_t Val;
359
};
360
361
struct SysRegOp {
362
const char *Data;
363
unsigned Length;
364
unsigned Encoding;
365
// FIXME: Add the Encoding parsed fields as needed for checks,
366
// e.g.: read/write or user/supervisor/machine privileges.
367
};
368
369
struct VTypeOp {
370
unsigned Val;
371
};
372
373
struct FRMOp {
374
RISCVFPRndMode::RoundingMode FRM;
375
};
376
377
struct FenceOp {
378
unsigned Val;
379
};
380
381
struct RlistOp {
382
unsigned Val;
383
};
384
385
struct SpimmOp {
386
unsigned Val;
387
};
388
389
struct RegRegOp {
390
MCRegister Reg1;
391
MCRegister Reg2;
392
};
393
394
SMLoc StartLoc, EndLoc;
395
union {
396
StringRef Tok;
397
RegOp Reg;
398
ImmOp Imm;
399
FPImmOp FPImm;
400
struct SysRegOp SysReg;
401
struct VTypeOp VType;
402
struct FRMOp FRM;
403
struct FenceOp Fence;
404
struct RlistOp Rlist;
405
struct SpimmOp Spimm;
406
struct RegRegOp RegReg;
407
};
408
409
RISCVOperand(KindTy K) : Kind(K) {}
410
411
public:
412
RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
413
Kind = o.Kind;
414
StartLoc = o.StartLoc;
415
EndLoc = o.EndLoc;
416
switch (Kind) {
417
case KindTy::Register:
418
Reg = o.Reg;
419
break;
420
case KindTy::Immediate:
421
Imm = o.Imm;
422
break;
423
case KindTy::FPImmediate:
424
FPImm = o.FPImm;
425
break;
426
case KindTy::Token:
427
Tok = o.Tok;
428
break;
429
case KindTy::SystemRegister:
430
SysReg = o.SysReg;
431
break;
432
case KindTy::VType:
433
VType = o.VType;
434
break;
435
case KindTy::FRM:
436
FRM = o.FRM;
437
break;
438
case KindTy::Fence:
439
Fence = o.Fence;
440
break;
441
case KindTy::Rlist:
442
Rlist = o.Rlist;
443
break;
444
case KindTy::Spimm:
445
Spimm = o.Spimm;
446
break;
447
case KindTy::RegReg:
448
RegReg = o.RegReg;
449
break;
450
}
451
}
452
453
bool isToken() const override { return Kind == KindTy::Token; }
454
bool isReg() const override { return Kind == KindTy::Register; }
455
bool isV0Reg() const {
456
return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
457
}
458
bool isAnyReg() const {
459
return Kind == KindTy::Register &&
460
(RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
461
RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
462
RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
463
}
464
bool isAnyRegC() const {
465
return Kind == KindTy::Register &&
466
(RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
467
Reg.RegNum) ||
468
RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
469
Reg.RegNum));
470
}
471
bool isImm() const override { return Kind == KindTy::Immediate; }
472
bool isMem() const override { return false; }
473
bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
474
bool isRegReg() const { return Kind == KindTy::RegReg; }
475
bool isRlist() const { return Kind == KindTy::Rlist; }
476
bool isSpimm() const { return Kind == KindTy::Spimm; }
477
478
bool isGPR() const {
479
return Kind == KindTy::Register &&
480
RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
481
}
482
483
bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
484
485
bool isGPRPair() const {
486
return Kind == KindTy::Register &&
487
RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
488
Reg.RegNum);
489
}
490
491
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
492
RISCVMCExpr::VariantKind &VK) {
493
if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
494
VK = RE->getKind();
495
return RE->evaluateAsConstant(Imm);
496
}
497
498
if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
499
VK = RISCVMCExpr::VK_RISCV_None;
500
Imm = CE->getValue();
501
return true;
502
}
503
504
return false;
505
}
506
507
// True if operand is a symbol with no modifiers, or a constant with no
508
// modifiers and isShiftedInt<N-1, 1>(Op).
509
template <int N> bool isBareSimmNLsb0() const {
510
int64_t Imm;
511
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
512
if (!isImm())
513
return false;
514
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
515
bool IsValid;
516
if (!IsConstantImm)
517
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
518
else
519
IsValid = isShiftedInt<N - 1, 1>(Imm);
520
return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
521
}
522
523
// Predicate methods for AsmOperands defined in RISCVInstrInfo.td
524
525
bool isBareSymbol() const {
526
int64_t Imm;
527
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
528
// Must be of 'immediate' type but not a constant.
529
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
530
return false;
531
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
532
VK == RISCVMCExpr::VK_RISCV_None;
533
}
534
535
bool isCallSymbol() const {
536
int64_t Imm;
537
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
538
// Must be of 'immediate' type but not a constant.
539
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
540
return false;
541
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
542
(VK == RISCVMCExpr::VK_RISCV_CALL ||
543
VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
544
}
545
546
bool isPseudoJumpSymbol() const {
547
int64_t Imm;
548
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
549
// Must be of 'immediate' type but not a constant.
550
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
551
return false;
552
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
553
VK == RISCVMCExpr::VK_RISCV_CALL;
554
}
555
556
bool isTPRelAddSymbol() const {
557
int64_t Imm;
558
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
559
// Must be of 'immediate' type but not a constant.
560
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
561
return false;
562
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
563
VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
564
}
565
566
bool isTLSDESCCallSymbol() const {
567
int64_t Imm;
568
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
569
// Must be of 'immediate' type but not a constant.
570
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
571
return false;
572
return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
573
VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;
574
}
575
576
bool isCSRSystemRegister() const { return isSystemRegister(); }
577
578
bool isVTypeImm(unsigned N) const {
579
int64_t Imm;
580
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
581
if (!isImm())
582
return false;
583
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
584
return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
585
}
586
587
// If the last operand of the vsetvli/vsetvli instruction is a constant
588
// expression, KindTy is Immediate.
589
bool isVTypeI10() const {
590
if (Kind == KindTy::Immediate)
591
return isVTypeImm(10);
592
return Kind == KindTy::VType;
593
}
594
bool isVTypeI11() const {
595
if (Kind == KindTy::Immediate)
596
return isVTypeImm(11);
597
return Kind == KindTy::VType;
598
}
599
600
/// Return true if the operand is a valid for the fence instruction e.g.
601
/// ('iorw').
602
bool isFenceArg() const { return Kind == KindTy::Fence; }
603
604
/// Return true if the operand is a valid floating point rounding mode.
605
bool isFRMArg() const { return Kind == KindTy::FRM; }
606
bool isFRMArgLegacy() const { return Kind == KindTy::FRM; }
607
bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
608
609
/// Return true if the operand is a valid fli.s floating-point immediate.
610
bool isLoadFPImm() const {
611
if (isImm())
612
return isUImm5();
613
if (Kind != KindTy::FPImmediate)
614
return false;
615
int Idx = RISCVLoadFPImm::getLoadFPImm(
616
APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
617
// Don't allow decimal version of the minimum value. It is a different value
618
// for each supported data type.
619
return Idx >= 0 && Idx != 1;
620
}
621
622
bool isImmXLenLI() const {
623
int64_t Imm;
624
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
625
if (!isImm())
626
return false;
627
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
628
if (VK == RISCVMCExpr::VK_RISCV_LO ||
629
VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
630
VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
631
VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)
632
return true;
633
// Given only Imm, ensuring that the actually specified constant is either
634
// a signed or unsigned 64-bit number is unfortunately impossible.
635
if (IsConstantImm) {
636
return VK == RISCVMCExpr::VK_RISCV_None &&
637
(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
638
}
639
640
return RISCVAsmParser::isSymbolDiff(getImm());
641
}
642
643
bool isImmXLenLI_Restricted() const {
644
int64_t Imm;
645
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
646
if (!isImm())
647
return false;
648
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
649
// 'la imm' supports constant immediates only.
650
return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
651
(isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
652
}
653
654
bool isUImmLog2XLen() const {
655
int64_t Imm;
656
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
657
if (!isImm())
658
return false;
659
if (!evaluateConstantImm(getImm(), Imm, VK) ||
660
VK != RISCVMCExpr::VK_RISCV_None)
661
return false;
662
return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
663
}
664
665
bool isUImmLog2XLenNonZero() const {
666
int64_t Imm;
667
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
668
if (!isImm())
669
return false;
670
if (!evaluateConstantImm(getImm(), Imm, VK) ||
671
VK != RISCVMCExpr::VK_RISCV_None)
672
return false;
673
if (Imm == 0)
674
return false;
675
return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
676
}
677
678
bool isUImmLog2XLenHalf() const {
679
int64_t Imm;
680
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
681
if (!isImm())
682
return false;
683
if (!evaluateConstantImm(getImm(), Imm, VK) ||
684
VK != RISCVMCExpr::VK_RISCV_None)
685
return false;
686
return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
687
}
688
689
template <unsigned N> bool IsUImm() const {
690
int64_t Imm;
691
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
692
if (!isImm())
693
return false;
694
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
695
return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
696
}
697
698
bool isUImm1() const { return IsUImm<1>(); }
699
bool isUImm2() const { return IsUImm<2>(); }
700
bool isUImm3() const { return IsUImm<3>(); }
701
bool isUImm4() const { return IsUImm<4>(); }
702
bool isUImm5() const { return IsUImm<5>(); }
703
bool isUImm6() const { return IsUImm<6>(); }
704
bool isUImm7() const { return IsUImm<7>(); }
705
bool isUImm8() const { return IsUImm<8>(); }
706
bool isUImm16() const { return IsUImm<16>(); }
707
bool isUImm20() const { return IsUImm<20>(); }
708
bool isUImm32() const { return IsUImm<32>(); }
709
710
bool isUImm8GE32() const {
711
int64_t Imm;
712
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
713
if (!isImm())
714
return false;
715
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
716
return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
717
VK == RISCVMCExpr::VK_RISCV_None;
718
}
719
720
bool isRnumArg() const {
721
int64_t Imm;
722
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
723
if (!isImm())
724
return false;
725
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
726
return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
727
VK == RISCVMCExpr::VK_RISCV_None;
728
}
729
730
bool isRnumArg_0_7() const {
731
int64_t Imm;
732
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
733
if (!isImm())
734
return false;
735
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
736
return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) &&
737
VK == RISCVMCExpr::VK_RISCV_None;
738
}
739
740
bool isRnumArg_1_10() const {
741
int64_t Imm;
742
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
743
if (!isImm())
744
return false;
745
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
746
return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) &&
747
VK == RISCVMCExpr::VK_RISCV_None;
748
}
749
750
bool isRnumArg_2_14() const {
751
int64_t Imm;
752
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
753
if (!isImm())
754
return false;
755
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
756
return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) &&
757
VK == RISCVMCExpr::VK_RISCV_None;
758
}
759
760
bool isSImm5() const {
761
if (!isImm())
762
return false;
763
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
764
int64_t Imm;
765
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
766
return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
767
VK == RISCVMCExpr::VK_RISCV_None;
768
}
769
770
bool isSImm6() const {
771
if (!isImm())
772
return false;
773
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
774
int64_t Imm;
775
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
776
return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
777
VK == RISCVMCExpr::VK_RISCV_None;
778
}
779
780
bool isSImm6NonZero() const {
781
if (!isImm())
782
return false;
783
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
784
int64_t Imm;
785
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
786
return IsConstantImm && Imm != 0 &&
787
isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
788
VK == RISCVMCExpr::VK_RISCV_None;
789
}
790
791
bool isCLUIImm() const {
792
if (!isImm())
793
return false;
794
int64_t Imm;
795
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
796
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
797
return IsConstantImm && (Imm != 0) &&
798
(isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
799
VK == RISCVMCExpr::VK_RISCV_None;
800
}
801
802
bool isUImm2Lsb0() const {
803
if (!isImm())
804
return false;
805
int64_t Imm;
806
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
807
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
808
return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
809
VK == RISCVMCExpr::VK_RISCV_None;
810
}
811
812
bool isUImm5Lsb0() const {
813
if (!isImm())
814
return false;
815
int64_t Imm;
816
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
817
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
818
return IsConstantImm && isShiftedUInt<4, 1>(Imm) &&
819
VK == RISCVMCExpr::VK_RISCV_None;
820
}
821
822
bool isUImm6Lsb0() const {
823
if (!isImm())
824
return false;
825
int64_t Imm;
826
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
827
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
828
return IsConstantImm && isShiftedUInt<5, 1>(Imm) &&
829
VK == RISCVMCExpr::VK_RISCV_None;
830
}
831
832
bool isUImm7Lsb00() const {
833
if (!isImm())
834
return false;
835
int64_t Imm;
836
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
837
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
838
return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
839
VK == RISCVMCExpr::VK_RISCV_None;
840
}
841
842
bool isUImm8Lsb00() const {
843
if (!isImm())
844
return false;
845
int64_t Imm;
846
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
847
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
848
return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
849
VK == RISCVMCExpr::VK_RISCV_None;
850
}
851
852
bool isUImm8Lsb000() const {
853
if (!isImm())
854
return false;
855
int64_t Imm;
856
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
857
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
858
return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
859
VK == RISCVMCExpr::VK_RISCV_None;
860
}
861
862
bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
863
864
bool isUImm9Lsb000() const {
865
if (!isImm())
866
return false;
867
int64_t Imm;
868
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
869
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
870
return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
871
VK == RISCVMCExpr::VK_RISCV_None;
872
}
873
874
bool isUImm10Lsb00NonZero() const {
875
if (!isImm())
876
return false;
877
int64_t Imm;
878
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
879
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
880
return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
881
VK == RISCVMCExpr::VK_RISCV_None;
882
}
883
884
// If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
885
// This allows writing 'addi a0, a0, 0xffffffff'.
886
static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
887
if (IsRV64Imm || !isUInt<32>(Imm))
888
return Imm;
889
return SignExtend64<32>(Imm);
890
}
891
892
bool isSImm12() const {
893
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
894
int64_t Imm;
895
bool IsValid;
896
if (!isImm())
897
return false;
898
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
899
if (!IsConstantImm)
900
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
901
else
902
IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
903
return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
904
VK == RISCVMCExpr::VK_RISCV_LO ||
905
VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
906
VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||
907
VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
908
VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);
909
}
910
911
bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
912
913
bool isSImm12Lsb00000() const {
914
if (!isImm())
915
return false;
916
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
917
int64_t Imm;
918
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
919
return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
920
VK == RISCVMCExpr::VK_RISCV_None;
921
}
922
923
bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
924
925
bool isSImm10Lsb0000NonZero() const {
926
if (!isImm())
927
return false;
928
int64_t Imm;
929
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
930
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
931
return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
932
VK == RISCVMCExpr::VK_RISCV_None;
933
}
934
935
bool isUImm20LUI() const {
936
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
937
int64_t Imm;
938
bool IsValid;
939
if (!isImm())
940
return false;
941
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
942
if (!IsConstantImm) {
943
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
944
return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
945
VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
946
} else {
947
return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
948
VK == RISCVMCExpr::VK_RISCV_HI ||
949
VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
950
}
951
}
952
953
bool isUImm20AUIPC() const {
954
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
955
int64_t Imm;
956
bool IsValid;
957
if (!isImm())
958
return false;
959
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
960
if (!IsConstantImm) {
961
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
962
return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
963
VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
964
VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
965
VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
966
VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
967
}
968
969
return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
970
VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
971
VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
972
VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
973
VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
974
VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
975
}
976
977
bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
978
979
bool isImmZero() const {
980
if (!isImm())
981
return false;
982
int64_t Imm;
983
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
984
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
985
return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
986
}
987
988
bool isSImm5Plus1() const {
989
if (!isImm())
990
return false;
991
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
992
int64_t Imm;
993
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
994
return IsConstantImm &&
995
isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
996
VK == RISCVMCExpr::VK_RISCV_None;
997
}
998
999
/// getStartLoc - Gets location of the first token of this operand
1000
SMLoc getStartLoc() const override { return StartLoc; }
1001
/// getEndLoc - Gets location of the last token of this operand
1002
SMLoc getEndLoc() const override { return EndLoc; }
1003
/// True if this operand is for an RV64 instruction
1004
bool isRV64Imm() const {
1005
assert(Kind == KindTy::Immediate && "Invalid type access!");
1006
return Imm.IsRV64;
1007
}
1008
1009
MCRegister getReg() const override {
1010
assert(Kind == KindTy::Register && "Invalid type access!");
1011
return Reg.RegNum;
1012
}
1013
1014
StringRef getSysReg() const {
1015
assert(Kind == KindTy::SystemRegister && "Invalid type access!");
1016
return StringRef(SysReg.Data, SysReg.Length);
1017
}
1018
1019
const MCExpr *getImm() const {
1020
assert(Kind == KindTy::Immediate && "Invalid type access!");
1021
return Imm.Val;
1022
}
1023
1024
uint64_t getFPConst() const {
1025
assert(Kind == KindTy::FPImmediate && "Invalid type access!");
1026
return FPImm.Val;
1027
}
1028
1029
StringRef getToken() const {
1030
assert(Kind == KindTy::Token && "Invalid type access!");
1031
return Tok;
1032
}
1033
1034
unsigned getVType() const {
1035
assert(Kind == KindTy::VType && "Invalid type access!");
1036
return VType.Val;
1037
}
1038
1039
RISCVFPRndMode::RoundingMode getFRM() const {
1040
assert(Kind == KindTy::FRM && "Invalid type access!");
1041
return FRM.FRM;
1042
}
1043
1044
unsigned getFence() const {
1045
assert(Kind == KindTy::Fence && "Invalid type access!");
1046
return Fence.Val;
1047
}
1048
1049
void print(raw_ostream &OS) const override {
1050
auto RegName = [](MCRegister Reg) {
1051
if (Reg)
1052
return RISCVInstPrinter::getRegisterName(Reg);
1053
else
1054
return "noreg";
1055
};
1056
1057
switch (Kind) {
1058
case KindTy::Immediate:
1059
OS << *getImm();
1060
break;
1061
case KindTy::FPImmediate:
1062
break;
1063
case KindTy::Register:
1064
OS << "<register " << RegName(getReg()) << ">";
1065
break;
1066
case KindTy::Token:
1067
OS << "'" << getToken() << "'";
1068
break;
1069
case KindTy::SystemRegister:
1070
OS << "<sysreg: " << getSysReg() << '>';
1071
break;
1072
case KindTy::VType:
1073
OS << "<vtype: ";
1074
RISCVVType::printVType(getVType(), OS);
1075
OS << '>';
1076
break;
1077
case KindTy::FRM:
1078
OS << "<frm: ";
1079
roundingModeToString(getFRM());
1080
OS << '>';
1081
break;
1082
case KindTy::Fence:
1083
OS << "<fence: ";
1084
OS << getFence();
1085
OS << '>';
1086
break;
1087
case KindTy::Rlist:
1088
OS << "<rlist: ";
1089
RISCVZC::printRlist(Rlist.Val, OS);
1090
OS << '>';
1091
break;
1092
case KindTy::Spimm:
1093
OS << "<Spimm: ";
1094
OS << Spimm.Val;
1095
OS << '>';
1096
break;
1097
case KindTy::RegReg:
1098
OS << "<RegReg: Reg1 " << RegName(RegReg.Reg1);
1099
OS << " Reg2 " << RegName(RegReg.Reg2);
1100
break;
1101
}
1102
}
1103
1104
static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
1105
auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
1106
Op->Tok = Str;
1107
Op->StartLoc = S;
1108
Op->EndLoc = S;
1109
return Op;
1110
}
1111
1112
static std::unique_ptr<RISCVOperand>
1113
createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
1114
auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
1115
Op->Reg.RegNum = RegNo;
1116
Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1117
Op->StartLoc = S;
1118
Op->EndLoc = E;
1119
return Op;
1120
}
1121
1122
static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
1123
SMLoc E, bool IsRV64) {
1124
auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1125
Op->Imm.Val = Val;
1126
Op->Imm.IsRV64 = IsRV64;
1127
Op->StartLoc = S;
1128
Op->EndLoc = E;
1129
return Op;
1130
}
1131
1132
static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1133
auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1134
Op->FPImm.Val = Val;
1135
Op->StartLoc = S;
1136
Op->EndLoc = S;
1137
return Op;
1138
}
1139
1140
static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1141
unsigned Encoding) {
1142
auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1143
Op->SysReg.Data = Str.data();
1144
Op->SysReg.Length = Str.size();
1145
Op->SysReg.Encoding = Encoding;
1146
Op->StartLoc = S;
1147
Op->EndLoc = S;
1148
return Op;
1149
}
1150
1151
static std::unique_ptr<RISCVOperand>
1152
createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1153
auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1154
Op->FRM.FRM = FRM;
1155
Op->StartLoc = S;
1156
Op->EndLoc = S;
1157
return Op;
1158
}
1159
1160
static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1161
auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1162
Op->Fence.Val = Val;
1163
Op->StartLoc = S;
1164
Op->EndLoc = S;
1165
return Op;
1166
}
1167
1168
static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1169
auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1170
Op->VType.Val = VTypeI;
1171
Op->StartLoc = S;
1172
Op->EndLoc = S;
1173
return Op;
1174
}
1175
1176
static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
1177
SMLoc S) {
1178
auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1179
Op->Rlist.Val = RlistEncode;
1180
Op->StartLoc = S;
1181
return Op;
1182
}
1183
1184
static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No,
1185
unsigned Reg2No, SMLoc S) {
1186
auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
1187
Op->RegReg.Reg1 = Reg1No;
1188
Op->RegReg.Reg2 = Reg2No;
1189
Op->StartLoc = S;
1190
Op->EndLoc = S;
1191
return Op;
1192
}
1193
1194
static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
1195
auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1196
Op->Spimm.Val = Spimm;
1197
Op->StartLoc = S;
1198
return Op;
1199
}
1200
1201
static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1202
assert(Expr && "Expr shouldn't be null!");
1203
int64_t Imm = 0;
1204
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1205
bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1206
1207
if (IsConstant)
1208
Inst.addOperand(
1209
MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
1210
else
1211
Inst.addOperand(MCOperand::createExpr(Expr));
1212
}
1213
1214
// Used by the TableGen Code
1215
void addRegOperands(MCInst &Inst, unsigned N) const {
1216
assert(N == 1 && "Invalid number of operands!");
1217
Inst.addOperand(MCOperand::createReg(getReg()));
1218
}
1219
1220
void addImmOperands(MCInst &Inst, unsigned N) const {
1221
assert(N == 1 && "Invalid number of operands!");
1222
addExpr(Inst, getImm(), isRV64Imm());
1223
}
1224
1225
void addFPImmOperands(MCInst &Inst, unsigned N) const {
1226
assert(N == 1 && "Invalid number of operands!");
1227
if (isImm()) {
1228
addExpr(Inst, getImm(), isRV64Imm());
1229
return;
1230
}
1231
1232
int Imm = RISCVLoadFPImm::getLoadFPImm(
1233
APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1234
Inst.addOperand(MCOperand::createImm(Imm));
1235
}
1236
1237
void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1238
assert(N == 1 && "Invalid number of operands!");
1239
Inst.addOperand(MCOperand::createImm(Fence.Val));
1240
}
1241
1242
void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1243
assert(N == 1 && "Invalid number of operands!");
1244
Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
1245
}
1246
1247
// Support non-canonical syntax:
1248
// "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1249
// "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1250
void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1251
assert(N == 1 && "Invalid number of operands!");
1252
int64_t Imm = 0;
1253
if (Kind == KindTy::Immediate) {
1254
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1255
[[maybe_unused]] bool IsConstantImm =
1256
evaluateConstantImm(getImm(), Imm, VK);
1257
assert(IsConstantImm && "Invalid VTypeI Operand!");
1258
} else {
1259
Imm = getVType();
1260
}
1261
Inst.addOperand(MCOperand::createImm(Imm));
1262
}
1263
1264
void addRlistOperands(MCInst &Inst, unsigned N) const {
1265
assert(N == 1 && "Invalid number of operands!");
1266
Inst.addOperand(MCOperand::createImm(Rlist.Val));
1267
}
1268
1269
void addRegRegOperands(MCInst &Inst, unsigned N) const {
1270
assert(N == 2 && "Invalid number of operands!");
1271
Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
1272
Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
1273
}
1274
1275
void addSpimmOperands(MCInst &Inst, unsigned N) const {
1276
assert(N == 1 && "Invalid number of operands!");
1277
Inst.addOperand(MCOperand::createImm(Spimm.Val));
1278
}
1279
1280
void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1281
assert(N == 1 && "Invalid number of operands!");
1282
Inst.addOperand(MCOperand::createImm(getFRM()));
1283
}
1284
};
1285
} // end anonymous namespace.
1286
1287
#define GET_REGISTER_MATCHER
1288
#define GET_SUBTARGET_FEATURE_NAME
1289
#define GET_MATCHER_IMPLEMENTATION
1290
#define GET_MNEMONIC_SPELL_CHECKER
1291
#include "RISCVGenAsmMatcher.inc"
1292
1293
static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1294
assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1295
return Reg - RISCV::F0_D + RISCV::F0_H;
1296
}
1297
1298
static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
1299
assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
1300
return Reg - RISCV::F0_D + RISCV::F0_F;
1301
}
1302
1303
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1304
unsigned Kind) {
1305
unsigned RegClassID;
1306
if (Kind == MCK_VRM2)
1307
RegClassID = RISCV::VRM2RegClassID;
1308
else if (Kind == MCK_VRM4)
1309
RegClassID = RISCV::VRM4RegClassID;
1310
else if (Kind == MCK_VRM8)
1311
RegClassID = RISCV::VRM8RegClassID;
1312
else
1313
return 0;
1314
return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1315
&RISCVMCRegisterClasses[RegClassID]);
1316
}
1317
1318
unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1319
unsigned Kind) {
1320
RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1321
if (!Op.isReg())
1322
return Match_InvalidOperand;
1323
1324
MCRegister Reg = Op.getReg();
1325
bool IsRegFPR64 =
1326
RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1327
bool IsRegFPR64C =
1328
RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1329
bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1330
1331
// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1332
// register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1333
if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1334
(IsRegFPR64C && Kind == MCK_FPR32C)) {
1335
Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1336
return Match_Success;
1337
}
1338
// As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1339
// register from FPR64 to FPR16 if necessary.
1340
if (IsRegFPR64 && Kind == MCK_FPR16) {
1341
Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1342
return Match_Success;
1343
}
1344
// As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1345
// the register from VR to VRM2/VRM4/VRM8 if necessary.
1346
if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1347
Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1348
if (Op.Reg.RegNum == 0)
1349
return Match_InvalidOperand;
1350
return Match_Success;
1351
}
1352
return Match_InvalidOperand;
1353
}
1354
1355
unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1356
const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
1357
1358
for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1359
if (MCID.operands()[I].RegClass == RISCV::GPRPairRegClassID) {
1360
const auto &Op = Inst.getOperand(I);
1361
assert(Op.isReg());
1362
1363
MCRegister Reg = Op.getReg();
1364
if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg))
1365
continue;
1366
1367
// FIXME: We should form a paired register during parsing/matching.
1368
if (((Reg.id() - RISCV::X0) & 1) != 0)
1369
return Match_RequiresEvenGPRs;
1370
}
1371
}
1372
1373
return Match_Success;
1374
}
1375
1376
bool RISCVAsmParser::generateImmOutOfRangeError(
1377
SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1378
const Twine &Msg = "immediate must be an integer in the range") {
1379
return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1380
}
1381
1382
bool RISCVAsmParser::generateImmOutOfRangeError(
1383
OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1384
const Twine &Msg = "immediate must be an integer in the range") {
1385
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1386
return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
1387
}
1388
1389
bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1390
OperandVector &Operands,
1391
MCStreamer &Out,
1392
uint64_t &ErrorInfo,
1393
bool MatchingInlineAsm) {
1394
MCInst Inst;
1395
FeatureBitset MissingFeatures;
1396
1397
auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1398
MatchingInlineAsm);
1399
switch (Result) {
1400
default:
1401
break;
1402
case Match_Success:
1403
if (validateInstruction(Inst, Operands))
1404
return true;
1405
return processInstruction(Inst, IDLoc, Operands, Out);
1406
case Match_MissingFeature: {
1407
assert(MissingFeatures.any() && "Unknown missing features!");
1408
bool FirstFeature = true;
1409
std::string Msg = "instruction requires the following:";
1410
for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1411
if (MissingFeatures[i]) {
1412
Msg += FirstFeature ? " " : ", ";
1413
Msg += getSubtargetFeatureName(i);
1414
FirstFeature = false;
1415
}
1416
}
1417
return Error(IDLoc, Msg);
1418
}
1419
case Match_MnemonicFail: {
1420
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1421
std::string Suggestion = RISCVMnemonicSpellCheck(
1422
((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1423
return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1424
}
1425
case Match_InvalidOperand: {
1426
SMLoc ErrorLoc = IDLoc;
1427
if (ErrorInfo != ~0ULL) {
1428
if (ErrorInfo >= Operands.size())
1429
return Error(ErrorLoc, "too few operands for instruction");
1430
1431
ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1432
if (ErrorLoc == SMLoc())
1433
ErrorLoc = IDLoc;
1434
}
1435
return Error(ErrorLoc, "invalid operand for instruction");
1436
}
1437
}
1438
1439
// Handle the case when the error message is of specific type
1440
// other than the generic Match_InvalidOperand, and the
1441
// corresponding operand is missing.
1442
if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1443
SMLoc ErrorLoc = IDLoc;
1444
if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1445
return Error(ErrorLoc, "too few operands for instruction");
1446
}
1447
1448
switch (Result) {
1449
default:
1450
break;
1451
case Match_RequiresEvenGPRs:
1452
return Error(IDLoc,
1453
"double precision floating point operands must use even "
1454
"numbered X register");
1455
case Match_InvalidImmXLenLI:
1456
if (isRV64()) {
1457
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1458
return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1459
}
1460
return generateImmOutOfRangeError(Operands, ErrorInfo,
1461
std::numeric_limits<int32_t>::min(),
1462
std::numeric_limits<uint32_t>::max());
1463
case Match_InvalidImmXLenLI_Restricted:
1464
if (isRV64()) {
1465
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1466
return Error(ErrorLoc, "operand either must be a constant 64-bit integer "
1467
"or a bare symbol name");
1468
}
1469
return generateImmOutOfRangeError(
1470
Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
1471
std::numeric_limits<uint32_t>::max(),
1472
"operand either must be a bare symbol name or an immediate integer in "
1473
"the range");
1474
case Match_InvalidImmZero: {
1475
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1476
return Error(ErrorLoc, "immediate must be zero");
1477
}
1478
case Match_InvalidUImmLog2XLen:
1479
if (isRV64())
1480
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1481
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1482
case Match_InvalidUImmLog2XLenNonZero:
1483
if (isRV64())
1484
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1485
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1486
case Match_InvalidUImmLog2XLenHalf:
1487
if (isRV64())
1488
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1489
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1490
case Match_InvalidUImm1:
1491
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1492
case Match_InvalidUImm2:
1493
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1494
case Match_InvalidUImm2Lsb0:
1495
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1496
"immediate must be one of");
1497
case Match_InvalidUImm3:
1498
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1499
case Match_InvalidUImm4:
1500
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1501
case Match_InvalidUImm5:
1502
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1503
case Match_InvalidUImm6:
1504
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1505
case Match_InvalidUImm7:
1506
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1507
case Match_InvalidUImm8:
1508
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
1509
case Match_InvalidUImm8GE32:
1510
return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1511
case Match_InvalidSImm5:
1512
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1513
(1 << 4) - 1);
1514
case Match_InvalidSImm6:
1515
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1516
(1 << 5) - 1);
1517
case Match_InvalidSImm6NonZero:
1518
return generateImmOutOfRangeError(
1519
Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1520
"immediate must be non-zero in the range");
1521
case Match_InvalidCLUIImm:
1522
return generateImmOutOfRangeError(
1523
Operands, ErrorInfo, 1, (1 << 5) - 1,
1524
"immediate must be in [0xfffe0, 0xfffff] or");
1525
case Match_InvalidUImm5Lsb0:
1526
return generateImmOutOfRangeError(
1527
Operands, ErrorInfo, 0, (1 << 5) - 2,
1528
"immediate must be a multiple of 2 bytes in the range");
1529
case Match_InvalidUImm6Lsb0:
1530
return generateImmOutOfRangeError(
1531
Operands, ErrorInfo, 0, (1 << 6) - 2,
1532
"immediate must be a multiple of 2 bytes in the range");
1533
case Match_InvalidUImm7Lsb00:
1534
return generateImmOutOfRangeError(
1535
Operands, ErrorInfo, 0, (1 << 7) - 4,
1536
"immediate must be a multiple of 4 bytes in the range");
1537
case Match_InvalidUImm8Lsb00:
1538
return generateImmOutOfRangeError(
1539
Operands, ErrorInfo, 0, (1 << 8) - 4,
1540
"immediate must be a multiple of 4 bytes in the range");
1541
case Match_InvalidUImm8Lsb000:
1542
return generateImmOutOfRangeError(
1543
Operands, ErrorInfo, 0, (1 << 8) - 8,
1544
"immediate must be a multiple of 8 bytes in the range");
1545
case Match_InvalidSImm9Lsb0:
1546
return generateImmOutOfRangeError(
1547
Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1548
"immediate must be a multiple of 2 bytes in the range");
1549
case Match_InvalidUImm9Lsb000:
1550
return generateImmOutOfRangeError(
1551
Operands, ErrorInfo, 0, (1 << 9) - 8,
1552
"immediate must be a multiple of 8 bytes in the range");
1553
case Match_InvalidUImm10Lsb00NonZero:
1554
return generateImmOutOfRangeError(
1555
Operands, ErrorInfo, 4, (1 << 10) - 4,
1556
"immediate must be a multiple of 4 bytes in the range");
1557
case Match_InvalidSImm10Lsb0000NonZero:
1558
return generateImmOutOfRangeError(
1559
Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1560
"immediate must be a multiple of 16 bytes and non-zero in the range");
1561
case Match_InvalidSImm12:
1562
return generateImmOutOfRangeError(
1563
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1564
"operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1565
"integer in the range");
1566
case Match_InvalidSImm12Lsb0:
1567
return generateImmOutOfRangeError(
1568
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1569
"immediate must be a multiple of 2 bytes in the range");
1570
case Match_InvalidSImm12Lsb00000:
1571
return generateImmOutOfRangeError(
1572
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1573
"immediate must be a multiple of 32 bytes in the range");
1574
case Match_InvalidSImm13Lsb0:
1575
return generateImmOutOfRangeError(
1576
Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1577
"immediate must be a multiple of 2 bytes in the range");
1578
case Match_InvalidUImm20LUI:
1579
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1580
"operand must be a symbol with "
1581
"%hi/%tprel_hi modifier or an integer in "
1582
"the range");
1583
case Match_InvalidUImm20:
1584
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
1585
case Match_InvalidUImm20AUIPC:
1586
return generateImmOutOfRangeError(
1587
Operands, ErrorInfo, 0, (1 << 20) - 1,
1588
"operand must be a symbol with a "
1589
"%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1590
"an integer in the range");
1591
case Match_InvalidSImm21Lsb0JAL:
1592
return generateImmOutOfRangeError(
1593
Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1594
"immediate must be a multiple of 2 bytes in the range");
1595
case Match_InvalidCSRSystemRegister: {
1596
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1597
"operand must be a valid system register "
1598
"name or an integer in the range");
1599
}
1600
case Match_InvalidLoadFPImm: {
1601
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1602
return Error(ErrorLoc, "operand must be a valid floating-point constant");
1603
}
1604
case Match_InvalidBareSymbol: {
1605
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1606
return Error(ErrorLoc, "operand must be a bare symbol name");
1607
}
1608
case Match_InvalidPseudoJumpSymbol: {
1609
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1610
return Error(ErrorLoc, "operand must be a valid jump target");
1611
}
1612
case Match_InvalidCallSymbol: {
1613
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1614
return Error(ErrorLoc, "operand must be a bare symbol name");
1615
}
1616
case Match_InvalidTPRelAddSymbol: {
1617
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1618
return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1619
}
1620
case Match_InvalidTLSDESCCallSymbol: {
1621
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1622
return Error(ErrorLoc,
1623
"operand must be a symbol with %tlsdesc_call modifier");
1624
}
1625
case Match_InvalidRTZArg: {
1626
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1627
return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
1628
}
1629
case Match_InvalidVTypeI: {
1630
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1631
return generateVTypeError(ErrorLoc);
1632
}
1633
case Match_InvalidVMaskRegister: {
1634
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1635
return Error(ErrorLoc, "operand must be v0.t");
1636
}
1637
case Match_InvalidSImm5Plus1: {
1638
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1639
(1 << 4),
1640
"immediate must be in the range");
1641
}
1642
case Match_InvalidRlist: {
1643
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1644
return Error(
1645
ErrorLoc,
1646
"operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1647
}
1648
case Match_InvalidStackAdj: {
1649
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1650
return Error(
1651
ErrorLoc,
1652
"stack adjustment is invalid for this instruction and register list; "
1653
"refer to Zc spec for a detailed range of stack adjustment");
1654
}
1655
case Match_InvalidRnumArg: {
1656
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1657
}
1658
case Match_InvalidRegReg: {
1659
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1660
return Error(ErrorLoc, "operands must be register and register");
1661
}
1662
}
1663
1664
llvm_unreachable("Unknown match type detected!");
1665
}
1666
1667
// Attempts to match Name as a register (either using the default name or
1668
// alternative ABI names), setting RegNo to the matching register. Upon
1669
// failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1670
// will be rejected.
1671
MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1672
MCRegister Reg = MatchRegisterName(Name);
1673
// The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1674
// match always matches the 64-bit variant, and not the 16/32-bit one.
1675
assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1676
assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1677
// The default FPR register class is based on the tablegen enum ordering.
1678
static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1679
static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1680
if (!Reg)
1681
Reg = MatchRegisterAltName(Name);
1682
if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1683
Reg = RISCV::NoRegister;
1684
return Reg;
1685
}
1686
1687
bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1688
SMLoc &EndLoc) {
1689
if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1690
return Error(StartLoc, "invalid register name");
1691
return false;
1692
}
1693
1694
ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1695
SMLoc &EndLoc) {
1696
const AsmToken &Tok = getParser().getTok();
1697
StartLoc = Tok.getLoc();
1698
EndLoc = Tok.getEndLoc();
1699
StringRef Name = getLexer().getTok().getIdentifier();
1700
1701
Reg = matchRegisterNameHelper(Name);
1702
if (!Reg)
1703
return ParseStatus::NoMatch;
1704
1705
getParser().Lex(); // Eat identifier token.
1706
return ParseStatus::Success;
1707
}
1708
1709
ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1710
bool AllowParens) {
1711
SMLoc FirstS = getLoc();
1712
bool HadParens = false;
1713
AsmToken LParen;
1714
1715
// If this is an LParen and a parenthesised register name is allowed, parse it
1716
// atomically.
1717
if (AllowParens && getLexer().is(AsmToken::LParen)) {
1718
AsmToken Buf[2];
1719
size_t ReadCount = getLexer().peekTokens(Buf);
1720
if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1721
HadParens = true;
1722
LParen = getParser().getTok();
1723
getParser().Lex(); // Eat '('
1724
}
1725
}
1726
1727
switch (getLexer().getKind()) {
1728
default:
1729
if (HadParens)
1730
getLexer().UnLex(LParen);
1731
return ParseStatus::NoMatch;
1732
case AsmToken::Identifier:
1733
StringRef Name = getLexer().getTok().getIdentifier();
1734
MCRegister RegNo = matchRegisterNameHelper(Name);
1735
1736
if (!RegNo) {
1737
if (HadParens)
1738
getLexer().UnLex(LParen);
1739
return ParseStatus::NoMatch;
1740
}
1741
if (HadParens)
1742
Operands.push_back(RISCVOperand::createToken("(", FirstS));
1743
SMLoc S = getLoc();
1744
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
1745
getLexer().Lex();
1746
Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1747
}
1748
1749
if (HadParens) {
1750
getParser().Lex(); // Eat ')'
1751
Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1752
}
1753
1754
return ParseStatus::Success;
1755
}
1756
1757
ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1758
SMLoc S = getLoc();
1759
SMLoc E;
1760
const MCExpr *Res;
1761
1762
switch (getLexer().getKind()) {
1763
default:
1764
return ParseStatus::NoMatch;
1765
case AsmToken::LParen:
1766
case AsmToken::Minus:
1767
case AsmToken::Plus:
1768
case AsmToken::Exclaim:
1769
case AsmToken::Tilde:
1770
case AsmToken::Integer:
1771
case AsmToken::String: {
1772
if (getParser().parseExpression(Res, E))
1773
return ParseStatus::Failure;
1774
1775
auto *CE = dyn_cast<MCConstantExpr>(Res);
1776
if (CE) {
1777
int64_t Imm = CE->getValue();
1778
if (isUInt<7>(Imm)) {
1779
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1780
return ParseStatus::Success;
1781
}
1782
}
1783
1784
break;
1785
}
1786
case AsmToken::Identifier: {
1787
StringRef Identifier;
1788
if (getParser().parseIdentifier(Identifier))
1789
return ParseStatus::Failure;
1790
1791
auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1792
if (Opcode) {
1793
assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1794
"Unexpected opcode");
1795
Res = MCConstantExpr::create(Opcode->Value, getContext());
1796
E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1797
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1798
return ParseStatus::Success;
1799
}
1800
1801
break;
1802
}
1803
case AsmToken::Percent:
1804
break;
1805
}
1806
1807
return generateImmOutOfRangeError(
1808
S, 0, 127,
1809
"opcode must be a valid opcode name or an immediate in the range");
1810
}
1811
1812
ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1813
SMLoc S = getLoc();
1814
SMLoc E;
1815
const MCExpr *Res;
1816
1817
switch (getLexer().getKind()) {
1818
default:
1819
return ParseStatus::NoMatch;
1820
case AsmToken::LParen:
1821
case AsmToken::Minus:
1822
case AsmToken::Plus:
1823
case AsmToken::Exclaim:
1824
case AsmToken::Tilde:
1825
case AsmToken::Integer:
1826
case AsmToken::String: {
1827
if (getParser().parseExpression(Res, E))
1828
return ParseStatus::Failure;
1829
1830
auto *CE = dyn_cast<MCConstantExpr>(Res);
1831
if (CE) {
1832
int64_t Imm = CE->getValue();
1833
if (Imm >= 0 && Imm <= 2) {
1834
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1835
return ParseStatus::Success;
1836
}
1837
}
1838
1839
break;
1840
}
1841
case AsmToken::Identifier: {
1842
StringRef Identifier;
1843
if (getParser().parseIdentifier(Identifier))
1844
return ParseStatus::Failure;
1845
1846
unsigned Opcode;
1847
if (Identifier == "C0")
1848
Opcode = 0;
1849
else if (Identifier == "C1")
1850
Opcode = 1;
1851
else if (Identifier == "C2")
1852
Opcode = 2;
1853
else
1854
break;
1855
1856
Res = MCConstantExpr::create(Opcode, getContext());
1857
E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1858
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1859
return ParseStatus::Success;
1860
}
1861
case AsmToken::Percent: {
1862
// Discard operand with modifier.
1863
break;
1864
}
1865
}
1866
1867
return generateImmOutOfRangeError(
1868
S, 0, 2,
1869
"opcode must be a valid opcode name or an immediate in the range");
1870
}
1871
1872
ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1873
SMLoc S = getLoc();
1874
const MCExpr *Res;
1875
1876
switch (getLexer().getKind()) {
1877
default:
1878
return ParseStatus::NoMatch;
1879
case AsmToken::LParen:
1880
case AsmToken::Minus:
1881
case AsmToken::Plus:
1882
case AsmToken::Exclaim:
1883
case AsmToken::Tilde:
1884
case AsmToken::Integer:
1885
case AsmToken::String: {
1886
if (getParser().parseExpression(Res))
1887
return ParseStatus::Failure;
1888
1889
auto *CE = dyn_cast<MCConstantExpr>(Res);
1890
if (CE) {
1891
int64_t Imm = CE->getValue();
1892
if (isUInt<12>(Imm)) {
1893
auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1894
// Accept an immediate representing a named Sys Reg if it satisfies the
1895
// the required features.
1896
for (auto &Reg : Range) {
1897
if (Reg.haveRequiredFeatures(STI->getFeatureBits())) {
1898
Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm));
1899
return ParseStatus::Success;
1900
}
1901
}
1902
// Accept an immediate representing an un-named Sys Reg if the range is
1903
// valid, regardless of the required features.
1904
Operands.push_back(RISCVOperand::createSysReg("", S, Imm));
1905
return ParseStatus::Success;
1906
}
1907
}
1908
1909
return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1910
}
1911
case AsmToken::Identifier: {
1912
StringRef Identifier;
1913
if (getParser().parseIdentifier(Identifier))
1914
return ParseStatus::Failure;
1915
1916
auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1917
if (!SysReg)
1918
SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1919
if (!SysReg)
1920
if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1921
Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1922
SysReg->Name + "'");
1923
1924
// Accept a named Sys Reg if the required features are present.
1925
if (SysReg) {
1926
if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
1927
return Error(S, "system register use requires an option to be enabled");
1928
Operands.push_back(
1929
RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1930
return ParseStatus::Success;
1931
}
1932
1933
return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1934
"operand must be a valid system register "
1935
"name or an integer in the range");
1936
}
1937
case AsmToken::Percent: {
1938
// Discard operand with modifier.
1939
return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1940
}
1941
}
1942
1943
return ParseStatus::NoMatch;
1944
}
1945
1946
ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
1947
SMLoc S = getLoc();
1948
1949
// Parse special floats (inf/nan/min) representation.
1950
if (getTok().is(AsmToken::Identifier)) {
1951
StringRef Identifier = getTok().getIdentifier();
1952
if (Identifier.compare_insensitive("inf") == 0) {
1953
Operands.push_back(
1954
RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
1955
getTok().getEndLoc(), isRV64()));
1956
} else if (Identifier.compare_insensitive("nan") == 0) {
1957
Operands.push_back(
1958
RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
1959
getTok().getEndLoc(), isRV64()));
1960
} else if (Identifier.compare_insensitive("min") == 0) {
1961
Operands.push_back(
1962
RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
1963
getTok().getEndLoc(), isRV64()));
1964
} else {
1965
return TokError("invalid floating point literal");
1966
}
1967
1968
Lex(); // Eat the token.
1969
1970
return ParseStatus::Success;
1971
}
1972
1973
// Handle negation, as that still comes through as a separate token.
1974
bool IsNegative = parseOptionalToken(AsmToken::Minus);
1975
1976
const AsmToken &Tok = getTok();
1977
if (!Tok.is(AsmToken::Real))
1978
return TokError("invalid floating point immediate");
1979
1980
// Parse FP representation.
1981
APFloat RealVal(APFloat::IEEEdouble());
1982
auto StatusOrErr =
1983
RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
1984
if (errorToBool(StatusOrErr.takeError()))
1985
return TokError("invalid floating point representation");
1986
1987
if (IsNegative)
1988
RealVal.changeSign();
1989
1990
Operands.push_back(RISCVOperand::createFPImm(
1991
RealVal.bitcastToAPInt().getZExtValue(), S));
1992
1993
Lex(); // Eat the token.
1994
1995
return ParseStatus::Success;
1996
}
1997
1998
ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1999
SMLoc S = getLoc();
2000
SMLoc E;
2001
const MCExpr *Res;
2002
2003
switch (getLexer().getKind()) {
2004
default:
2005
return ParseStatus::NoMatch;
2006
case AsmToken::LParen:
2007
case AsmToken::Dot:
2008
case AsmToken::Minus:
2009
case AsmToken::Plus:
2010
case AsmToken::Exclaim:
2011
case AsmToken::Tilde:
2012
case AsmToken::Integer:
2013
case AsmToken::String:
2014
case AsmToken::Identifier:
2015
if (getParser().parseExpression(Res, E))
2016
return ParseStatus::Failure;
2017
break;
2018
case AsmToken::Percent:
2019
return parseOperandWithModifier(Operands);
2020
}
2021
2022
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2023
return ParseStatus::Success;
2024
}
2025
2026
ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
2027
SMLoc S = getLoc();
2028
SMLoc E;
2029
2030
if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
2031
return ParseStatus::Failure;
2032
2033
if (getLexer().getKind() != AsmToken::Identifier)
2034
return Error(getLoc(), "expected valid identifier for operand modifier");
2035
StringRef Identifier = getParser().getTok().getIdentifier();
2036
RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
2037
if (VK == RISCVMCExpr::VK_RISCV_Invalid)
2038
return Error(getLoc(), "unrecognized operand modifier");
2039
2040
getParser().Lex(); // Eat the identifier
2041
if (parseToken(AsmToken::LParen, "expected '('"))
2042
return ParseStatus::Failure;
2043
2044
const MCExpr *SubExpr;
2045
if (getParser().parseParenExpression(SubExpr, E))
2046
return ParseStatus::Failure;
2047
2048
const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
2049
Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
2050
return ParseStatus::Success;
2051
}
2052
2053
ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2054
SMLoc S = getLoc();
2055
const MCExpr *Res;
2056
2057
if (getLexer().getKind() != AsmToken::Identifier)
2058
return ParseStatus::NoMatch;
2059
2060
StringRef Identifier;
2061
AsmToken Tok = getLexer().getTok();
2062
2063
if (getParser().parseIdentifier(Identifier))
2064
return ParseStatus::Failure;
2065
2066
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2067
2068
if (Identifier.consume_back("@plt"))
2069
return Error(getLoc(), "'@plt' operand not valid for instruction");
2070
2071
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2072
2073
if (Sym->isVariable()) {
2074
const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
2075
if (!isa<MCSymbolRefExpr>(V)) {
2076
getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
2077
return ParseStatus::NoMatch;
2078
}
2079
Res = V;
2080
} else
2081
Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
2082
2083
MCBinaryExpr::Opcode Opcode;
2084
switch (getLexer().getKind()) {
2085
default:
2086
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2087
return ParseStatus::Success;
2088
case AsmToken::Plus:
2089
Opcode = MCBinaryExpr::Add;
2090
getLexer().Lex();
2091
break;
2092
case AsmToken::Minus:
2093
Opcode = MCBinaryExpr::Sub;
2094
getLexer().Lex();
2095
break;
2096
}
2097
2098
const MCExpr *Expr;
2099
if (getParser().parseExpression(Expr, E))
2100
return ParseStatus::Failure;
2101
Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
2102
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2103
return ParseStatus::Success;
2104
}
2105
2106
ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2107
SMLoc S = getLoc();
2108
const MCExpr *Res;
2109
2110
if (getLexer().getKind() != AsmToken::Identifier)
2111
return ParseStatus::NoMatch;
2112
2113
// Avoid parsing the register in `call rd, foo` as a call symbol.
2114
if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
2115
return ParseStatus::NoMatch;
2116
2117
StringRef Identifier;
2118
if (getParser().parseIdentifier(Identifier))
2119
return ParseStatus::Failure;
2120
2121
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
2122
2123
RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
2124
(void)Identifier.consume_back("@plt");
2125
2126
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2127
Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
2128
Res = RISCVMCExpr::create(Res, Kind, getContext());
2129
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2130
return ParseStatus::Success;
2131
}
2132
2133
ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2134
SMLoc S = getLoc();
2135
SMLoc E;
2136
const MCExpr *Res;
2137
2138
if (getParser().parseExpression(Res, E))
2139
return ParseStatus::Failure;
2140
2141
if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2142
cast<MCSymbolRefExpr>(Res)->getKind() ==
2143
MCSymbolRefExpr::VariantKind::VK_PLT)
2144
return Error(S, "operand must be a valid jump target");
2145
2146
Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2147
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2148
return ParseStatus::Success;
2149
}
2150
2151
ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2152
// Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2153
// both being acceptable forms. When parsing `jal ra, foo` this function
2154
// will be called for the `ra` register operand in an attempt to match the
2155
// single-operand alias. parseJALOffset must fail for this case. It would
2156
// seem logical to try parse the operand using parseImmediate and return
2157
// NoMatch if the next token is a comma (meaning we must be parsing a jal in
2158
// the second form rather than the first). We can't do this as there's no
2159
// way of rewinding the lexer state. Instead, return NoMatch if this operand
2160
// is an identifier and is followed by a comma.
2161
if (getLexer().is(AsmToken::Identifier) &&
2162
getLexer().peekTok().is(AsmToken::Comma))
2163
return ParseStatus::NoMatch;
2164
2165
return parseImmediate(Operands);
2166
}
2167
2168
bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2169
unsigned &Sew, unsigned &Lmul,
2170
bool &Fractional, bool &TailAgnostic,
2171
bool &MaskAgnostic) {
2172
if (Tok.isNot(AsmToken::Identifier))
2173
return true;
2174
2175
StringRef Identifier = Tok.getIdentifier();
2176
2177
switch (State) {
2178
case VTypeState_SEW:
2179
if (!Identifier.consume_front("e"))
2180
break;
2181
if (Identifier.getAsInteger(10, Sew))
2182
break;
2183
if (!RISCVVType::isValidSEW(Sew))
2184
break;
2185
State = VTypeState_LMUL;
2186
return false;
2187
case VTypeState_LMUL: {
2188
if (!Identifier.consume_front("m"))
2189
break;
2190
Fractional = Identifier.consume_front("f");
2191
if (Identifier.getAsInteger(10, Lmul))
2192
break;
2193
if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2194
break;
2195
2196
if (Fractional) {
2197
unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2198
unsigned MinLMUL = ELEN / 8;
2199
if (Lmul > MinLMUL)
2200
Warning(Tok.getLoc(),
2201
"use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2202
Twine(MinLMUL) + " is reserved");
2203
}
2204
2205
State = VTypeState_TailPolicy;
2206
return false;
2207
}
2208
case VTypeState_TailPolicy:
2209
if (Identifier == "ta")
2210
TailAgnostic = true;
2211
else if (Identifier == "tu")
2212
TailAgnostic = false;
2213
else
2214
break;
2215
State = VTypeState_MaskPolicy;
2216
return false;
2217
case VTypeState_MaskPolicy:
2218
if (Identifier == "ma")
2219
MaskAgnostic = true;
2220
else if (Identifier == "mu")
2221
MaskAgnostic = false;
2222
else
2223
break;
2224
State = VTypeState_Done;
2225
return false;
2226
case VTypeState_Done:
2227
// Extra token?
2228
break;
2229
}
2230
2231
return true;
2232
}
2233
2234
ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2235
SMLoc S = getLoc();
2236
2237
unsigned Sew = 0;
2238
unsigned Lmul = 0;
2239
bool Fractional = false;
2240
bool TailAgnostic = false;
2241
bool MaskAgnostic = false;
2242
2243
VTypeState State = VTypeState_SEW;
2244
SMLoc SEWLoc = S;
2245
2246
if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2247
MaskAgnostic))
2248
return ParseStatus::NoMatch;
2249
2250
getLexer().Lex();
2251
2252
while (parseOptionalToken(AsmToken::Comma)) {
2253
if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2254
MaskAgnostic))
2255
break;
2256
2257
getLexer().Lex();
2258
}
2259
2260
if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
2261
RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2262
if (Fractional) {
2263
unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2264
unsigned MaxSEW = ELEN / Lmul;
2265
// If MaxSEW < 8, we should have printed warning about reserved LMUL.
2266
if (MaxSEW >= 8 && Sew > MaxSEW)
2267
Warning(SEWLoc,
2268
"use of vtype encodings with SEW > " + Twine(MaxSEW) +
2269
" and LMUL == mf" + Twine(Lmul) +
2270
" may not be compatible with all RVV implementations");
2271
}
2272
2273
unsigned VTypeI =
2274
RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
2275
Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2276
return ParseStatus::Success;
2277
}
2278
2279
return generateVTypeError(S);
2280
}
2281
2282
bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2283
return Error(
2284
ErrorLoc,
2285
"operand must be "
2286
"e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2287
}
2288
2289
ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2290
if (getLexer().isNot(AsmToken::Identifier))
2291
return ParseStatus::NoMatch;
2292
2293
StringRef Name = getLexer().getTok().getIdentifier();
2294
if (!Name.consume_back(".t"))
2295
return Error(getLoc(), "expected '.t' suffix");
2296
MCRegister RegNo = matchRegisterNameHelper(Name);
2297
2298
if (!RegNo)
2299
return ParseStatus::NoMatch;
2300
if (RegNo != RISCV::V0)
2301
return ParseStatus::NoMatch;
2302
SMLoc S = getLoc();
2303
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2304
getLexer().Lex();
2305
Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
2306
return ParseStatus::Success;
2307
}
2308
2309
ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2310
if (getLexer().isNot(AsmToken::Identifier))
2311
return ParseStatus::NoMatch;
2312
2313
StringRef Name = getLexer().getTok().getIdentifier();
2314
MCRegister RegNo = matchRegisterNameHelper(Name);
2315
2316
if (!RegNo)
2317
return ParseStatus::NoMatch;
2318
SMLoc S = getLoc();
2319
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2320
getLexer().Lex();
2321
Operands.push_back(RISCVOperand::createReg(
2322
RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2323
return ParseStatus::Success;
2324
}
2325
2326
template <bool IsRV64>
2327
ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2328
return parseGPRPair(Operands, IsRV64);
2329
}
2330
2331
ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2332
bool IsRV64Inst) {
2333
// If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2334
// RV64 as it will prevent matching the RV64 version of the same instruction
2335
// that doesn't use a GPRPair.
2336
// If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2337
// still parse as a pair.
2338
if (!IsRV64Inst && isRV64())
2339
return ParseStatus::NoMatch;
2340
2341
if (getLexer().isNot(AsmToken::Identifier))
2342
return ParseStatus::NoMatch;
2343
2344
StringRef Name = getLexer().getTok().getIdentifier();
2345
MCRegister RegNo = matchRegisterNameHelper(Name);
2346
2347
if (!RegNo)
2348
return ParseStatus::NoMatch;
2349
2350
if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo))
2351
return ParseStatus::NoMatch;
2352
2353
if ((RegNo - RISCV::X0) & 1)
2354
return TokError("register must be even");
2355
2356
SMLoc S = getLoc();
2357
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2358
getLexer().Lex();
2359
2360
const MCRegisterInfo *RI = getContext().getRegisterInfo();
2361
unsigned Pair = RI->getMatchingSuperReg(
2362
RegNo, RISCV::sub_gpr_even,
2363
&RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2364
Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2365
return ParseStatus::Success;
2366
}
2367
2368
ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2369
if (getLexer().isNot(AsmToken::Identifier))
2370
return TokError(
2371
"operand must be a valid floating point rounding mode mnemonic");
2372
2373
StringRef Str = getLexer().getTok().getIdentifier();
2374
RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
2375
2376
if (FRM == RISCVFPRndMode::Invalid)
2377
return TokError(
2378
"operand must be a valid floating point rounding mode mnemonic");
2379
2380
Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2381
Lex(); // Eat identifier token.
2382
return ParseStatus::Success;
2383
}
2384
2385
ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2386
const AsmToken &Tok = getLexer().getTok();
2387
2388
if (Tok.is(AsmToken::Integer)) {
2389
if (Tok.getIntVal() != 0)
2390
goto ParseFail;
2391
2392
Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2393
Lex();
2394
return ParseStatus::Success;
2395
}
2396
2397
if (Tok.is(AsmToken::Identifier)) {
2398
StringRef Str = Tok.getIdentifier();
2399
2400
// Letters must be unique, taken from 'iorw', and in ascending order. This
2401
// holds as long as each individual character is one of 'iorw' and is
2402
// greater than the previous character.
2403
unsigned Imm = 0;
2404
bool Valid = true;
2405
char Prev = '\0';
2406
for (char c : Str) {
2407
switch (c) {
2408
default:
2409
Valid = false;
2410
break;
2411
case 'i':
2412
Imm |= RISCVFenceField::I;
2413
break;
2414
case 'o':
2415
Imm |= RISCVFenceField::O;
2416
break;
2417
case 'r':
2418
Imm |= RISCVFenceField::R;
2419
break;
2420
case 'w':
2421
Imm |= RISCVFenceField::W;
2422
break;
2423
}
2424
2425
if (c <= Prev) {
2426
Valid = false;
2427
break;
2428
}
2429
Prev = c;
2430
}
2431
2432
if (!Valid)
2433
goto ParseFail;
2434
2435
Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2436
Lex();
2437
return ParseStatus::Success;
2438
}
2439
2440
ParseFail:
2441
return TokError("operand must be formed of letters selected in-order from "
2442
"'iorw' or be 0");
2443
}
2444
2445
ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2446
if (parseToken(AsmToken::LParen, "expected '('"))
2447
return ParseStatus::Failure;
2448
Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2449
2450
if (!parseRegister(Operands).isSuccess())
2451
return Error(getLoc(), "expected register");
2452
2453
if (parseToken(AsmToken::RParen, "expected ')'"))
2454
return ParseStatus::Failure;
2455
Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2456
2457
return ParseStatus::Success;
2458
}
2459
2460
ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2461
// Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2462
// as one of their register operands, such as `(a0)`. This just denotes that
2463
// the register (in this case `a0`) contains a memory address.
2464
//
2465
// Normally, we would be able to parse these by putting the parens into the
2466
// instruction string. However, GNU as also accepts a zero-offset memory
2467
// operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2468
// with parseImmediate followed by parseMemOpBaseReg, but these instructions
2469
// do not accept an immediate operand, and we do not want to add a "dummy"
2470
// operand that is silently dropped.
2471
//
2472
// Instead, we use this custom parser. This will: allow (and discard) an
2473
// offset if it is zero; require (and discard) parentheses; and add only the
2474
// parsed register operand to `Operands`.
2475
//
2476
// These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2477
// which will only print the register surrounded by parentheses (which GNU as
2478
// also uses as its canonical representation for these operands).
2479
std::unique_ptr<RISCVOperand> OptionalImmOp;
2480
2481
if (getLexer().isNot(AsmToken::LParen)) {
2482
// Parse an Integer token. We do not accept arbritrary constant expressions
2483
// in the offset field (because they may include parens, which complicates
2484
// parsing a lot).
2485
int64_t ImmVal;
2486
SMLoc ImmStart = getLoc();
2487
if (getParser().parseIntToken(ImmVal,
2488
"expected '(' or optional integer offset"))
2489
return ParseStatus::Failure;
2490
2491
// Create a RISCVOperand for checking later (so the error messages are
2492
// nicer), but we don't add it to Operands.
2493
SMLoc ImmEnd = getLoc();
2494
OptionalImmOp =
2495
RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2496
ImmStart, ImmEnd, isRV64());
2497
}
2498
2499
if (parseToken(AsmToken::LParen,
2500
OptionalImmOp ? "expected '(' after optional integer offset"
2501
: "expected '(' or optional integer offset"))
2502
return ParseStatus::Failure;
2503
2504
if (!parseRegister(Operands).isSuccess())
2505
return Error(getLoc(), "expected register");
2506
2507
if (parseToken(AsmToken::RParen, "expected ')'"))
2508
return ParseStatus::Failure;
2509
2510
// Deferred Handling of non-zero offsets. This makes the error messages nicer.
2511
if (OptionalImmOp && !OptionalImmOp->isImmZero())
2512
return Error(
2513
OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2514
SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2515
2516
return ParseStatus::Success;
2517
}
2518
2519
ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2520
// RR : a2(a1)
2521
if (getLexer().getKind() != AsmToken::Identifier)
2522
return ParseStatus::NoMatch;
2523
2524
StringRef RegName = getLexer().getTok().getIdentifier();
2525
MCRegister Reg = matchRegisterNameHelper(RegName);
2526
if (!Reg)
2527
return Error(getLoc(), "invalid register");
2528
getLexer().Lex();
2529
2530
if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2531
return ParseStatus::Failure;
2532
2533
if (getLexer().getKind() != AsmToken::Identifier)
2534
return Error(getLoc(), "expected register");
2535
2536
StringRef Reg2Name = getLexer().getTok().getIdentifier();
2537
MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);
2538
if (!Reg2)
2539
return Error(getLoc(), "invalid register");
2540
getLexer().Lex();
2541
2542
if (parseToken(AsmToken::RParen, "expected ')'"))
2543
return ParseStatus::Failure;
2544
2545
Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
2546
2547
return ParseStatus::Success;
2548
}
2549
2550
ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
2551
// Rlist: {ra [, s0[-sN]]}
2552
// XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2553
SMLoc S = getLoc();
2554
2555
if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2556
return ParseStatus::Failure;
2557
2558
bool IsEABI = isRVE();
2559
2560
if (getLexer().isNot(AsmToken::Identifier))
2561
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2562
2563
StringRef RegName = getLexer().getTok().getIdentifier();
2564
MCRegister RegStart = matchRegisterNameHelper(RegName);
2565
MCRegister RegEnd;
2566
if (RegStart != RISCV::X1)
2567
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2568
getLexer().Lex();
2569
2570
// parse case like ,s0
2571
if (parseOptionalToken(AsmToken::Comma)) {
2572
if (getLexer().isNot(AsmToken::Identifier))
2573
return Error(getLoc(), "invalid register");
2574
StringRef RegName = getLexer().getTok().getIdentifier();
2575
RegStart = matchRegisterNameHelper(RegName);
2576
if (!RegStart)
2577
return Error(getLoc(), "invalid register");
2578
if (RegStart != RISCV::X8)
2579
return Error(getLoc(),
2580
"continuous register list must start from 's0' or 'x8'");
2581
getLexer().Lex(); // eat reg
2582
}
2583
2584
// parse case like -s1
2585
if (parseOptionalToken(AsmToken::Minus)) {
2586
StringRef EndName = getLexer().getTok().getIdentifier();
2587
// FIXME: the register mapping and checks of EABI is wrong
2588
RegEnd = matchRegisterNameHelper(EndName);
2589
if (!RegEnd)
2590
return Error(getLoc(), "invalid register");
2591
if (IsEABI && RegEnd != RISCV::X9)
2592
return Error(getLoc(), "contiguous register list of EABI can only be "
2593
"'s0-s1' or 'x8-x9' pair");
2594
getLexer().Lex();
2595
}
2596
2597
if (!IsEABI) {
2598
// parse extra part like ', x18[-x20]' for XRegList
2599
if (parseOptionalToken(AsmToken::Comma)) {
2600
if (RegEnd != RISCV::X9)
2601
return Error(
2602
getLoc(),
2603
"first contiguous registers pair of register list must be 'x8-x9'");
2604
2605
// parse ', x18' for extra part
2606
if (getLexer().isNot(AsmToken::Identifier))
2607
return Error(getLoc(), "invalid register");
2608
StringRef EndName = getLexer().getTok().getIdentifier();
2609
if (MatchRegisterName(EndName) != RISCV::X18)
2610
return Error(getLoc(),
2611
"second contiguous registers pair of register list "
2612
"must start from 'x18'");
2613
getLexer().Lex();
2614
2615
// parse '-x20' for extra part
2616
if (parseOptionalToken(AsmToken::Minus)) {
2617
if (getLexer().isNot(AsmToken::Identifier))
2618
return Error(getLoc(), "invalid register");
2619
EndName = getLexer().getTok().getIdentifier();
2620
if (MatchRegisterName(EndName) == RISCV::NoRegister)
2621
return Error(getLoc(), "invalid register");
2622
getLexer().Lex();
2623
}
2624
RegEnd = MatchRegisterName(EndName);
2625
}
2626
}
2627
2628
if (RegEnd == RISCV::X26)
2629
return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2630
"x18-x26} is not supported");
2631
2632
if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2633
return ParseStatus::Failure;
2634
2635
if (RegEnd == RISCV::NoRegister)
2636
RegEnd = RegStart;
2637
2638
auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2639
if (Encode == RISCVZC::INVALID_RLIST)
2640
return Error(S, "invalid register list");
2641
Operands.push_back(RISCVOperand::createRlist(Encode, S));
2642
2643
return ParseStatus::Success;
2644
}
2645
2646
ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2647
bool ExpectNegative) {
2648
bool Negative = parseOptionalToken(AsmToken::Minus);
2649
2650
SMLoc S = getLoc();
2651
int64_t StackAdjustment = getLexer().getTok().getIntVal();
2652
unsigned Spimm = 0;
2653
unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2654
2655
if (Negative != ExpectNegative ||
2656
!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))
2657
return ParseStatus::NoMatch;
2658
Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2659
getLexer().Lex();
2660
return ParseStatus::Success;
2661
}
2662
2663
/// Looks at a token type and creates the relevant operand from this
2664
/// information, adding to Operands. If operand was parsed, returns false, else
2665
/// true.
2666
bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2667
// Check if the current operand has a custom associated parser, if so, try to
2668
// custom parse the operand, or fallback to the general approach.
2669
ParseStatus Result =
2670
MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2671
if (Result.isSuccess())
2672
return false;
2673
if (Result.isFailure())
2674
return true;
2675
2676
// Attempt to parse token as a register.
2677
if (parseRegister(Operands, true).isSuccess())
2678
return false;
2679
2680
// Attempt to parse token as an immediate
2681
if (parseImmediate(Operands).isSuccess()) {
2682
// Parse memory base register if present
2683
if (getLexer().is(AsmToken::LParen))
2684
return !parseMemOpBaseReg(Operands).isSuccess();
2685
return false;
2686
}
2687
2688
// Finally we have exhausted all options and must declare defeat.
2689
Error(getLoc(), "unknown operand");
2690
return true;
2691
}
2692
2693
bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2694
StringRef Name, SMLoc NameLoc,
2695
OperandVector &Operands) {
2696
// Ensure that if the instruction occurs when relaxation is enabled,
2697
// relocations are forced for the file. Ideally this would be done when there
2698
// is enough information to reliably determine if the instruction itself may
2699
// cause relaxations. Unfortunately instruction processing stage occurs in the
2700
// same pass as relocation emission, so it's too late to set a 'sticky bit'
2701
// for the entire file.
2702
if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2703
auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2704
if (Assembler != nullptr) {
2705
RISCVAsmBackend &MAB =
2706
static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2707
MAB.setForceRelocs();
2708
}
2709
}
2710
2711
// First operand is token for instruction
2712
Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2713
2714
// If there are no more operands, then finish
2715
if (getLexer().is(AsmToken::EndOfStatement)) {
2716
getParser().Lex(); // Consume the EndOfStatement.
2717
return false;
2718
}
2719
2720
// Parse first operand
2721
if (parseOperand(Operands, Name))
2722
return true;
2723
2724
// Parse until end of statement, consuming commas between operands
2725
while (parseOptionalToken(AsmToken::Comma)) {
2726
// Parse next operand
2727
if (parseOperand(Operands, Name))
2728
return true;
2729
}
2730
2731
if (getParser().parseEOL("unexpected token")) {
2732
getParser().eatToEndOfStatement();
2733
return true;
2734
}
2735
return false;
2736
}
2737
2738
bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2739
RISCVMCExpr::VariantKind &Kind) {
2740
Kind = RISCVMCExpr::VK_RISCV_None;
2741
2742
if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2743
Kind = RE->getKind();
2744
Expr = RE->getSubExpr();
2745
}
2746
2747
MCValue Res;
2748
MCFixup Fixup;
2749
if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2750
return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2751
return false;
2752
}
2753
2754
bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
2755
MCValue Res;
2756
MCFixup Fixup;
2757
if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
2758
return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
2759
Res.getSymB();
2760
}
2761
return false;
2762
}
2763
2764
ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
2765
StringRef IDVal = DirectiveID.getString();
2766
2767
if (IDVal == ".option")
2768
return parseDirectiveOption();
2769
if (IDVal == ".attribute")
2770
return parseDirectiveAttribute();
2771
if (IDVal == ".insn")
2772
return parseDirectiveInsn(DirectiveID.getLoc());
2773
if (IDVal == ".variant_cc")
2774
return parseDirectiveVariantCC();
2775
2776
return ParseStatus::NoMatch;
2777
}
2778
2779
bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2780
bool FromOptionDirective) {
2781
for (auto &Feature : RISCVFeatureKV)
2782
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2783
clearFeatureBits(Feature.Value, Feature.Key);
2784
2785
auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2786
Arch, /*EnableExperimentalExtension=*/true,
2787
/*ExperimentalExtensionVersionCheck=*/true);
2788
if (!ParseResult) {
2789
std::string Buffer;
2790
raw_string_ostream OutputErrMsg(Buffer);
2791
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2792
OutputErrMsg << "invalid arch name '" << Arch << "', "
2793
<< ErrMsg.getMessage();
2794
});
2795
2796
return Error(Loc, OutputErrMsg.str());
2797
}
2798
auto &ISAInfo = *ParseResult;
2799
2800
for (auto &Feature : RISCVFeatureKV)
2801
if (ISAInfo->hasExtension(Feature.Key))
2802
setFeatureBits(Feature.Value, Feature.Key);
2803
2804
if (FromOptionDirective) {
2805
if (ISAInfo->getXLen() == 32 && isRV64())
2806
return Error(Loc, "bad arch string switching from rv64 to rv32");
2807
else if (ISAInfo->getXLen() == 64 && !isRV64())
2808
return Error(Loc, "bad arch string switching from rv32 to rv64");
2809
}
2810
2811
if (ISAInfo->getXLen() == 32)
2812
clearFeatureBits(RISCV::Feature64Bit, "64bit");
2813
else if (ISAInfo->getXLen() == 64)
2814
setFeatureBits(RISCV::Feature64Bit, "64bit");
2815
else
2816
return Error(Loc, "bad arch string " + Arch);
2817
2818
Result = ISAInfo->toString();
2819
return false;
2820
}
2821
2822
bool RISCVAsmParser::parseDirectiveOption() {
2823
MCAsmParser &Parser = getParser();
2824
// Get the option token.
2825
AsmToken Tok = Parser.getTok();
2826
2827
// At the moment only identifiers are supported.
2828
if (parseToken(AsmToken::Identifier, "expected identifier"))
2829
return true;
2830
2831
StringRef Option = Tok.getIdentifier();
2832
2833
if (Option == "push") {
2834
if (Parser.parseEOL())
2835
return true;
2836
2837
getTargetStreamer().emitDirectiveOptionPush();
2838
pushFeatureBits();
2839
return false;
2840
}
2841
2842
if (Option == "pop") {
2843
SMLoc StartLoc = Parser.getTok().getLoc();
2844
if (Parser.parseEOL())
2845
return true;
2846
2847
getTargetStreamer().emitDirectiveOptionPop();
2848
if (popFeatureBits())
2849
return Error(StartLoc, ".option pop with no .option push");
2850
2851
return false;
2852
}
2853
2854
if (Option == "arch") {
2855
SmallVector<RISCVOptionArchArg> Args;
2856
do {
2857
if (Parser.parseComma())
2858
return true;
2859
2860
RISCVOptionArchArgType Type;
2861
if (parseOptionalToken(AsmToken::Plus))
2862
Type = RISCVOptionArchArgType::Plus;
2863
else if (parseOptionalToken(AsmToken::Minus))
2864
Type = RISCVOptionArchArgType::Minus;
2865
else if (!Args.empty())
2866
return Error(Parser.getTok().getLoc(),
2867
"unexpected token, expected + or -");
2868
else
2869
Type = RISCVOptionArchArgType::Full;
2870
2871
if (Parser.getTok().isNot(AsmToken::Identifier))
2872
return Error(Parser.getTok().getLoc(),
2873
"unexpected token, expected identifier");
2874
2875
StringRef Arch = Parser.getTok().getString();
2876
SMLoc Loc = Parser.getTok().getLoc();
2877
Parser.Lex();
2878
2879
if (Type == RISCVOptionArchArgType::Full) {
2880
std::string Result;
2881
if (resetToArch(Arch, Loc, Result, true))
2882
return true;
2883
2884
Args.emplace_back(Type, Result);
2885
break;
2886
}
2887
2888
if (isDigit(Arch.back()))
2889
return Error(
2890
Loc, "extension version number parsing not currently implemented");
2891
2892
std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
2893
if (!enableExperimentalExtension() &&
2894
StringRef(Feature).starts_with("experimental-"))
2895
return Error(Loc, "unexpected experimental extensions");
2896
auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
2897
if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
2898
return Error(Loc, "unknown extension feature");
2899
2900
Args.emplace_back(Type, Arch.str());
2901
2902
if (Type == RISCVOptionArchArgType::Plus) {
2903
FeatureBitset OldFeatureBits = STI->getFeatureBits();
2904
2905
setFeatureBits(Ext->Value, Ext->Key);
2906
auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
2907
if (!ParseResult) {
2908
copySTI().setFeatureBits(OldFeatureBits);
2909
setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2910
2911
std::string Buffer;
2912
raw_string_ostream OutputErrMsg(Buffer);
2913
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2914
OutputErrMsg << ErrMsg.getMessage();
2915
});
2916
2917
return Error(Loc, OutputErrMsg.str());
2918
}
2919
} else {
2920
assert(Type == RISCVOptionArchArgType::Minus);
2921
// It is invalid to disable an extension that there are other enabled
2922
// extensions depend on it.
2923
// TODO: Make use of RISCVISAInfo to handle this
2924
for (auto &Feature : RISCVFeatureKV) {
2925
if (getSTI().hasFeature(Feature.Value) &&
2926
Feature.Implies.test(Ext->Value))
2927
return Error(Loc, Twine("can't disable ") + Ext->Key +
2928
" extension; " + Feature.Key +
2929
" extension requires " + Ext->Key +
2930
" extension");
2931
}
2932
2933
clearFeatureBits(Ext->Value, Ext->Key);
2934
}
2935
} while (Parser.getTok().isNot(AsmToken::EndOfStatement));
2936
2937
if (Parser.parseEOL())
2938
return true;
2939
2940
getTargetStreamer().emitDirectiveOptionArch(Args);
2941
return false;
2942
}
2943
2944
if (Option == "rvc") {
2945
if (Parser.parseEOL())
2946
return true;
2947
2948
getTargetStreamer().emitDirectiveOptionRVC();
2949
setFeatureBits(RISCV::FeatureStdExtC, "c");
2950
return false;
2951
}
2952
2953
if (Option == "norvc") {
2954
if (Parser.parseEOL())
2955
return true;
2956
2957
getTargetStreamer().emitDirectiveOptionNoRVC();
2958
clearFeatureBits(RISCV::FeatureStdExtC, "c");
2959
clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
2960
return false;
2961
}
2962
2963
if (Option == "pic") {
2964
if (Parser.parseEOL())
2965
return true;
2966
2967
getTargetStreamer().emitDirectiveOptionPIC();
2968
ParserOptions.IsPicEnabled = true;
2969
return false;
2970
}
2971
2972
if (Option == "nopic") {
2973
if (Parser.parseEOL())
2974
return true;
2975
2976
getTargetStreamer().emitDirectiveOptionNoPIC();
2977
ParserOptions.IsPicEnabled = false;
2978
return false;
2979
}
2980
2981
if (Option == "relax") {
2982
if (Parser.parseEOL())
2983
return true;
2984
2985
getTargetStreamer().emitDirectiveOptionRelax();
2986
setFeatureBits(RISCV::FeatureRelax, "relax");
2987
return false;
2988
}
2989
2990
if (Option == "norelax") {
2991
if (Parser.parseEOL())
2992
return true;
2993
2994
getTargetStreamer().emitDirectiveOptionNoRelax();
2995
clearFeatureBits(RISCV::FeatureRelax, "relax");
2996
return false;
2997
}
2998
2999
// Unknown option.
3000
Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
3001
"'rvc', 'norvc', 'arch', 'relax' or "
3002
"'norelax'");
3003
Parser.eatToEndOfStatement();
3004
return false;
3005
}
3006
3007
/// parseDirectiveAttribute
3008
/// ::= .attribute expression ',' ( expression | "string" )
3009
/// ::= .attribute identifier ',' ( expression | "string" )
3010
bool RISCVAsmParser::parseDirectiveAttribute() {
3011
MCAsmParser &Parser = getParser();
3012
int64_t Tag;
3013
SMLoc TagLoc;
3014
TagLoc = Parser.getTok().getLoc();
3015
if (Parser.getTok().is(AsmToken::Identifier)) {
3016
StringRef Name = Parser.getTok().getIdentifier();
3017
std::optional<unsigned> Ret =
3018
ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
3019
if (!Ret)
3020
return Error(TagLoc, "attribute name not recognised: " + Name);
3021
Tag = *Ret;
3022
Parser.Lex();
3023
} else {
3024
const MCExpr *AttrExpr;
3025
3026
TagLoc = Parser.getTok().getLoc();
3027
if (Parser.parseExpression(AttrExpr))
3028
return true;
3029
3030
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3031
if (check(!CE, TagLoc, "expected numeric constant"))
3032
return true;
3033
3034
Tag = CE->getValue();
3035
}
3036
3037
if (Parser.parseComma())
3038
return true;
3039
3040
StringRef StringValue;
3041
int64_t IntegerValue = 0;
3042
bool IsIntegerValue = true;
3043
3044
// RISC-V attributes have a string value if the tag number is odd
3045
// and an integer value if the tag number is even.
3046
if (Tag % 2)
3047
IsIntegerValue = false;
3048
3049
SMLoc ValueExprLoc = Parser.getTok().getLoc();
3050
if (IsIntegerValue) {
3051
const MCExpr *ValueExpr;
3052
if (Parser.parseExpression(ValueExpr))
3053
return true;
3054
3055
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3056
if (!CE)
3057
return Error(ValueExprLoc, "expected numeric constant");
3058
IntegerValue = CE->getValue();
3059
} else {
3060
if (Parser.getTok().isNot(AsmToken::String))
3061
return Error(Parser.getTok().getLoc(), "expected string constant");
3062
3063
StringValue = Parser.getTok().getStringContents();
3064
Parser.Lex();
3065
}
3066
3067
if (Parser.parseEOL())
3068
return true;
3069
3070
if (IsIntegerValue)
3071
getTargetStreamer().emitAttribute(Tag, IntegerValue);
3072
else if (Tag != RISCVAttrs::ARCH)
3073
getTargetStreamer().emitTextAttribute(Tag, StringValue);
3074
else {
3075
std::string Result;
3076
if (resetToArch(StringValue, ValueExprLoc, Result, false))
3077
return true;
3078
3079
// Then emit the arch string.
3080
getTargetStreamer().emitTextAttribute(Tag, Result);
3081
}
3082
3083
return false;
3084
}
3085
3086
bool isValidInsnFormat(StringRef Format, bool AllowC) {
3087
return StringSwitch<bool>(Format)
3088
.Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3089
.Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
3090
.Default(false);
3091
}
3092
3093
/// parseDirectiveInsn
3094
/// ::= .insn [ format encoding, (operands (, operands)*) ]
3095
/// ::= .insn [ length, value ]
3096
/// ::= .insn [ value ]
3097
bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3098
MCAsmParser &Parser = getParser();
3099
3100
bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3101
getSTI().hasFeature(RISCV::FeatureStdExtZca);
3102
3103
// Expect instruction format as identifier.
3104
StringRef Format;
3105
SMLoc ErrorLoc = Parser.getTok().getLoc();
3106
if (Parser.parseIdentifier(Format)) {
3107
// Try parsing .insn [length], value
3108
int64_t Length = 0;
3109
int64_t Value = 0;
3110
if (Parser.parseIntToken(
3111
Value, "expected instruction format or an integer constant"))
3112
return true;
3113
if (Parser.parseOptionalToken(AsmToken::Comma)) {
3114
Length = Value;
3115
if (Parser.parseIntToken(Value, "expected an integer constant"))
3116
return true;
3117
}
3118
3119
// TODO: Add support for long instructions
3120
int64_t RealLength = (Value & 3) == 3 ? 4 : 2;
3121
if (!isUIntN(RealLength * 8, Value))
3122
return Error(ErrorLoc, "invalid operand for instruction");
3123
if (RealLength == 2 && !AllowC)
3124
return Error(ErrorLoc, "compressed instructions are not allowed");
3125
if (Length != 0 && Length != RealLength)
3126
return Error(ErrorLoc, "instruction length mismatch");
3127
3128
if (getParser().parseEOL("invalid operand for instruction")) {
3129
getParser().eatToEndOfStatement();
3130
return true;
3131
}
3132
3133
emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn16
3134
: RISCV::Insn32)
3135
.addImm(Value));
3136
return false;
3137
}
3138
3139
if (!isValidInsnFormat(Format, AllowC))
3140
return Error(ErrorLoc, "invalid instruction format");
3141
3142
std::string FormatName = (".insn_" + Format).str();
3143
3144
ParseInstructionInfo Info;
3145
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
3146
3147
if (ParseInstruction(Info, FormatName, L, Operands))
3148
return true;
3149
3150
unsigned Opcode;
3151
uint64_t ErrorInfo;
3152
return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3153
ErrorInfo,
3154
/*MatchingInlineAsm=*/false);
3155
}
3156
3157
/// parseDirectiveVariantCC
3158
/// ::= .variant_cc symbol
3159
bool RISCVAsmParser::parseDirectiveVariantCC() {
3160
StringRef Name;
3161
if (getParser().parseIdentifier(Name))
3162
return TokError("expected symbol name");
3163
if (parseEOL())
3164
return true;
3165
getTargetStreamer().emitDirectiveVariantCC(
3166
*getContext().getOrCreateSymbol(Name));
3167
return false;
3168
}
3169
3170
void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3171
MCInst CInst;
3172
bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3173
if (Res)
3174
++RISCVNumInstrsCompressed;
3175
S.emitInstruction((Res ? CInst : Inst), getSTI());
3176
}
3177
3178
void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3179
MCStreamer &Out) {
3180
SmallVector<MCInst, 8> Seq;
3181
RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3182
3183
for (MCInst &Inst : Seq) {
3184
emitToStreamer(Out, Inst);
3185
}
3186
}
3187
3188
void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
3189
const MCExpr *Symbol,
3190
RISCVMCExpr::VariantKind VKHi,
3191
unsigned SecondOpcode, SMLoc IDLoc,
3192
MCStreamer &Out) {
3193
// A pair of instructions for PC-relative addressing; expands to
3194
// TmpLabel: AUIPC TmpReg, VKHi(symbol)
3195
// OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3196
MCContext &Ctx = getContext();
3197
3198
MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3199
Out.emitLabel(TmpLabel);
3200
3201
const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
3202
emitToStreamer(
3203
Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
3204
3205
const MCExpr *RefToLinkTmpLabel =
3206
RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
3207
RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
3208
3209
emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3210
.addOperand(DestReg)
3211
.addOperand(TmpReg)
3212
.addExpr(RefToLinkTmpLabel));
3213
}
3214
3215
void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3216
MCStreamer &Out) {
3217
// The load local address pseudo-instruction "lla" is used in PC-relative
3218
// addressing of local symbols:
3219
// lla rdest, symbol
3220
// expands to
3221
// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3222
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3223
MCOperand DestReg = Inst.getOperand(0);
3224
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3225
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3226
RISCV::ADDI, IDLoc, Out);
3227
}
3228
3229
void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3230
MCStreamer &Out) {
3231
// The load global address pseudo-instruction "lga" is used in GOT-indirect
3232
// addressing of global symbols:
3233
// lga rdest, symbol
3234
// expands to
3235
// TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3236
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3237
MCOperand DestReg = Inst.getOperand(0);
3238
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3239
unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3240
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3241
SecondOpcode, IDLoc, Out);
3242
}
3243
3244
void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3245
MCStreamer &Out) {
3246
// The load address pseudo-instruction "la" is used in PC-relative and
3247
// GOT-indirect addressing of global symbols:
3248
// la rdest, symbol
3249
// is an alias for either (for non-PIC)
3250
// lla rdest, symbol
3251
// or (for PIC)
3252
// lga rdest, symbol
3253
if (ParserOptions.IsPicEnabled)
3254
emitLoadGlobalAddress(Inst, IDLoc, Out);
3255
else
3256
emitLoadLocalAddress(Inst, IDLoc, Out);
3257
}
3258
3259
void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3260
MCStreamer &Out) {
3261
// The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3262
// initial-exec TLS model addressing of global symbols:
3263
// la.tls.ie rdest, symbol
3264
// expands to
3265
// TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3266
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3267
MCOperand DestReg = Inst.getOperand(0);
3268
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3269
unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3270
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
3271
SecondOpcode, IDLoc, Out);
3272
}
3273
3274
void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3275
MCStreamer &Out) {
3276
// The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3277
// global-dynamic TLS model addressing of global symbols:
3278
// la.tls.gd rdest, symbol
3279
// expands to
3280
// TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3281
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3282
MCOperand DestReg = Inst.getOperand(0);
3283
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3284
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
3285
RISCV::ADDI, IDLoc, Out);
3286
}
3287
3288
void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3289
SMLoc IDLoc, MCStreamer &Out,
3290
bool HasTmpReg) {
3291
// The load/store pseudo-instruction does a pc-relative load with
3292
// a symbol.
3293
//
3294
// The expansion looks like this
3295
//
3296
// TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3297
// [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3298
unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3299
MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
3300
unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3301
MCOperand TmpReg = Inst.getOperand(0);
3302
const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3303
emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3304
Opcode, IDLoc, Out);
3305
}
3306
3307
void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3308
int64_t Width, SMLoc IDLoc,
3309
MCStreamer &Out) {
3310
// The sign/zero extend pseudo-instruction does two shifts, with the shift
3311
// amounts dependent on the XLEN.
3312
//
3313
// The expansion looks like this
3314
//
3315
// SLLI rd, rs, XLEN - Width
3316
// SR[A|R]I rd, rd, XLEN - Width
3317
MCOperand DestReg = Inst.getOperand(0);
3318
MCOperand SourceReg = Inst.getOperand(1);
3319
3320
unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3321
int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3322
3323
assert(ShAmt > 0 && "Shift amount must be non-zero.");
3324
3325
emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3326
.addOperand(DestReg)
3327
.addOperand(SourceReg)
3328
.addImm(ShAmt));
3329
3330
emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3331
.addOperand(DestReg)
3332
.addOperand(DestReg)
3333
.addImm(ShAmt));
3334
}
3335
3336
void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3337
MCStreamer &Out) {
3338
if (Inst.getNumOperands() == 3) {
3339
// unmasked va >= x
3340
//
3341
// pseudoinstruction: vmsge{u}.vx vd, va, x
3342
// expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3343
emitToStreamer(Out, MCInstBuilder(Opcode)
3344
.addOperand(Inst.getOperand(0))
3345
.addOperand(Inst.getOperand(1))
3346
.addOperand(Inst.getOperand(2))
3347
.addReg(RISCV::NoRegister)
3348
.setLoc(IDLoc));
3349
emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3350
.addOperand(Inst.getOperand(0))
3351
.addOperand(Inst.getOperand(0))
3352
.addOperand(Inst.getOperand(0))
3353
.setLoc(IDLoc));
3354
} else if (Inst.getNumOperands() == 4) {
3355
// masked va >= x, vd != v0
3356
//
3357
// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3358
// expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3359
assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3360
"The destination register should not be V0.");
3361
emitToStreamer(Out, MCInstBuilder(Opcode)
3362
.addOperand(Inst.getOperand(0))
3363
.addOperand(Inst.getOperand(1))
3364
.addOperand(Inst.getOperand(2))
3365
.addOperand(Inst.getOperand(3))
3366
.setLoc(IDLoc));
3367
emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3368
.addOperand(Inst.getOperand(0))
3369
.addOperand(Inst.getOperand(0))
3370
.addReg(RISCV::V0)
3371
.setLoc(IDLoc));
3372
} else if (Inst.getNumOperands() == 5 &&
3373
Inst.getOperand(0).getReg() == RISCV::V0) {
3374
// masked va >= x, vd == v0
3375
//
3376
// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3377
// expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3378
assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3379
"The destination register should be V0.");
3380
assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3381
"The temporary vector register should not be V0.");
3382
emitToStreamer(Out, MCInstBuilder(Opcode)
3383
.addOperand(Inst.getOperand(1))
3384
.addOperand(Inst.getOperand(2))
3385
.addOperand(Inst.getOperand(3))
3386
.addReg(RISCV::NoRegister)
3387
.setLoc(IDLoc));
3388
emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3389
.addOperand(Inst.getOperand(0))
3390
.addOperand(Inst.getOperand(0))
3391
.addOperand(Inst.getOperand(1))
3392
.setLoc(IDLoc));
3393
} else if (Inst.getNumOperands() == 5) {
3394
// masked va >= x, any vd
3395
//
3396
// pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3397
// expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3398
// vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3399
assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3400
"The temporary vector register should not be V0.");
3401
emitToStreamer(Out, MCInstBuilder(Opcode)
3402
.addOperand(Inst.getOperand(1))
3403
.addOperand(Inst.getOperand(2))
3404
.addOperand(Inst.getOperand(3))
3405
.addReg(RISCV::NoRegister)
3406
.setLoc(IDLoc));
3407
emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3408
.addOperand(Inst.getOperand(1))
3409
.addReg(RISCV::V0)
3410
.addOperand(Inst.getOperand(1))
3411
.setLoc(IDLoc));
3412
emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3413
.addOperand(Inst.getOperand(0))
3414
.addOperand(Inst.getOperand(0))
3415
.addReg(RISCV::V0)
3416
.setLoc(IDLoc));
3417
emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3418
.addOperand(Inst.getOperand(0))
3419
.addOperand(Inst.getOperand(1))
3420
.addOperand(Inst.getOperand(0))
3421
.setLoc(IDLoc));
3422
}
3423
}
3424
3425
bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3426
OperandVector &Operands) {
3427
assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3428
assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3429
if (Inst.getOperand(2).getReg() != RISCV::X4) {
3430
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3431
return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3432
"%tprel_add modifier");
3433
}
3434
3435
return false;
3436
}
3437
3438
bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3439
OperandVector &Operands) {
3440
assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3441
assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3442
if (Inst.getOperand(0).getReg() != RISCV::X5) {
3443
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3444
return Error(ErrorLoc, "the output operand must be t0/x5 when using "
3445
"%tlsdesc_call modifier");
3446
}
3447
3448
return false;
3449
}
3450
3451
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3452
return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
3453
llvm::SMLoc());
3454
}
3455
3456
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3457
return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3458
llvm::SMLoc());
3459
}
3460
3461
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3462
return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3463
llvm::SMLoc());
3464
}
3465
3466
bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3467
OperandVector &Operands) {
3468
unsigned Opcode = Inst.getOpcode();
3469
3470
if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3471
Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3472
unsigned DestReg = Inst.getOperand(0).getReg();
3473
unsigned TempReg = Inst.getOperand(1).getReg();
3474
if (DestReg == TempReg) {
3475
SMLoc Loc = Operands.back()->getStartLoc();
3476
return Error(Loc, "the temporary vector register cannot be the same as "
3477
"the destination register");
3478
}
3479
}
3480
3481
if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3482
Opcode == RISCV::TH_LWD) {
3483
unsigned Rd1 = Inst.getOperand(0).getReg();
3484
unsigned Rd2 = Inst.getOperand(1).getReg();
3485
unsigned Rs1 = Inst.getOperand(2).getReg();
3486
// The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3487
if (Rs1 == Rd1 && Rs1 == Rd2) {
3488
SMLoc Loc = Operands[1]->getStartLoc();
3489
return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");
3490
}
3491
}
3492
3493
if (Opcode == RISCV::CM_MVSA01) {
3494
unsigned Rd1 = Inst.getOperand(0).getReg();
3495
unsigned Rd2 = Inst.getOperand(1).getReg();
3496
if (Rd1 == Rd2) {
3497
SMLoc Loc = Operands[1]->getStartLoc();
3498
return Error(Loc, "rs1 and rs2 must be different");
3499
}
3500
}
3501
3502
bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3503
Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3504
bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3505
// The last operand of XTHeadMemPair instructions must be constant 3 or 4
3506
// depending on the data width.
3507
if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3508
SMLoc Loc = Operands.back()->getStartLoc();
3509
return Error(Loc, "operand must be constant 3");
3510
} else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3511
SMLoc Loc = Operands.back()->getStartLoc();
3512
return Error(Loc, "operand must be constant 4");
3513
}
3514
3515
const MCInstrDesc &MCID = MII.get(Opcode);
3516
if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3517
return false;
3518
3519
if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3520
Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3521
// Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3522
unsigned VCIXDst = Inst.getOperand(0).getReg();
3523
SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3524
if (MCID.TSFlags & RISCVII::VS1Constraint) {
3525
unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3526
if (VCIXDst == VCIXRs1)
3527
return Error(VCIXDstLoc, "the destination vector register group cannot"
3528
" overlap the source vector register group");
3529
}
3530
if (MCID.TSFlags & RISCVII::VS2Constraint) {
3531
unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3532
if (VCIXDst == VCIXRs2)
3533
return Error(VCIXDstLoc, "the destination vector register group cannot"
3534
" overlap the source vector register group");
3535
}
3536
return false;
3537
}
3538
3539
unsigned DestReg = Inst.getOperand(0).getReg();
3540
unsigned Offset = 0;
3541
int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
3542
if (TiedOp == 0)
3543
Offset = 1;
3544
3545
// Operands[1] will be the first operand, DestReg.
3546
SMLoc Loc = Operands[1]->getStartLoc();
3547
if (MCID.TSFlags & RISCVII::VS2Constraint) {
3548
unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();
3549
if (DestReg == CheckReg)
3550
return Error(Loc, "the destination vector register group cannot overlap"
3551
" the source vector register group");
3552
}
3553
if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
3554
unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();
3555
if (DestReg == CheckReg)
3556
return Error(Loc, "the destination vector register group cannot overlap"
3557
" the source vector register group");
3558
}
3559
if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3560
// vadc, vsbc are special cases. These instructions have no mask register.
3561
// The destination register could not be V0.
3562
if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3563
Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3564
Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3565
Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3566
Opcode == RISCV::VMERGE_VXM)
3567
return Error(Loc, "the destination vector register group cannot be V0");
3568
3569
// Regardless masked or unmasked version, the number of operands is the
3570
// same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3571
// actually. We need to check the last operand to ensure whether it is
3572
// masked or not.
3573
unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3574
assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3575
"Unexpected register for mask operand");
3576
3577
if (DestReg == CheckReg)
3578
return Error(Loc, "the destination vector register group cannot overlap"
3579
" the mask register");
3580
}
3581
return false;
3582
}
3583
3584
bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3585
OperandVector &Operands,
3586
MCStreamer &Out) {
3587
Inst.setLoc(IDLoc);
3588
3589
switch (Inst.getOpcode()) {
3590
default:
3591
break;
3592
case RISCV::PseudoLLAImm:
3593
case RISCV::PseudoLAImm:
3594
case RISCV::PseudoLI: {
3595
MCRegister Reg = Inst.getOperand(0).getReg();
3596
const MCOperand &Op1 = Inst.getOperand(1);
3597
if (Op1.isExpr()) {
3598
// We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3599
// Just convert to an addi. This allows compatibility with gas.
3600
emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3601
.addReg(Reg)
3602
.addReg(RISCV::X0)
3603
.addExpr(Op1.getExpr()));
3604
return false;
3605
}
3606
int64_t Imm = Inst.getOperand(1).getImm();
3607
// On RV32 the immediate here can either be a signed or an unsigned
3608
// 32-bit number. Sign extension has to be performed to ensure that Imm
3609
// represents the expected signed 64-bit number.
3610
if (!isRV64())
3611
Imm = SignExtend64<32>(Imm);
3612
emitLoadImm(Reg, Imm, Out);
3613
return false;
3614
}
3615
case RISCV::PseudoLLA:
3616
emitLoadLocalAddress(Inst, IDLoc, Out);
3617
return false;
3618
case RISCV::PseudoLGA:
3619
emitLoadGlobalAddress(Inst, IDLoc, Out);
3620
return false;
3621
case RISCV::PseudoLA:
3622
emitLoadAddress(Inst, IDLoc, Out);
3623
return false;
3624
case RISCV::PseudoLA_TLS_IE:
3625
emitLoadTLSIEAddress(Inst, IDLoc, Out);
3626
return false;
3627
case RISCV::PseudoLA_TLS_GD:
3628
emitLoadTLSGDAddress(Inst, IDLoc, Out);
3629
return false;
3630
case RISCV::PseudoLB:
3631
emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3632
return false;
3633
case RISCV::PseudoLBU:
3634
emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3635
return false;
3636
case RISCV::PseudoLH:
3637
emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3638
return false;
3639
case RISCV::PseudoLHU:
3640
emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3641
return false;
3642
case RISCV::PseudoLW:
3643
emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3644
return false;
3645
case RISCV::PseudoLWU:
3646
emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3647
return false;
3648
case RISCV::PseudoLD:
3649
emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3650
return false;
3651
case RISCV::PseudoFLH:
3652
emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3653
return false;
3654
case RISCV::PseudoFLW:
3655
emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3656
return false;
3657
case RISCV::PseudoFLD:
3658
emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3659
return false;
3660
case RISCV::PseudoSB:
3661
emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3662
return false;
3663
case RISCV::PseudoSH:
3664
emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3665
return false;
3666
case RISCV::PseudoSW:
3667
emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3668
return false;
3669
case RISCV::PseudoSD:
3670
emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3671
return false;
3672
case RISCV::PseudoFSH:
3673
emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3674
return false;
3675
case RISCV::PseudoFSW:
3676
emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3677
return false;
3678
case RISCV::PseudoFSD:
3679
emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3680
return false;
3681
case RISCV::PseudoAddTPRel:
3682
if (checkPseudoAddTPRel(Inst, Operands))
3683
return true;
3684
break;
3685
case RISCV::PseudoTLSDESCCall:
3686
if (checkPseudoTLSDESCCall(Inst, Operands))
3687
return true;
3688
break;
3689
case RISCV::PseudoSEXT_B:
3690
emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3691
return false;
3692
case RISCV::PseudoSEXT_H:
3693
emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3694
return false;
3695
case RISCV::PseudoZEXT_H:
3696
emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3697
return false;
3698
case RISCV::PseudoZEXT_W:
3699
emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3700
return false;
3701
case RISCV::PseudoVMSGEU_VX:
3702
case RISCV::PseudoVMSGEU_VX_M:
3703
case RISCV::PseudoVMSGEU_VX_M_T:
3704
emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3705
return false;
3706
case RISCV::PseudoVMSGE_VX:
3707
case RISCV::PseudoVMSGE_VX_M:
3708
case RISCV::PseudoVMSGE_VX_M_T:
3709
emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3710
return false;
3711
case RISCV::PseudoVMSGE_VI:
3712
case RISCV::PseudoVMSLT_VI: {
3713
// These instructions are signed and so is immediate so we can subtract one
3714
// and change the opcode.
3715
int64_t Imm = Inst.getOperand(2).getImm();
3716
unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3717
: RISCV::VMSLE_VI;
3718
emitToStreamer(Out, MCInstBuilder(Opc)
3719
.addOperand(Inst.getOperand(0))
3720
.addOperand(Inst.getOperand(1))
3721
.addImm(Imm - 1)
3722
.addOperand(Inst.getOperand(3))
3723
.setLoc(IDLoc));
3724
return false;
3725
}
3726
case RISCV::PseudoVMSGEU_VI:
3727
case RISCV::PseudoVMSLTU_VI: {
3728
int64_t Imm = Inst.getOperand(2).getImm();
3729
// Unsigned comparisons are tricky because the immediate is signed. If the
3730
// immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3731
// false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3732
// vmsne v0, v1, v1 which is always false.
3733
if (Imm == 0) {
3734
unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3735
? RISCV::VMSEQ_VV
3736
: RISCV::VMSNE_VV;
3737
emitToStreamer(Out, MCInstBuilder(Opc)
3738
.addOperand(Inst.getOperand(0))
3739
.addOperand(Inst.getOperand(1))
3740
.addOperand(Inst.getOperand(1))
3741
.addOperand(Inst.getOperand(3))
3742
.setLoc(IDLoc));
3743
} else {
3744
// Other immediate values can subtract one like signed.
3745
unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3746
? RISCV::VMSGTU_VI
3747
: RISCV::VMSLEU_VI;
3748
emitToStreamer(Out, MCInstBuilder(Opc)
3749
.addOperand(Inst.getOperand(0))
3750
.addOperand(Inst.getOperand(1))
3751
.addImm(Imm - 1)
3752
.addOperand(Inst.getOperand(3))
3753
.setLoc(IDLoc));
3754
}
3755
3756
return false;
3757
}
3758
}
3759
3760
emitToStreamer(Out, Inst);
3761
return false;
3762
}
3763
3764
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() {
3765
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
3766
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
3767
}
3768
3769