From 24532d05f8da67058c41ea4ad885c96ee918aa57 Mon Sep 17 00:00:00 2001 From: Weining Lu Date: Tue, 3 May 2022 11:06:24 +0800 Subject: [PATCH] [LoongArch] Check msb is not less than lsb for the bstr{ins/pick}.{w/d} instructions Differential Revision: https://reviews.llvm.org/D124825 --- .../AsmParser/LoongArchAsmParser.cpp | 34 +++++++++++++++++++ .../test/MC/LoongArch/Basic/Integer/invalid.s | 9 +++++ .../MC/LoongArch/Basic/Integer/invalid64.s | 9 +++++ 3 files changed, 52 insertions(+) diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 8f6331d7d699..0c9518233751 100644 --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -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); diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s index bd01eb49d11c..94b3976f5bfd 100644 --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s @@ -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: ^~~~~~ diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s index e5249f04f492..e7e6fb09840b 100644 --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s @@ -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: ^~~~~~