[ARM64] Add parsing for vector lists such as {v0.8b-v3.8b}
authorBradley Smith <bradley.smith@arm.com>
Wed, 9 Apr 2014 14:41:58 +0000 (14:41 +0000)
committerBradley Smith <bradley.smith@arm.com>
Wed, 9 Apr 2014 14:41:58 +0000 (14:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205862 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
test/MC/ARM64/vector-lists.s [new file with mode: 0644]

index b406617de802ab8483edfbd7fb3603eed7ec46d1..46440a9bee8583f9203cce6f4bd72e426819b64f 100644 (file)
@@ -55,7 +55,7 @@ private:
   unsigned parseCondCodeString(StringRef Cond);
   bool parseCondCode(OperandVector &Operands, bool invertCondCode);
   int tryParseRegister();
-  int tryMatchVectorRegister(StringRef &Kind);
+  int tryMatchVectorRegister(StringRef &Kind, bool expected);
   bool parseOptionalShift(OperandVector &Operands);
   bool parseOptionalExtend(OperandVector &Operands);
   bool parseRegister(OperandVector &Operands);
@@ -1895,7 +1895,7 @@ int ARM64AsmParser::tryParseRegister() {
 
 /// tryMatchVectorRegister - Try to parse a vector register name with optional
 /// kind specifier. If it is a register specifier, eat the token and return it.
-int ARM64AsmParser::tryMatchVectorRegister(StringRef &Kind) {
+int ARM64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
   if (Parser.getTok().isNot(AsmToken::Identifier)) {
     TokError("vector register expected");
     return -1;
@@ -1918,6 +1918,9 @@ int ARM64AsmParser::tryMatchVectorRegister(StringRef &Kind) {
     Parser.Lex(); // Eat the register token.
     return RegNum;
   }
+
+  if (expected)
+    TokError("vector register expected");
   return -1;
 }
 
@@ -3004,7 +3007,7 @@ bool ARM64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
   SMLoc S = getLoc();
   // Check for a vector register specifier first.
   StringRef Kind;
-  int64_t Reg = tryMatchVectorRegister(Kind);
+  int64_t Reg = tryMatchVectorRegister(Kind, false);
   if (Reg == -1)
     return true;
   Operands.push_back(
@@ -3354,36 +3357,57 @@ bool ARM64AsmParser::parseVectorList(OperandVector &Operands) {
   SMLoc S = getLoc();
   Parser.Lex(); // Eat left bracket token.
   StringRef Kind;
-  int64_t FirstReg = tryMatchVectorRegister(Kind);
+  int64_t FirstReg = tryMatchVectorRegister(Kind, true);
   if (FirstReg == -1)
-    return Error(getLoc(), "vector register expected");
+    return true;
   int64_t PrevReg = FirstReg;
   unsigned Count = 1;
-  while (Parser.getTok().isNot(AsmToken::RCurly)) {
-    if (Parser.getTok().is(AsmToken::EndOfStatement))
-      Error(getLoc(), "'}' expected");
 
-    if (Parser.getTok().isNot(AsmToken::Comma))
-      return Error(getLoc(), "',' expected");
-    Parser.Lex(); // Eat the comma token.
+  if (Parser.getTok().is(AsmToken::Minus)) {
+    Parser.Lex(); // Eat the minus.
 
     SMLoc Loc = getLoc();
     StringRef NextKind;
-    int64_t Reg = tryMatchVectorRegister(NextKind);
+    int64_t Reg = tryMatchVectorRegister(NextKind, true);
     if (Reg == -1)
-      return Error(Loc, "vector register expected");
+      return true;
     // Any Kind suffices must match on all regs in the list.
     if (Kind != NextKind)
       return Error(Loc, "mismatched register size suffix");
 
-    // Registers must be incremental (with wraparound at 31)
-    if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
-        (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
-      return Error(Loc, "registers must be sequential");
+    unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
+
+    if (Space == 0 || Space > 3) {
+      return Error(Loc, "invalid number of vectors");
+    }
+
+    Count += Space;
+  }
+  else {
+    while (Parser.getTok().is(AsmToken::Comma)) {
+      Parser.Lex(); // Eat the comma token.
+
+      SMLoc Loc = getLoc();
+      StringRef NextKind;
+      int64_t Reg = tryMatchVectorRegister(NextKind, true);
+      if (Reg == -1)
+        return true;
+      // Any Kind suffices must match on all regs in the list.
+      if (Kind != NextKind)
+        return Error(Loc, "mismatched register size suffix");
 
-    PrevReg = Reg;
-    ++Count;
+      // Registers must be incremental (with wraparound at 31)
+      if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
+          (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
+       return Error(Loc, "registers must be sequential");
+
+      PrevReg = Reg;
+      ++Count;
+    }
   }
+
+  if (Parser.getTok().is(AsmToken::EndOfStatement))
+    Error(getLoc(), "'}' expected");
   Parser.Lex(); // Eat the '}' token.
 
   unsigned NumElements = 0;
diff --git a/test/MC/ARM64/vector-lists.s b/test/MC/ARM64/vector-lists.s
new file mode 100644 (file)
index 0000000..e4cef61
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: not llvm-mc -triple arm64 -show-encoding < %s 2>%t | FileCheck %s
+// RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
+
+    ST4     {v0.8B-v3.8B}, [x0]
+    ST4     {v0.4H-v3.4H}, [x0]
+
+// CHECK: st4  { v0.8b, v1.8b, v2.8b, v3.8b }, [x0] // encoding: [0x00,0x00,0x00,0x0c]
+// CHECK: st4  { v0.4h, v1.4h, v2.4h, v3.4h }, [x0] // encoding: [0x00,0x04,0x00,0x0c]
+
+    ST4     {v0.8B-v4.8B}, [x0]
+    ST4     {v0.8B-v3.8B,v4.8B}, [x0]
+    ST4     {v0.8B-v3.8H}, [x0]
+    ST4     {v0.8B-v3.16B}, [x0]
+    ST4     {v0.8B-},[x0]
+
+// CHECK-ERRORS: error: invalid number of vectors
+// CHECK-ERRORS: error: unexpected token in argument list
+// CHECK-ERRORS: error: mismatched register size suffix
+// CHECK-ERRORS: error: mismatched register size suffix
+// CHECK-ERRORS: error: vector register expected