Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -260,6 +260,19 @@ (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO); } + bool isSImm6NonZero() const { + RISCVMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (!IsConstantImm) + IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); + else + IsValid = (isInt<6>(Imm) && (Imm != 0)); + return IsValid && + (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO); + } + bool isUImm6NonZero() const { int64_t Imm; RISCVMCExpr::VariantKind VK; @@ -338,11 +351,11 @@ bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } - bool isSImm10Lsb0000() const { + bool isSImm10Lsb0000NonZero() const { int64_t Imm; RISCVMCExpr::VariantKind VK; bool IsConstantImm = evaluateConstantImm(Imm, VK); - return IsConstantImm && isShiftedInt<6, 4>(Imm) && + return IsConstantImm && isShiftedInt<6, 4>(Imm) && (Imm != 0) && VK == RISCVMCExpr::VK_RISCV_None; } @@ -613,6 +626,10 @@ case Match_InvalidSImm6: return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1); + case Match_InvalidSImm6NonZero: + return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), + (1 << 5) - 1, + "immediate must be non-zero in the range"); case Match_InvalidUImm6NonZero: return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); case Match_InvalidUImm7Lsb00: @@ -639,10 +656,10 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, 4, (1 << 10) - 4, "immediate must be a multiple of 4 bytes in the range"); - case Match_InvalidSImm10Lsb0000: + case Match_InvalidSImm10Lsb0000NonZero: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16, - "immediate must be a multiple of 16 bytes in the range"); + "immediate must be a multiple of 16 bytes and non-zero in the range"); case Match_InvalidSImm12: return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1); Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -35,6 +35,13 @@ let DecoderMethod = "decodeSImmOperand<6>"; } +def simm6nonzero : Operand, + ImmLeaf(Imm) && (Imm != 0);}]> { + let ParserMatchClass = SImmAsmOperand<6, "NonZero">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<6>"; +} + def uimm6nonzero : Operand, ImmLeaf(Imm) && (Imm != 0);}]> { let ParserMatchClass = UImmAsmOperand<6, "NonZero">; @@ -91,9 +98,10 @@ } // A 10-bit signed immediate where the least significant four bits are zero. -def simm10_lsb0000 : Operand, - ImmLeaf(Imm);}]> { - let ParserMatchClass = SImmAsmOperand<10, "Lsb0000">; +def simm10_lsb0000nonzero : Operand, + ImmLeaf(Imm) && (Imm != 0);}]> { + let ParserMatchClass = SImmAsmOperand<10, "Lsb0000NonZero">; let EncoderMethod = "getImmOpValue"; let DecoderMethod = "decodeSImmOperand<10>"; } @@ -253,7 +261,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADDI : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb), - (ins GPRNoX0:$rd, simm6:$imm), + (ins GPRNoX0:$rd, simm6nonzero:$imm), "c.addi", "$rd, $imm"> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; @@ -282,7 +290,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb), - (ins SP:$rd, simm10_lsb0000:$imm), + (ins SP:$rd, simm10_lsb0000nonzero:$imm), "c.addi16sp", "$rd, $imm"> { let Constraints = "$rd = $rd_wb"; let Inst{12} = imm{9}; Index: test/MC/RISCV/rv32c-invalid.s =================================================================== --- test/MC/RISCV/rv32c-invalid.s +++ test/MC/RISCV/rv32c-invalid.s @@ -45,9 +45,13 @@ ## simm6 c.li t0, 128 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] -c.addi t0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] c.andi a0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +## simm6nonzero +c.addi t0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] + ## uimm6nonzero c.lui t0, 64 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [1, 63] c.lui t0, 0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [1, 63] @@ -71,6 +75,7 @@ c.addi4spn a0, sp, 0 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] c.addi4spn a0, sp, 1024 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] -## simm10_lsb0000 -c.addi16sp sp, -528 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-512, 496] -c.addi16sp sp, 512 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-512, 496] +## simm10_lsb0000nonzero +c.addi16sp sp, -528 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496] +c.addi16sp sp, 512 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496] +c.addi16sp sp, 0 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496]