[x86] Add assembly parser bounds checking to the immediate value for cmpss/cmpsd...
authorCraig Topper <craig.topper@gmail.com>
Wed, 21 Jan 2015 06:07:53 +0000 (06:07 +0000)
committerCraig Topper <craig.topper@gmail.com>
Wed, 21 Jan 2015 06:07:53 +0000 (06:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226642 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/AsmParser/X86AsmParserCommon.h
lib/Target/X86/AsmParser/X86Operand.h
lib/Target/X86/X86InstrAVX512.td
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86InstrSSE.td
test/MC/X86/x86-32-avx.s
test/MC/X86/x86_errors.s

index 72aeeaac1639e65ca9d4363d7fc4effdf0ad2f3d..7610806c4578afcb112876da91a38010a1eaf38a 100644 (file)
@@ -34,6 +34,11 @@ inline bool isImmSExti64i32Value(uint64_t Value) {
           (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
 }
 
+inline bool isImmUnsignedi8Value(uint64_t Value) {
+  return ((                                  Value <= 0x00000000000000FFULL)||
+          (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
+}
+
 } // End of namespace llvm
 
 #endif
index 6675d4dc045ce0cfff1c58a9edba44051b2c4ed8..ac4c0435720c53ab400e3601a0095a644a53435d 100644 (file)
@@ -187,6 +187,13 @@ struct X86Operand : public MCParsedAsmOperand {
     return isImmSExti64i32Value(CE->getValue());
   }
 
+  bool isImmUnsignedi8() const {
+    if (!isImm()) return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    return isImmUnsignedi8Value(CE->getValue());
+  }
+
   bool isOffsetOf() const override {
     return OffsetOfLoc.getPointer();
   }
index 4809d7c650a08d86b2316d2111864fd2f794911d..4dd91f464c5c152a1c33cb0dd58fd7145bdeab0b 100644 (file)
@@ -1210,11 +1210,11 @@ multiclass avx512_cmp_scalar<RegisterClass RC, X86MemOperand x86memop,
                 (ld_frag addr:$src2), imm:$cc))], IIC_SSE_ALU_F32P_RM>, EVEX_4V;
   let isAsmParserOnly = 1, hasSideEffects = 0 in {
     def rri_alt : AVX512Ii8<0xC2, MRMSrcReg,
-               (outs VK1:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
+               (outs VK1:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
                asm_alt, [], IIC_SSE_ALU_F32S_RR>, EVEX_4V;
     let mayLoad = 1 in
     def rmi_alt : AVX512Ii8<0xC2, MRMSrcMem,
-               (outs VK1:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
+               (outs VK1:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
                asm_alt, [], IIC_SSE_ALU_F32P_RM>, EVEX_4V;
   }
 }
@@ -1545,12 +1545,12 @@ multiclass avx512_cmp_packed<RegisterClass KRC, RegisterClass RC,
   // Accept explicit immediate argument form instead of comparison code.
   let isAsmParserOnly = 1, hasSideEffects = 0 in {
     def rri_alt : AVX512PIi8<0xC2, MRMSrcReg,
-               (outs KRC:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
+               (outs KRC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
               !strconcat("vcmp", suffix,
                         "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), [], d>;
     let mayLoad = 1 in
     def rmi_alt : AVX512PIi8<0xC2, MRMSrcMem,
-               (outs KRC:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
+               (outs KRC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
               !strconcat("vcmp", suffix,
                         "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), [], d>;
   }
index 64e4636b1ac374f7cad14f73d550cb8a237cc62d..079b233bb64bb9143eeb2fd8f51fe83dd20ed280 100644 (file)
@@ -609,6 +609,14 @@ def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass {
                       ImmSExti64i32AsmOperand];
 }
 
+// Unsigned immediate used by SSE/AVX instructions
+// [0, 0xFF]
+//   [0xFFFFFFFFFFFFFF80, 0xFFFFFFFFFFFFFFFF]
+def ImmUnsignedi8AsmOperand : AsmOperandClass {
+  let Name = "ImmUnsignedi8";
+  let RenderMethod = "addImmOperands";
+}
+
 // A couple of more descriptive operand definitions.
 // 16-bits but only 8 bits are significant.
 def i16i8imm  : Operand<i16> {
@@ -627,6 +635,18 @@ def i64i32imm  : Operand<i64> {
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
+// 64-bits but only 8 bits are significant.
+def i64i8imm   : Operand<i64> {
+  let ParserMatchClass = ImmSExti64i8AsmOperand;
+  let OperandType = "OPERAND_IMMEDIATE";
+}
+
+// Unsigned 8-bit immediate used by SSE/AVX instructions.
+def u8imm : Operand<i8> {
+  let ParserMatchClass = ImmUnsignedi8AsmOperand;
+  let OperandType = "OPERAND_IMMEDIATE";
+}
+
 // 64-bits but only 32 bits are significant, and those bits are treated as being
 // pc relative.
 def i64i32imm_pcrel : Operand<i64> {
@@ -635,12 +655,6 @@ def i64i32imm_pcrel : Operand<i64> {
   let OperandType = "OPERAND_PCREL";
 }
 
-// 64-bits but only 8 bits are significant.
-def i64i8imm   : Operand<i64> {
-  let ParserMatchClass = ImmSExti64i8AsmOperand;
-  let OperandType = "OPERAND_IMMEDIATE";
-}
-
 def lea64_32mem : Operand<i32> {
   let PrintMethod = "printanymem";
   let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, i8imm);
index 56d76839e159f3d366a26014e36b96322223d0bf..b4bcd7756b5fc5b69f343becd8dd399fe6128d08 100644 (file)
@@ -2348,11 +2348,11 @@ multiclass sse12_cmp_scalar<RegisterClass RC, X86MemOperand x86memop,
   // Accept explicit immediate argument form instead of comparison code.
   let isAsmParserOnly = 1, hasSideEffects = 0 in {
     def rr_alt : SIi8<0xC2, MRMSrcReg, (outs RC:$dst),
-                      (ins RC:$src1, RC:$src2, i8imm:$cc), asm_alt, [],
+                      (ins RC:$src1, RC:$src2, u8imm:$cc), asm_alt, [],
                       IIC_SSE_ALU_F32S_RR>, Sched<[itins.Sched]>;
     let mayLoad = 1 in
     def rm_alt : SIi8<0xC2, MRMSrcMem, (outs RC:$dst),
-                      (ins RC:$src1, x86memop:$src2, i8imm:$cc), asm_alt, [],
+                      (ins RC:$src1, x86memop:$src2, u8imm:$cc), asm_alt, [],
                       IIC_SSE_ALU_F32S_RM>,
                       Sched<[itins.Sched.Folded, ReadAfterLd]>;
   }
@@ -2502,11 +2502,11 @@ multiclass sse12_cmp_packed<RegisterClass RC, X86MemOperand x86memop,
   // Accept explicit immediate argument form instead of comparison code.
   let isAsmParserOnly = 1, hasSideEffects = 0 in {
     def rri_alt : PIi8<0xC2, MRMSrcReg,
-               (outs RC:$dst), (ins RC:$src1, RC:$src2, i8imm:$cc),
+               (outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc),
                asm_alt, [], itins.rr, d>, Sched<[WriteFAdd]>;
     let mayLoad = 1 in
     def rmi_alt : PIi8<0xC2, MRMSrcMem,
-               (outs RC:$dst), (ins RC:$src1, x86memop:$src2, i8imm:$cc),
+               (outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc),
                asm_alt, [], itins.rm, d>,
                Sched<[WriteFAddLd, ReadAfterLd]>;
   }
index ec4abdbb2a8bf027b2366ba300fe56ef9293e881..5c702392a909287f406ceebd86bc1d68f8c99abe 100644 (file)
           vdppd $0x81, %xmm2, %xmm5, %xmm1
 // CHECK: vinsertps $129, %xmm3, %xmm2, %xmm1
           vinsertps $0x81, %xmm3, %xmm2, %xmm1
+
+// CHECK: vcmpps $-128, %xmm2, %xmm1, %xmm0
+// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0x80]
+vcmpps $-128, %xmm2, %xmm1, %xmm0
+
+// CHECK: vcmpps $128, %xmm2, %xmm1, %xmm0
+// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0x80]
+vcmpps $128, %xmm2, %xmm1, %xmm0
+
+// CHECK: vcmpps $255, %xmm2, %xmm1, %xmm0
+// CHECK: encoding: [0xc5,0xf0,0xc2,0xc2,0xff]
+vcmpps $255, %xmm2, %xmm1, %xmm0
index 0b3bc7f43502bfb77867353deb3929e8d584098b..fa87ef676f3e54091dcd1fbac789c4c9d7812298 100644 (file)
@@ -50,3 +50,11 @@ outb al, 4
 // 32: error: invalid segment register
 // 64: error: invalid segment register
 movl %eax:0x00, %ebx
+
+// 32: error: invalid operand for instruction
+// 64: error: invalid operand for instruction
+cmpps $-129, %xmm0, %xmm0
+
+// 32: error: invalid operand for instruction
+// 64: error: invalid operand for instruction
+cmppd $256, %xmm0, %xmm0