OSDN Git Service

[LLParser] Parse vector GEP constant expression correctly
authorMichael Kuperstein <mkuper@google.com>
Wed, 21 Dec 2016 18:29:47 +0000 (18:29 +0000)
committerMichael Kuperstein <mkuper@google.com>
Wed, 21 Dec 2016 18:29:47 +0000 (18:29 +0000)
The constantexpr parsing was too constrained and rejected legal vector GEPs.
This relaxes it to be similar to the ones for instruction parsing.

This fixes PR30816.

Differential Revision: https://reviews.llvm.org/D28013

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

lib/AsmParser/LLParser.cpp
test/Assembler/getelementptr_vec_ce.ll [new file with mode: 0644]
test/Assembler/getelementptr_vec_ce2.ll [new file with mode: 0644]

index 712a2c6..d1891b7 100644 (file)
@@ -3193,20 +3193,23 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
             ExplicitTypeLoc,
             "explicit pointee type doesn't match operand's pointee type");
 
+      unsigned GEPWidth =
+          BaseType->isVectorTy() ? BaseType->getVectorNumElements() : 0;
+
       ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
       for (Constant *Val : Indices) {
         Type *ValTy = Val->getType();
         if (!ValTy->getScalarType()->isIntegerTy())
           return Error(ID.Loc, "getelementptr index must be an integer");
-        if (ValTy->isVectorTy() != BaseType->isVectorTy())
-          return Error(ID.Loc, "getelementptr index type missmatch");
         if (ValTy->isVectorTy()) {
           unsigned ValNumEl = ValTy->getVectorNumElements();
-          unsigned PtrNumEl = BaseType->getVectorNumElements();
-          if (ValNumEl != PtrNumEl)
+          if (GEPWidth && (ValNumEl != GEPWidth))
             return Error(
                 ID.Loc,
                 "getelementptr vector index has a wrong number of elements");
+          // GEPWidth may have been unknown because the base is a scalar,
+          // but it is known now.
+          GEPWidth = ValNumEl;
         }
       }
 
diff --git a/test/Assembler/getelementptr_vec_ce.ll b/test/Assembler/getelementptr_vec_ce.ll
new file mode 100644 (file)
index 0000000..4cf2964
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+@G = global [4 x i32] zeroinitializer
+
+; CHECK-LABEL: @foo
+; CHECK: ret <4 x i32*> getelementptr ([4 x i32], [4 x i32]* @G, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>)
+define <4 x i32*> @foo() {
+  ret <4 x i32*> getelementptr ([4 x i32], [4 x i32]* @G, i32 0, <4 x i32> <i32 0, i32 1, i32 2, i32 3>)
+}
diff --git a/test/Assembler/getelementptr_vec_ce2.ll b/test/Assembler/getelementptr_vec_ce2.ll
new file mode 100644 (file)
index 0000000..06362c8
--- /dev/null
@@ -0,0 +1,8 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+
+@G = global [4 x [4 x i32]] zeroinitializer
+
+; CHECK: getelementptr vector index has a wrong number of elements
+define <4 x i32*> @foo() {
+  ret <4 x i32*> getelementptr ([4 x [4 x i32]], [4 x [4 x i32]]* @G, i32 0, <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <8 x i32> zeroinitializer)
+}