[ARM64] Correct more bounds checks/diagnostics for arithmetic shift operands
authorBradley Smith <bradley.smith@arm.com>
Mon, 12 May 2014 09:41:43 +0000 (09:41 +0000)
committerBradley Smith <bradley.smith@arm.com>
Mon, 12 May 2014 09:41:43 +0000 (09:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208528 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM64/ARM64InstrFormats.td
lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
test/MC/ARM64/arithmetic-encoding.s
test/MC/ARM64/diags.s

index f44f45ed3d9415d2efbf2041f50aa1b26934e6b9..4e97a99ef68aabf753d50edd34cab953bee14269 100644 (file)
@@ -100,7 +100,7 @@ def MovImm64ShifterOperand : AsmOperandClass {
 class ArithmeticShifterOperand<int width> : AsmOperandClass {
   let SuperClasses = [ShifterOperand];
   let Name = "ArithmeticShifter" # width;
-  let PredicateMethod = "isArithmeticShifter";
+  let PredicateMethod = "isArithmeticShifter<" # width # ">";
   let RenderMethod = "addArithmeticShifterOperands";
   let DiagnosticType = "AddSubRegShift" # width;
 }
index 8276b5fc83046c6de95ff36791c2525bc5f9745e..98e428069dcd9de665a91bdba6a4979ff4831699 100644 (file)
@@ -807,7 +807,8 @@ public:
     // lsl is an alias for UXTW but will be a parsed as a k_Shifter operand.
     if (isShifter()) {
       ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(Shifter.Val);
-      return ST == ARM64_AM::LSL;
+      return ST == ARM64_AM::LSL &&
+             ARM64_AM::getShiftValue(Shifter.Val) <= 4;
     }
     return Kind == k_Extend && ARM64_AM::getArithShiftValue(Shifter.Val) <= 4;
   }
@@ -823,7 +824,8 @@ public:
     // lsl is an alias for UXTX but will be a parsed as a k_Shifter operand.
     if (isShifter()) {
       ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(Shifter.Val);
-      return ST == ARM64_AM::LSL;
+      return ST == ARM64_AM::LSL &&
+             ARM64_AM::getShiftValue(Shifter.Val) <= 4;
     }
     if (Kind != k_Extend)
       return false;
@@ -832,13 +834,15 @@ public:
            ARM64_AM::getArithShiftValue(Shifter.Val) <= 4;
   }
 
+  template <unsigned width>
   bool isArithmeticShifter() const {
     if (!isShifter())
       return false;
 
     // An arithmetic shifter is LSL, LSR, or ASR.
     ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(Shifter.Val);
-    return ST == ARM64_AM::LSL || ST == ARM64_AM::LSR || ST == ARM64_AM::ASR;
+    return (ST == ARM64_AM::LSL || ST == ARM64_AM::LSR ||
+           ST == ARM64_AM::ASR) && ARM64_AM::getShiftValue(Shifter.Val) < width;
   }
 
   bool isMovImm32Shifter() const {
@@ -2454,7 +2458,6 @@ ARM64AsmParser::tryParseOptionalShift(OperandVector &Operands) {
     return MatchOperand_ParseFail;
   }
 
-  SMLoc ExprLoc = getLoc();
   const MCExpr *ImmVal;
   if (getParser().parseExpression(ImmVal))
     return MatchOperand_ParseFail;
@@ -2465,14 +2468,19 @@ ARM64AsmParser::tryParseOptionalShift(OperandVector &Operands) {
     return MatchOperand_ParseFail;
   }
 
+  SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
+
+  // If we have an shift that is too large to encode then crudely pass it
+  // through as an invalid shift that is encodable so that we get consistant
+  // diagnostics rather than ones different from out of range 32-bit shifts.
   if ((MCE->getValue() & 0x3f) != MCE->getValue()) {
-    Error(ExprLoc, "immediate value too large for shifter operand");
-    return MatchOperand_ParseFail;
+    Operands.push_back(ARM64Operand::CreateShifter(ARM64_AM::InvalidShift, 0, S,
+                                                   E, getContext()));
+  } else {
+    Operands.push_back(ARM64Operand::CreateShifter(ShOp, MCE->getValue(), S,
+                                                   E, getContext()));
   }
 
-  SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
-  Operands.push_back(
-      ARM64Operand::CreateShifter(ShOp, MCE->getValue(), S, E, getContext()));
   return MatchOperand_Success;
 }
 
index 7a30e998cb0fecceb7449106f44e0678632de005..05b874cda593f8b2c301a33b5b2bbcb958ca3221 100644 (file)
@@ -107,72 +107,56 @@ foo:
   add x12, x13, x14
   add w12, w13, w14, lsl #12
   add x12, x13, x14, lsl #12
-  add w12, w13, w14, lsr #42
   add x12, x13, x14, lsr #42
-  add w12, w13, w14, asr #39
   add x12, x13, x14, asr #39
 
 ; CHECK: add w12, w13, w14           ; encoding: [0xac,0x01,0x0e,0x0b]
 ; CHECK: add x12, x13, x14           ; encoding: [0xac,0x01,0x0e,0x8b]
 ; CHECK: add w12, w13, w14, lsl #12  ; encoding: [0xac,0x31,0x0e,0x0b]
 ; CHECK: add x12, x13, x14, lsl #12  ; encoding: [0xac,0x31,0x0e,0x8b]
-; CHECK: add w12, w13, w14, lsr #42  ; encoding: [0xac,0xa9,0x4e,0x0b]
 ; CHECK: add x12, x13, x14, lsr #42  ; encoding: [0xac,0xa9,0x4e,0x8b]
-; CHECK: add w12, w13, w14, asr #39  ; encoding: [0xac,0x9d,0x8e,0x0b]
 ; CHECK: add x12, x13, x14, asr #39  ; encoding: [0xac,0x9d,0x8e,0x8b]
 
   sub w12, w13, w14
   sub x12, x13, x14
   sub w12, w13, w14, lsl #12
   sub x12, x13, x14, lsl #12
-  sub w12, w13, w14, lsr #42
   sub x12, x13, x14, lsr #42
-  sub w12, w13, w14, asr #39
   sub x12, x13, x14, asr #39
 
 ; CHECK: sub w12, w13, w14           ; encoding: [0xac,0x01,0x0e,0x4b]
 ; CHECK: sub x12, x13, x14           ; encoding: [0xac,0x01,0x0e,0xcb]
 ; CHECK: sub w12, w13, w14, lsl #12  ; encoding: [0xac,0x31,0x0e,0x4b]
 ; CHECK: sub x12, x13, x14, lsl #12  ; encoding: [0xac,0x31,0x0e,0xcb]
-; CHECK: sub w12, w13, w14, lsr #42  ; encoding: [0xac,0xa9,0x4e,0x4b]
 ; CHECK: sub x12, x13, x14, lsr #42  ; encoding: [0xac,0xa9,0x4e,0xcb]
-; CHECK: sub w12, w13, w14, asr #39  ; encoding: [0xac,0x9d,0x8e,0x4b]
 ; CHECK: sub x12, x13, x14, asr #39  ; encoding: [0xac,0x9d,0x8e,0xcb]
 
   adds w12, w13, w14
   adds x12, x13, x14
   adds w12, w13, w14, lsl #12
   adds x12, x13, x14, lsl #12
-  adds w12, w13, w14, lsr #42
   adds x12, x13, x14, lsr #42
-  adds w12, w13, w14, asr #39
   adds x12, x13, x14, asr #39
 
 ; CHECK: adds w12, w13, w14          ; encoding: [0xac,0x01,0x0e,0x2b]
 ; CHECK: adds x12, x13, x14          ; encoding: [0xac,0x01,0x0e,0xab]
 ; CHECK: adds w12, w13, w14, lsl #12 ; encoding: [0xac,0x31,0x0e,0x2b]
 ; CHECK: adds x12, x13, x14, lsl #12 ; encoding: [0xac,0x31,0x0e,0xab]
-; CHECK: adds w12, w13, w14, lsr #42 ; encoding: [0xac,0xa9,0x4e,0x2b]
 ; CHECK: adds x12, x13, x14, lsr #42 ; encoding: [0xac,0xa9,0x4e,0xab]
-; CHECK: adds w12, w13, w14, asr #39 ; encoding: [0xac,0x9d,0x8e,0x2b]
 ; CHECK: adds x12, x13, x14, asr #39 ; encoding: [0xac,0x9d,0x8e,0xab]
 
   subs w12, w13, w14
   subs x12, x13, x14
   subs w12, w13, w14, lsl #12
   subs x12, x13, x14, lsl #12
-  subs w12, w13, w14, lsr #42
   subs x12, x13, x14, lsr #42
-  subs w12, w13, w14, asr #39
   subs x12, x13, x14, asr #39
 
 ; CHECK: subs w12, w13, w14          ; encoding: [0xac,0x01,0x0e,0x6b]
 ; CHECK: subs x12, x13, x14          ; encoding: [0xac,0x01,0x0e,0xeb]
 ; CHECK: subs w12, w13, w14, lsl #12 ; encoding: [0xac,0x31,0x0e,0x6b]
 ; CHECK: subs x12, x13, x14, lsl #12 ; encoding: [0xac,0x31,0x0e,0xeb]
-; CHECK: subs w12, w13, w14, lsr #42 ; encoding: [0xac,0xa9,0x4e,0x6b]
 ; CHECK: subs x12, x13, x14, lsr #42 ; encoding: [0xac,0xa9,0x4e,0xeb]
-; CHECK: subs w12, w13, w14, asr #39 ; encoding: [0xac,0x9d,0x8e,0x6b]
 ; CHECK: subs x12, x13, x14, asr #39 ; encoding: [0xac,0x9d,0x8e,0xeb]
 
 ; Check use of upper case register names rdar://14354073
index 7d9ed5f2043109b6ec773824c11751b92758e60d..9846450b20835fbd2dbe4f18bc94fa751197706c 100644 (file)
@@ -176,7 +176,7 @@ foo:
 ; Where the immediate is out of range.
   add w1, w2, w3, lsr #75
 
-; CHECK-ERRORS: error: immediate value too large for shifter operand
+; CHECK-ERRORS: error: expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]
 ; CHECK-ERRORS: add w1, w2, w3, lsr #75
 ; CHECK-ERRORS:                      ^