diff options
| author | Yaxun Liu <Yaxun.Liu@amd.com> | 2016-10-03 14:41:50 +0000 |
|---|---|---|
| committer | Yaxun Liu <Yaxun.Liu@amd.com> | 2016-10-03 14:41:50 +0000 |
| commit | ea6b796e0e8a88af9899b1940b45a2e2b7589523 (patch) | |
| tree | d4b40d92078c638c96d31880f6a7eea91df8063b /clang/lib | |
| parent | bfdc37421244953af3db189c809fa02bab198b1d (diff) | |
| download | bcm5719-llvm-ea6b796e0e8a88af9899b1940b45a2e2b7589523.tar.gz bcm5719-llvm-ea6b796e0e8a88af9899b1940b45a2e2b7589523.zip | |
[OpenCL] Fix bug in __builtin_astype causing invalid LLVM cast instructions
__builtin_astype is used to cast OpenCL opaque types to other types, as such, it needs to be able to handle casting from and to pointer types correctly.
Current it cannot handle 1) casting between pointers of different addr spaces 2) casting between pointer type and non-pointer types.
This patch fixes that.
Differential Revision: https://reviews.llvm.org/D25123
llvm-svn: 283114
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index e70c31ad63a..dc8186563ce 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3407,6 +3407,52 @@ static Value *ConvertVec3AndVec4(CGBuilderTy &Builder, CodeGenFunction &CGF, return Builder.CreateShuffleVector(Src, UnV, Mask); } +// Create cast instructions for converting LLVM value \p Src to LLVM type \p +// DstTy. \p Src has the same size as \p DstTy. Both are single value types +// but could be scalar or vectors of different lengths, and either can be +// pointer. +// There are 4 cases: +// 1. non-pointer -> non-pointer : needs 1 bitcast +// 2. pointer -> pointer : needs 1 bitcast or addrspacecast +// 3. pointer -> non-pointer +// a) pointer -> intptr_t : needs 1 ptrtoint +// b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast +// 4. non-pointer -> pointer +// a) intptr_t -> pointer : needs 1 inttoptr +// b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr +// Note: for cases 3b and 4b two casts are required since LLVM casts do not +// allow casting directly between pointer types and non-integer non-pointer +// types. +static Value *createCastsForTypeOfSameSize(CGBuilderTy &Builder, + const llvm::DataLayout &DL, + Value *Src, llvm::Type *DstTy, + StringRef Name = "") { + auto SrcTy = Src->getType(); + + // Case 1. + if (!SrcTy->isPointerTy() && !DstTy->isPointerTy()) + return Builder.CreateBitCast(Src, DstTy, Name); + + // Case 2. + if (SrcTy->isPointerTy() && DstTy->isPointerTy()) + return Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DstTy, Name); + + // Case 3. + if (SrcTy->isPointerTy() && !DstTy->isPointerTy()) { + // Case 3b. + if (!DstTy->isIntegerTy()) + Src = Builder.CreatePtrToInt(Src, DL.getIntPtrType(SrcTy)); + // Cases 3a and 3b. + return Builder.CreateBitOrPointerCast(Src, DstTy, Name); + } + + // Case 4b. + if (!SrcTy->isIntegerTy()) + Src = Builder.CreateBitCast(Src, DL.getIntPtrType(DstTy)); + // Cases 4a and 4b. + return Builder.CreateIntToPtr(Src, DstTy, Name); +} + Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) { Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); llvm::Type *DstTy = ConvertType(E->getType()); @@ -3421,7 +3467,8 @@ Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) { // vector to get a vec4, then a bitcast if the target type is different. if (NumElementsSrc == 3 && NumElementsDst != 3) { Src = ConvertVec3AndVec4(Builder, CGF, Src, 4); - Src = Builder.CreateBitCast(Src, DstTy); + Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src, + DstTy); Src->setName("astype"); return Src; } @@ -3431,13 +3478,15 @@ Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) { // get a vec3. if (NumElementsSrc != 3 && NumElementsDst == 3) { auto Vec4Ty = llvm::VectorType::get(DstTy->getVectorElementType(), 4); - Src = Builder.CreateBitCast(Src, Vec4Ty); + Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src, + Vec4Ty); Src = ConvertVec3AndVec4(Builder, CGF, Src, 3); Src->setName("astype"); return Src; } - return Builder.CreateBitCast(Src, DstTy, "astype"); + return Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), + Src, DstTy, "astype"); } Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) { |

