diff options
Diffstat (limited to 'clang/lib/CodeGen')
| -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) { |

