From: Chris Lattner Date: Wed, 23 Dec 2009 21:31:11 +0000 (+0000) Subject: fix opencl extvector element extraction on rvalues. We previously X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=998eab186790b7246a572a9950174f7f36442c06;p=clang 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 64fbfbcb56..6b54d969f8 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1179,7 +1179,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { static llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext, llvm::SmallVector &Elts) { - llvm::SmallVector CElts; + llvm::SmallVector CElts; for (unsigned i = 0, e = Elts.size(); i != e; ++i) CElts.push_back(llvm::ConstantInt::get( @@ -1190,21 +1190,44 @@ llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext, 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(); + 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(); 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(); + 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 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 Indices; E->getEncodedElementAccess(Indices); @@ -1219,7 +1242,6 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { llvm::Constant *BaseElts = Base.getExtVectorElts(); llvm::SmallVector CElts; - const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext); for (unsigned i = 0, e = Indices.size(); i != e; ++i) { if (isa(BaseElts)) CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0)); diff --git a/test/CodeGen/ext-vector.c b/test/CodeGen/ext-vector.c index e322f77bde..d09599dfb6 100644 --- a/test/CodeGen/ext-vector.c +++ b/test/CodeGen/ext-vector.c @@ -138,3 +138,16 @@ void test8(float4 *ap, float4 *bp, int c) { cmp = a == b; cmp = a != b; } + +int test9(int4 V) { + return V.xy.x; +} + +int test10(foo_t V) { + return (V+V).x; +} + +int4 test11a(); +int test11() { + return test11a().x; +}