Skip to content

Commit 1584014

Browse files
authored
[RISCV] Check that the stack adjust immediate for cm.push/pop* has the correct sign and is divisible by 16. (#85295)
To do this I've added a new AsmOperand for cm.push to expect a negative value. We also use that to customize the print function so that we don't need to detect cm.push opcode to add the negative sign. I've renamed some places that used Spimm to be StackAdj since that's what is being parsed. I'm still not about where we should use Spimm or StackAdj. I've removed the printSpimm helper function which in one usage printed the sp[5:4]<<4 value and the other usage printed the full stack adjustment. There wasn't anything interesting about how it was printed it just passed the value to the raw_stream. If there was something special needed, it's unclear whether it would be the same for the two different usages so I inlined it. One open question is whether we need to support stack adjustments expressed as an expression rather than a literal integer.
1 parent ac1af75 commit 1584014

File tree

8 files changed

+95
-36
lines changed

8 files changed

+95
-36
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,11 @@ class RISCVAsmParser : public MCTargetAsmParser {
213213
ParseStatus parseReglist(OperandVector &Operands);
214214
ParseStatus parseRegReg(OperandVector &Operands);
215215
ParseStatus parseRetval(OperandVector &Operands);
216-
ParseStatus parseZcmpSpimm(OperandVector &Operands);
216+
ParseStatus parseZcmpStackAdj(OperandVector &Operands,
217+
bool ExpectNegative = false);
218+
ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) {
219+
return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true);
220+
}
217221

218222
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
219223

@@ -1062,7 +1066,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
10621066
break;
10631067
case KindTy::Spimm:
10641068
OS << "<Spimm: ";
1065-
RISCVZC::printSpimm(Spimm.Val, OS);
1069+
OS << Spimm.Val;
10661070
OS << '>';
10671071
break;
10681072
case KindTy::RegReg:
@@ -1608,7 +1612,7 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16081612
ErrorLoc,
16091613
"operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
16101614
}
1611-
case Match_InvalidSpimm: {
1615+
case Match_InvalidStackAdj: {
16121616
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16131617
return Error(
16141618
ErrorLoc,
@@ -2583,16 +2587,18 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
25832587
return ParseStatus::Success;
25842588
}
25852589

2586-
ParseStatus RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) {
2587-
(void)parseOptionalToken(AsmToken::Minus);
2590+
ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2591+
bool ExpectNegative) {
2592+
bool Negative = parseOptionalToken(AsmToken::Minus);
25882593

25892594
SMLoc S = getLoc();
25902595
int64_t StackAdjustment = getLexer().getTok().getIntVal();
25912596
unsigned Spimm = 0;
25922597
unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
25932598

25942599
bool IsEABI = isRVE();
2595-
if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
2600+
if (Negative != ExpectNegative ||
2601+
!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
25962602
return ParseStatus::NoMatch;
25972603
Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
25982604
getLexer().Lex();

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,4 @@ void RISCVZC::printRlist(unsigned SlistEncode, raw_ostream &OS) {
236236
OS << "}";
237237
}
238238

239-
void RISCVZC::printSpimm(int64_t Spimm, raw_ostream &OS) { OS << Spimm; }
240-
241239
} // namespace llvm

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,15 +580,17 @@ inline static bool getSpimm(unsigned RlistVal, unsigned &SpimmVal,
580580
int64_t StackAdjustment, bool IsRV64, bool IsEABI) {
581581
if (RlistVal == RLISTENCODE::INVALID_RLIST)
582582
return false;
583-
unsigned stackAdj = getStackAdjBase(RlistVal, IsRV64, IsEABI);
584-
SpimmVal = (StackAdjustment - stackAdj) / 16;
583+
unsigned StackAdjBase = getStackAdjBase(RlistVal, IsRV64, IsEABI);
584+
StackAdjustment -= StackAdjBase;
585+
if (StackAdjustment % 16 != 0)
586+
return false;
587+
SpimmVal = StackAdjustment / 16;
585588
if (SpimmVal > 3)
586589
return false;
587590
return true;
588591
}
589592

590593
void printRlist(unsigned SlistEncode, raw_ostream &OS);
591-
void printSpimm(int64_t Spimm, raw_ostream &OS);
592594
} // namespace RISCVZC
593595

594596
} // namespace llvm

llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,24 +292,25 @@ void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo,
292292
O << ")";
293293
}
294294

295-
void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
296-
const MCSubtargetInfo &STI, raw_ostream &O) {
295+
void RISCVInstPrinter::printStackAdj(const MCInst *MI, unsigned OpNo,
296+
const MCSubtargetInfo &STI, raw_ostream &O,
297+
bool Negate) {
297298
int64_t Imm = MI->getOperand(OpNo).getImm();
298-
unsigned Opcode = MI->getOpcode();
299299
bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
300300
bool IsEABI = STI.hasFeature(RISCV::FeatureRVE);
301-
int64_t Spimm = 0;
301+
int64_t StackAdj = 0;
302302
auto RlistVal = MI->getOperand(0).getImm();
303303
assert(RlistVal != 16 && "Incorrect rlist.");
304304
auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64, IsEABI);
305-
Spimm = Imm + Base;
306-
assert((Spimm >= Base && Spimm <= Base + 48) && "Incorrect spimm");
307-
if (Opcode == RISCV::CM_PUSH)
308-
Spimm = -Spimm;
305+
StackAdj = Imm + Base;
306+
assert((StackAdj >= Base && StackAdj <= Base + 48) &&
307+
"Incorrect stack adjust");
308+
if (Negate)
309+
StackAdj = -StackAdj;
309310

310311
// RAII guard for ANSI color escape sequences
311312
WithMarkup ScopedMarkup = markup(O, Markup::Immediate);
312-
RISCVZC::printSpimm(Spimm, O);
313+
O << StackAdj;
313314
}
314315

315316
void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,13 @@ class RISCVInstPrinter : public MCInstPrinter {
5252
const MCSubtargetInfo &STI, raw_ostream &O);
5353
void printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
5454
raw_ostream &O);
55-
void printSpimm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
56-
raw_ostream &O);
55+
void printStackAdj(const MCInst *MI, unsigned OpNo,
56+
const MCSubtargetInfo &STI, raw_ostream &O,
57+
bool Negate = false);
58+
void printNegStackAdj(const MCInst *MI, unsigned OpNo,
59+
const MCSubtargetInfo &STI, raw_ostream &O) {
60+
return printStackAdj(MI, OpNo, STI, O, /*Negate*/ true);
61+
}
5762
void printRegReg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
5863
raw_ostream &O);
5964
// Autogenerated by tblgen.

llvm/lib/Target/RISCV/RISCVInstrInfoZc.td

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,20 @@ def RlistAsmOperand : AsmOperandClass {
4141
let DiagnosticType = "InvalidRlist";
4242
}
4343

44-
def SpimmAsmOperand : AsmOperandClass {
45-
let Name = "Spimm";
46-
let ParserMethod = "parseZcmpSpimm";
47-
let DiagnosticType = "InvalidSpimm";
44+
def StackAdjAsmOperand : AsmOperandClass {
45+
let Name = "StackAdj";
46+
let ParserMethod = "parseZcmpStackAdj";
47+
let DiagnosticType = "InvalidStackAdj";
48+
let PredicateMethod = "isSpimm";
49+
let RenderMethod = "addSpimmOperands";
50+
}
51+
52+
def NegStackAdjAsmOperand : AsmOperandClass {
53+
let Name = "NegStackAdj";
54+
let ParserMethod = "parseZcmpNegStackAdj";
55+
let DiagnosticType = "InvalidStackAdj";
56+
let PredicateMethod = "isSpimm";
57+
let RenderMethod = "addSpimmOperands";
4858
}
4959

5060
def rlist : Operand<OtherVT> {
@@ -59,11 +69,23 @@ def rlist : Operand<OtherVT> {
5969
// 0~3 Reserved for EABI
6070
return isUInt<4>(Imm) && Imm >= 4;
6171
}];
62-
}
72+
}
73+
74+
def stackadj : Operand<OtherVT> {
75+
let ParserMatchClass = StackAdjAsmOperand;
76+
let PrintMethod = "printStackAdj";
77+
let DecoderMethod = "decodeZcmpSpimm";
78+
let MCOperandPredicate = [{
79+
int64_t Imm;
80+
if (!MCOp.evaluateAsConstantImm(Imm))
81+
return false;
82+
return isShiftedUInt<2, 4>(Imm);
83+
}];
84+
}
6385

64-
def spimm : Operand<OtherVT> {
65-
let ParserMatchClass = SpimmAsmOperand;
66-
let PrintMethod = "printSpimm";
86+
def negstackadj : Operand<OtherVT> {
87+
let ParserMatchClass = NegStackAdjAsmOperand;
88+
let PrintMethod = "printNegStackAdj";
6789
let DecoderMethod = "decodeZcmpSpimm";
6890
let MCOperandPredicate = [{
6991
int64_t Imm;
@@ -124,14 +146,15 @@ class RVZcArith_r<bits<5> funct5, string OpcodeStr> :
124146
let Constraints = "$rd = $rd_wb";
125147
}
126148

127-
class RVInstZcCPPP<bits<5> funct5, string opcodestr>
128-
: RVInst16<(outs), (ins rlist:$rlist, spimm:$spimm),
129-
opcodestr, "$rlist, $spimm", [], InstFormatOther> {
149+
class RVInstZcCPPP<bits<5> funct5, string opcodestr,
150+
DAGOperand immtype = stackadj>
151+
: RVInst16<(outs), (ins rlist:$rlist, immtype:$stackadj),
152+
opcodestr, "$rlist, $stackadj", [], InstFormatOther> {
130153
bits<4> rlist;
131-
bits<16> spimm;
154+
bits<16> stackadj;
132155

133156
let Inst{1-0} = 0b10;
134-
let Inst{3-2} = spimm{5-4};
157+
let Inst{3-2} = stackadj{5-4};
135158
let Inst{7-4} = rlist;
136159
let Inst{12-8} = funct5;
137160
let Inst{15-13} = 0b101;
@@ -195,7 +218,7 @@ def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
195218

196219
let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp] in {
197220
let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2] in
198-
def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push">,
221+
def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push", negstackadj>,
199222
Sched<[WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
200223
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
201224
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,

llvm/test/MC/RISCV/rv32zcmp-invalid.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
1717
cm.popretz {ra, s0-s1}, 112
18+
19+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
20+
cm.push {ra}, 16
21+
22+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
23+
cm.pop {ra, s0-s1}, -32
24+
25+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
26+
cm.push {ra}, -8
27+
28+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
29+
cm.pop {ra, s0-s1}, -40

llvm/test/MC/RISCV/rv64zcmp-invalid.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
1717
cm.popretz {ra, s0-s1}, 112
18+
19+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
20+
cm.push {ra}, 16
21+
22+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
23+
cm.pop {ra, s0-s1}, -32
24+
25+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
26+
cm.push {ra}, -15
27+
28+
# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment
29+
cm.pop {ra, s0-s1}, -33

0 commit comments

Comments
 (0)