[mips][ias] Range check uimmz operands.
authorDaniel Sanders <daniel.sanders@imgtec.com>
Fri, 6 Nov 2015 12:11:03 +0000 (12:11 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Fri, 6 Nov 2015 12:11:03 +0000 (12:11 +0000)
Reviewers: vkalintiris

Subscribers: dsanders, atanasyan, llvm-commits

Differential Revision: http://reviews.llvm.org/D14013

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252294 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MipsInstrInfo.td
test/MC/Mips/msa/invalid-64.s [new file with mode: 0644]
test/MC/Mips/msa/invalid.s [new file with mode: 0644]

index 78c3e224a003b7dd594d4dbe3ebe0e198e57bc70..09ae6a5d43c72328d46b81fa6913ce044714359b 100644 (file)
@@ -383,7 +383,7 @@ class MipsAsmParser : public MCTargetAsmParser {
 
 public:
   enum MipsMatchResultTy {
-    Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
+    Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
 #define GET_OPERAND_DIAGNOSTIC_TYPES
 #include "MipsGenAsmMatcher.inc"
 #undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -894,6 +894,13 @@ public:
     Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
   }
 
+  template <unsigned Bits>
+  void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    uint64_t Imm = getConstantImm() & ((1 << Bits) - 1);
+    Inst.addOperand(MCOperand::createImm(Imm));
+  }
+
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     const MCExpr *Expr = getImm();
@@ -953,6 +960,9 @@ public:
   bool isConstantImm() const {
     return isImm() && dyn_cast<MCConstantExpr>(getImm());
   }
+  bool isConstantImmz() const {
+    return isConstantImm() && getConstantImm() == 0;
+  }
   template <unsigned Bits> bool isUImm() const {
     return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
   }
@@ -3234,6 +3244,17 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
   return Match_Success;
 }
 
+static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
+                            uint64_t ErrorInfo) {
+  if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
+    SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
+    if (ErrorLoc == SMLoc())
+      return Loc;
+    return ErrorLoc;
+  }
+  return Loc;
+}
+
 bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                             OperandVector &Operands,
                                             MCStreamer &Out,
@@ -3262,7 +3283,7 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
       if (ErrorInfo >= Operands.size())
         return Error(IDLoc, "too few operands for instruction");
 
-      ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
+      ErrorLoc = Operands[ErrorInfo]->getStartLoc();
       if (ErrorLoc == SMLoc())
         ErrorLoc = IDLoc;
     }
@@ -3273,6 +3294,8 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return Error(IDLoc, "invalid instruction");
   case Match_RequiresDifferentSrcAndDst:
     return Error(IDLoc, "source and destination must be different");
+  case Match_Immz:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
   }
 
   llvm_unreachable("Implement any new match types added!");
index 4305198e4021822de0d54b8ba477215f5e7c0fb0..0a32967b5152a11d5afa3fb9edc53360beffa54c 100644 (file)
@@ -381,6 +381,14 @@ include "MipsInstrFormats.td"
 // Mips Operand, Complex Patterns and Transformations Definitions.
 //===----------------------------------------------------------------------===//
 
+def ConstantImmzAsmOperandClass : AsmOperandClass {
+  let Name = "ConstantImmz";
+  let RenderMethod = "addConstantUImmOperands<1>";
+  let PredicateMethod = "isConstantImmz";
+  let SuperClasses = [];
+  let DiagnosticType = "Immz";
+}
+
 def MipsJumpTargetAsmOperand : AsmOperandClass {
   let Name = "JumpTarget";
   let ParserMethod = "parseJumpTarget";
@@ -450,6 +458,7 @@ def simm16_64   : Operand<i64> {
 // Zero
 def uimmz       : Operand<i32> {
   let PrintMethod = "printUnsignedImm";
+  let ParserMatchClass = ConstantImmzAsmOperandClass;
 }
 
 // Unsigned Operand
diff --git a/test/MC/Mips/msa/invalid-64.s b/test/MC/Mips/msa/invalid-64.s
new file mode 100644 (file)
index 0000000..cf1bff5
--- /dev/null
@@ -0,0 +1,11 @@
+# Instructions that are invalid
+#
+# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r2 -mattr=+msa \
+# RUN:     -show-encoding 2>%t1
+# RUN: FileCheck %s < %t1
+
+    .set noat
+    insve.b $w25[3], $w9[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.h $w24[2], $w2[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.w $w0[2], $w13[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.d $w3[0], $w18[1] # CHECK: :[[@LINE]]:26: error: expected '0'
diff --git a/test/MC/Mips/msa/invalid.s b/test/MC/Mips/msa/invalid.s
new file mode 100644 (file)
index 0000000..cf1bff5
--- /dev/null
@@ -0,0 +1,11 @@
+# Instructions that are invalid
+#
+# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r2 -mattr=+msa \
+# RUN:     -show-encoding 2>%t1
+# RUN: FileCheck %s < %t1
+
+    .set noat
+    insve.b $w25[3], $w9[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.h $w24[2], $w2[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.w $w0[2], $w13[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+    insve.d $w3[0], $w18[1] # CHECK: :[[@LINE]]:26: error: expected '0'