8
8
// ===----------------------------------------------------------------------===//
9
9
10
10
#include " MCTargetDesc/RISCVBaseInfo.h"
11
+ #include " MCTargetDesc/RISCVMCExpr.h"
11
12
#include " MCTargetDesc/RISCVMCTargetDesc.h"
12
13
#include " llvm/ADT/STLExtras.h"
13
14
#include " llvm/ADT/StringSwitch.h"
@@ -53,6 +54,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
53
54
OperandMatchResultTy parseImmediate (OperandVector &Operands);
54
55
OperandMatchResultTy parseRegister (OperandVector &Operands);
55
56
OperandMatchResultTy parseMemOpBaseReg (OperandVector &Operands);
57
+ OperandMatchResultTy parseOperandWithModifier (OperandVector &Operands);
56
58
57
59
bool parseOperand (OperandVector &Operands);
58
60
@@ -64,6 +66,10 @@ class RISCVAsmParser : public MCTargetAsmParser {
64
66
#undef GET_OPERAND_DIAGNOSTIC_TYPES
65
67
};
66
68
69
+ static bool classifySymbolRef (const MCExpr *Expr,
70
+ RISCVMCExpr::VariantKind &Kind,
71
+ int64_t &Addend);
72
+
67
73
RISCVAsmParser (const MCSubtargetInfo &STI, MCAsmParser &Parser,
68
74
const MCInstrInfo &MII, const MCTargetOptions &Options)
69
75
: MCTargetAsmParser(Options, STI) {
@@ -121,13 +127,32 @@ struct RISCVOperand : public MCParsedAsmOperand {
121
127
bool isImm () const override { return Kind == Immediate; }
122
128
bool isMem () const override { return false ; }
123
129
124
- bool isConstantImm () const {
125
- return isImm () && dyn_cast<MCConstantExpr>(getImm ());
126
- }
127
-
128
- int64_t getConstantImm () const {
130
+ bool evaluateConstantImm (int64_t &Imm, RISCVMCExpr::VariantKind &VK) const {
129
131
const MCExpr *Val = getImm ();
130
- return static_cast <const MCConstantExpr *>(Val)->getValue ();
132
+ bool Ret = false ;
133
+ if (auto *RE = dyn_cast<RISCVMCExpr>(Val)) {
134
+ Ret = RE->evaluateAsConstant (Imm);
135
+ VK = RE->getKind ();
136
+ } else if (auto CE = dyn_cast<MCConstantExpr>(Val)) {
137
+ Ret = true ;
138
+ VK = RISCVMCExpr::VK_RISCV_None;
139
+ Imm = CE->getValue ();
140
+ }
141
+ return Ret;
142
+ }
143
+
144
+ // True if operand is a symbol with no modifiers, or a constant with no
145
+ // modifiers and isShiftedInt<N-1, 1>(Op).
146
+ template <int N> bool isBareSimmNLsb0 () const {
147
+ int64_t Imm;
148
+ RISCVMCExpr::VariantKind VK;
149
+ bool IsConstantImm = evaluateConstantImm (Imm, VK);
150
+ bool IsValid;
151
+ if (!IsConstantImm)
152
+ IsValid = RISCVAsmParser::classifySymbolRef (getImm (), VK, Imm);
153
+ else
154
+ IsValid = isShiftedInt<N - 1 , 1 >(Imm);
155
+ return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
131
156
}
132
157
133
158
// Predicate methods for AsmOperands defined in RISCVInstrInfo.td
@@ -158,28 +183,49 @@ struct RISCVOperand : public MCParsedAsmOperand {
158
183
}
159
184
160
185
bool isUImm5 () const {
161
- return (isConstantImm () && isUInt<5 >(getConstantImm ()));
186
+ int64_t Imm;
187
+ RISCVMCExpr::VariantKind VK;
188
+ bool IsConstantImm = evaluateConstantImm (Imm, VK);
189
+ return IsConstantImm && isUInt<5 >(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
162
190
}
163
191
164
192
bool isSImm12 () const {
165
- return (isConstantImm () && isInt<12 >(getConstantImm ()));
193
+ RISCVMCExpr::VariantKind VK;
194
+ int64_t Imm;
195
+ bool IsValid;
196
+ bool IsConstantImm = evaluateConstantImm (Imm, VK);
197
+ if (!IsConstantImm)
198
+ IsValid = RISCVAsmParser::classifySymbolRef (getImm (), VK, Imm);
199
+ else
200
+ IsValid = isInt<12 >(Imm);
201
+ return IsValid &&
202
+ (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
166
203
}
167
204
168
205
bool isUImm12 () const {
169
- return (isConstantImm () && isUInt<12 >(getConstantImm ()));
206
+ int64_t Imm;
207
+ RISCVMCExpr::VariantKind VK;
208
+ bool IsConstantImm = evaluateConstantImm (Imm, VK);
209
+ return IsConstantImm && isUInt<12 >(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
170
210
}
171
211
172
- bool isSImm13Lsb0 () const {
173
- return (isConstantImm () && isShiftedInt<12 , 1 >(getConstantImm ()));
174
- }
212
+ bool isSImm13Lsb0 () const { return isBareSimmNLsb0<13 >(); }
175
213
176
214
bool isUImm20 () const {
177
- return (isConstantImm () && isUInt<20 >(getConstantImm ()));
215
+ RISCVMCExpr::VariantKind VK;
216
+ int64_t Imm;
217
+ bool IsValid;
218
+ bool IsConstantImm = evaluateConstantImm (Imm, VK);
219
+ if (!IsConstantImm)
220
+ IsValid = RISCVAsmParser::classifySymbolRef (getImm (), VK, Imm);
221
+ else
222
+ IsValid = isUInt<20 >(Imm);
223
+ return IsValid && (VK == RISCVMCExpr::VK_RISCV_None ||
224
+ VK == RISCVMCExpr::VK_RISCV_HI ||
225
+ VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
178
226
}
179
227
180
- bool isSImm21Lsb0 () const {
181
- return (isConstantImm () && isShiftedInt<20 , 1 >(getConstantImm ()));
182
- }
228
+ bool isSImm21Lsb0 () const { return isBareSimmNLsb0<21 >(); }
183
229
184
230
// / getStartLoc - Gets location of the first token of this operand
185
231
SMLoc getStartLoc () const override { return StartLoc; }
@@ -234,7 +280,7 @@ struct RISCVOperand : public MCParsedAsmOperand {
234
280
}
235
281
236
282
static std::unique_ptr<RISCVOperand> createImm (const MCExpr *Val, SMLoc S,
237
- SMLoc E) {
283
+ SMLoc E, MCContext &Ctx ) {
238
284
auto Op = make_unique<RISCVOperand>(Immediate);
239
285
Op->Imm .Val = Val;
240
286
Op->StartLoc = S;
@@ -244,8 +290,17 @@ struct RISCVOperand : public MCParsedAsmOperand {
244
290
245
291
void addExpr (MCInst &Inst, const MCExpr *Expr) const {
246
292
assert (Expr && " Expr shouldn't be null!" );
247
- if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
248
- Inst.addOperand (MCOperand::createImm (CE->getValue ()));
293
+ int64_t Imm = 0 ;
294
+ bool IsConstant = false ;
295
+ if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
296
+ IsConstant = RE->evaluateAsConstant (Imm);
297
+ } else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
298
+ IsConstant = true ;
299
+ Imm = CE->getValue ();
300
+ }
301
+
302
+ if (IsConstant)
303
+ Inst.addOperand (MCOperand::createImm (Imm));
249
304
else
250
305
Inst.addOperand (MCOperand::createExpr (Expr));
251
306
}
@@ -411,9 +466,51 @@ OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
411
466
Res = MCSymbolRefExpr::create (Sym, MCSymbolRefExpr::VK_None, getContext ());
412
467
break ;
413
468
}
469
+ case AsmToken::Percent:
470
+ return parseOperandWithModifier (Operands);
471
+ }
472
+
473
+ Operands.push_back (RISCVOperand::createImm (Res, S, E, getContext ()));
474
+ return MatchOperand_Success;
475
+ }
476
+
477
+ OperandMatchResultTy
478
+ RISCVAsmParser::parseOperandWithModifier (OperandVector &Operands) {
479
+ SMLoc S = getLoc ();
480
+ SMLoc E = SMLoc::getFromPointer (S.getPointer () - 1 );
481
+
482
+ if (getLexer ().getKind () != AsmToken::Percent) {
483
+ Error (getLoc (), " expected '%' for operand modifier" );
484
+ return MatchOperand_ParseFail;
485
+ }
486
+
487
+ getParser ().Lex (); // Eat '%'
488
+
489
+ if (getLexer ().getKind () != AsmToken::Identifier) {
490
+ Error (getLoc (), " expected valid identifier for operand modifier" );
491
+ return MatchOperand_ParseFail;
492
+ }
493
+ StringRef Identifier = getParser ().getTok ().getIdentifier ();
494
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName (Identifier);
495
+ if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
496
+ Error (getLoc (), " unrecognized operand modifier" );
497
+ return MatchOperand_ParseFail;
498
+ }
499
+
500
+ getParser ().Lex (); // Eat the identifier
501
+ if (getLexer ().getKind () != AsmToken::LParen) {
502
+ Error (getLoc (), " expected '('" );
503
+ return MatchOperand_ParseFail;
504
+ }
505
+ getParser ().Lex (); // Eat '('
506
+
507
+ const MCExpr *SubExpr;
508
+ if (getParser ().parseParenExpression (SubExpr, E)) {
509
+ return MatchOperand_ParseFail;
414
510
}
415
511
416
- Operands.push_back (RISCVOperand::createImm (Res, S, E));
512
+ const MCExpr *ModExpr = RISCVMCExpr::create (SubExpr, VK, getContext ());
513
+ Operands.push_back (RISCVOperand::createImm (ModExpr, S, E, getContext ()));
417
514
return MatchOperand_Success;
418
515
}
419
516
@@ -498,6 +595,51 @@ bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
498
595
return false ;
499
596
}
500
597
598
+ bool RISCVAsmParser::classifySymbolRef (const MCExpr *Expr,
599
+ RISCVMCExpr::VariantKind &Kind,
600
+ int64_t &Addend) {
601
+ Kind = RISCVMCExpr::VK_RISCV_None;
602
+ Addend = 0 ;
603
+
604
+ if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
605
+ Kind = RE->getKind ();
606
+ Expr = RE->getSubExpr ();
607
+ }
608
+
609
+ // It's a simple symbol reference or constant with no addend.
610
+ if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
611
+ return true ;
612
+
613
+ const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
614
+ if (!BE)
615
+ return false ;
616
+
617
+ if (!isa<MCSymbolRefExpr>(BE->getLHS ()))
618
+ return false ;
619
+
620
+ if (BE->getOpcode () != MCBinaryExpr::Add &&
621
+ BE->getOpcode () != MCBinaryExpr::Sub)
622
+ return false ;
623
+
624
+ // We are able to support the subtraction of two symbol references
625
+ if (BE->getOpcode () == MCBinaryExpr::Sub &&
626
+ isa<MCSymbolRefExpr>(BE->getRHS ()))
627
+ return true ;
628
+
629
+ // See if the addend is is a constant, otherwise there's more going
630
+ // on here than we can deal with.
631
+ auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS ());
632
+ if (!AddendExpr)
633
+ return false ;
634
+
635
+ Addend = AddendExpr->getValue ();
636
+ if (BE->getOpcode () == MCBinaryExpr::Sub)
637
+ Addend = -Addend;
638
+
639
+ // It's some symbol reference + a constant addend
640
+ return Kind != RISCVMCExpr::VK_RISCV_Invalid;
641
+ }
642
+
501
643
bool RISCVAsmParser::ParseDirective (AsmToken DirectiveID) { return true ; }
502
644
503
645
extern " C" void LLVMInitializeRISCVAsmParser () {
0 commit comments