fix opencl extvector element extraction on rvalues.  We previously
error_unsupported on test10 and crashed on test11.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92056 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 64fbfbc..6b54d96 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1179,7 +1179,7 @@
 static
 llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext,
                                        llvm::SmallVector<unsigned, 4> &Elts) {
-  llvm::SmallVector<llvm::Constant *, 4> CElts;
+  llvm::SmallVector<llvm::Constant*, 4> CElts;
 
   for (unsigned i = 0, e = Elts.size(); i != e; ++i)
     CElts.push_back(llvm::ConstantInt::get(
@@ -1190,21 +1190,44 @@
 
 LValue CodeGenFunction::
 EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
+  const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+
   // Emit the base vector as an l-value.
   LValue Base;
 
   // ExtVectorElementExpr's base can either be a vector or pointer to vector.
-  if (!E->isArrow()) {
-    assert(E->getBase()->getType()->isVectorType());
-    Base = EmitLValue(E->getBase());
-  } else {
-    const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
+  if (E->isArrow()) {
+    // If it is a pointer to a vector, emit the address and form an lvalue with
+    // it.
     llvm::Value *Ptr = EmitScalarExpr(E->getBase());
+    const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
     Qualifiers Quals = MakeQualifiers(PT->getPointeeType());
     Quals.removeObjCGCAttr();
     Base = LValue::MakeAddr(Ptr, Quals);
-  }
+  } else if (E->getBase()->isLvalue(getContext()) == Expr::LV_Valid) {
+    // Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
+    // emit the base as an lvalue.
+    assert(E->getBase()->getType()->isVectorType());
+    Base = EmitLValue(E->getBase());
+  } else {
+    // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such.
+    const VectorType *VT = E->getBase()->getType()->getAs<VectorType>();
+    assert(VT && "Result must be a vector");
+    llvm::Value *Vec = EmitScalarExpr(E->getBase());
+    
+    // Store the vector to memory (because LValue wants an address) and use an
+    // index list of 0,1,2,3 which is the full vector.
+    llvm::Value *VecMem =CreateTempAlloca(ConvertType(E->getBase()->getType()));
+    Builder.CreateStore(Vec, VecMem);
 
+    llvm::SmallVector<llvm::Constant *, 4> CElts;
+    for (unsigned i = 0, e = VT->getNumElements(); i != e; ++i)
+      CElts.push_back(llvm::ConstantInt::get(Int32Ty, i));
+                      
+    llvm::Constant *Elts = llvm::ConstantVector::get(&CElts[0], CElts.size());
+    Base = LValue::MakeExtVectorElt(VecMem, Elts, 0);
+  }
+  
   // Encode the element access list into a vector of unsigned indices.
   llvm::SmallVector<unsigned, 4> Indices;
   E->getEncodedElementAccess(Indices);
@@ -1219,7 +1242,6 @@
   llvm::Constant *BaseElts = Base.getExtVectorElts();
   llvm::SmallVector<llvm::Constant *, 4> CElts;
 
-  const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
   for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
     if (isa<llvm::ConstantAggregateZero>(BaseElts))
       CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0));