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());
// 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;
}
// 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) {
int3 f8(char16 x) {
return __builtin_astype(x, int3);
}
+
+//CHECK: define spir_func i32 addrspace(1)* @addr_cast(i32* readnone %[[x:.*]])
+//CHECK: %[[cast:.*]] = addrspacecast i32* %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* addr_cast(int *x) {
+ return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 addrspace(1)* @int_to_ptr(i32 %[[x:.*]])
+//CHECK: %[[cast:.*]] = inttoptr i32 %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* int_to_ptr(int x) {
+ return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 @ptr_to_int(i32* %[[x:.*]])
+//CHECK: %[[cast:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: ret i32 %[[cast]]
+int ptr_to_int(int *x) {
+ return __builtin_astype(x, int);
+}
+
+//CHECK: define spir_func <3 x i8> @ptr_to_char3(i32* %[[x:.*]])
+//CHECK: %[[cast1:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: %[[cast2:.*]] = bitcast i32 %[[cast1]] to <4 x i8>
+//CHECK: %[[astype:.*]] = shufflevector <4 x i8> %[[cast2]], <4 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+//CHECK: ret <3 x i8> %[[astype]]
+char3 ptr_to_char3(int *x) {
+ return __builtin_astype(x, char3);
+}
+
+//CHECK: define spir_func i32* @char3_to_ptr(<3 x i8> %[[x:.*]])
+//CHECK: %[[astype:.*]] = shufflevector <3 x i8> %[[x]], <3 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+//CHECK: %[[cast1:.*]] = bitcast <4 x i8> %[[astype]] to i32
+//CHECK: %[[cast2:.*]] = inttoptr i32 %[[cast1]] to i32*
+//CHECK: ret i32* %[[cast2]]
+int* char3_to_ptr(char3 x) {
+ return __builtin_astype(x, int*);
+}