[LoongArch] Check msb is not less than lsb for the bstr{ins/pick}.{w/d} instructions

Differential Revision: https://reviews.llvm.org/D124825
This commit is contained in:
Weining Lu 2022-05-03 11:06:24 +08:00
parent 9519dacab7
commit 24532d05f8
3 changed files with 52 additions and 0 deletions

View File

@ -43,6 +43,8 @@ class LoongArchAsmParser : public MCTargetAsmParser {
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override;
unsigned checkTargetMatchPredicate(MCInst &Inst) override;
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
@ -66,6 +68,7 @@ class LoongArchAsmParser : public MCTargetAsmParser {
public:
enum LoongArchMatchResultTy {
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
Match_RequiresMsbNotLessThanLsb,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "LoongArchGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@ -369,6 +372,32 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return false;
}
unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
switch (Inst.getOpcode()) {
default:
break;
case LoongArch::BSTRINS_W:
case LoongArch::BSTRINS_D:
case LoongArch::BSTRPICK_W:
case LoongArch::BSTRPICK_D: {
unsigned Opc = Inst.getOpcode();
const signed Msb =
(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
? Inst.getOperand(3).getImm()
: Inst.getOperand(2).getImm();
const signed Lsb =
(Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
? Inst.getOperand(4).getImm()
: Inst.getOperand(3).getImm();
if (Msb < Lsb)
return Match_RequiresMsbNotLessThanLsb;
return Match_Success;
}
}
return Match_Success;
}
unsigned
LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
unsigned Kind) {
@ -455,6 +484,11 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
switch (Result) {
default:
break;
case Match_RequiresMsbNotLessThanLsb: {
SMLoc ErrorStart = Operands[3]->getStartLoc();
return Error(ErrorStart, "msb is less than lsb",
SMRange(ErrorStart, Operands[4]->getEndLoc()));
}
case Match_InvalidUImm2:
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
/*Upper=*/(1 << 2) - 1);

View File

@ -180,3 +180,12 @@ fadd.d $fa0, $fa0, $fa0
## Using floating point registers when integer registers are expected
sll.w $a0, $a0, $fa0
# CHECK: :[[#@LINE-1]]:18: error: invalid operand for instruction
## msbw < lsbw
# CHECK: :[[#@LINE+1]]:21: error: msb is less than lsb
bstrins.w $a0, $a0, 1, 2
# CHECK: ^~~~
# CHECK: :[[#@LINE+1]]:22: error: msb is less than lsb
bstrpick.w $a0, $a0, 30, 31
# CHECK: ^~~~~~

View File

@ -64,3 +64,12 @@ lu32i.d $a0, -0x80001
# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
pcaddu18i $a0, 0x80000
# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
## msbd < lsbd
# CHECK: :[[#@LINE+1]]:21: error: msb is less than lsb
bstrins.d $a0, $a0, 1, 2
# CHECK: ^~~~
# CHECK: :[[#@LINE+1]]:22: error: msb is less than lsb
bstrpick.d $a0, $a0, 32, 63
# CHECK: ^~~~~~