Index: cfe/trunk/include/clang/Basic/TargetInfo.h =================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h +++ cfe/trunk/include/clang/Basic/TargetInfo.h @@ -294,6 +294,11 @@ return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace); } + /// \brief Return the maximum width of pointers on this target. + virtual uint64_t getMaxPointerWidth() const { + return PointerWidth; + } + /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } Index: cfe/trunk/lib/Basic/TargetInfo.cpp =================================================================== --- cfe/trunk/lib/Basic/TargetInfo.cpp +++ cfe/trunk/lib/Basic/TargetInfo.cpp @@ -306,8 +306,9 @@ } LongDoubleWidth = LongDoubleAlign = 128; - assert(PointerWidth == 32 || PointerWidth == 64); - bool Is32BitArch = PointerWidth == 32; + unsigned MaxPointerWidth = getMaxPointerWidth(); + assert(MaxPointerWidth == 32 || MaxPointerWidth == 64); + bool Is32BitArch = MaxPointerWidth == 32; SizeType = Is32BitArch ? UnsignedInt : UnsignedLong; PtrDiffType = Is32BitArch ? SignedInt : SignedLong; IntPtrType = Is32BitArch ? SignedInt : SignedLong; Index: cfe/trunk/lib/Basic/Targets.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets.cpp +++ cfe/trunk/lib/Basic/Targets.cpp @@ -2004,6 +2004,10 @@ } } + uint64_t getMaxPointerWidth() const override { + return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; + } + const char * getClobbers() const override { return ""; } Index: cfe/trunk/lib/CodeGen/CGExprScalar.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp @@ -787,7 +787,7 @@ // Handle pointer conversions next: pointers can only be converted to/from // other pointers and integers. Check for pointer types in terms of LLVM, as // some native types (like Obj-C id) may map to a pointer type. - if (isa(DstTy)) { + if (auto DstPT = dyn_cast(DstTy)) { // The source value may be an integer, or a pointer. if (isa(SrcTy)) return Builder.CreateBitCast(Src, DstTy, "conv"); @@ -795,7 +795,7 @@ assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); // First, convert to the correct width so that we control the kind of // extension. - llvm::Type *MiddleTy = CGF.IntPtrTy; + llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DstPT); bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); llvm::Value* IntResult = Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); @@ -1510,12 +1510,13 @@ // First, convert to the correct width so that we control the kind of // extension. - llvm::Type *MiddleTy = CGF.IntPtrTy; + auto DestLLVMTy = ConvertType(DestTy); + llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestLLVMTy); bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType(); llvm::Value* IntResult = Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); - return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy)); + return Builder.CreateIntToPtr(IntResult, DestLLVMTy); } case CK_PointerToIntegral: assert(!DestTy->isBooleanType() && "bool should use PointerToBool"); @@ -2426,6 +2427,7 @@ Value *pointer = op.LHS; Expr *pointerOperand = expr->getLHS(); + auto PtrTy = cast(pointer->getType()); Value *index = op.RHS; Expr *indexOperand = expr->getRHS(); @@ -2436,11 +2438,12 @@ } unsigned width = cast(index->getType())->getBitWidth(); - if (width != CGF.PointerWidthInBits) { + auto &DL = CGF.CGM.getDataLayout(); + if (width != DL.getTypeSizeInBits(PtrTy)) { // Zero-extend or sign-extend the pointer value according to // whether the index is signed or not. bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType(); - index = CGF.Builder.CreateIntCast(index, CGF.PtrDiffTy, isSigned, + index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned, "idx.ext"); } Index: cfe/trunk/lib/CodeGen/CodeGenModule.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp @@ -101,10 +101,13 @@ PointerWidthInBits = C.getTargetInfo().getPointerWidth(0); PointerAlignInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity(); + SizeSizeInBytes = + C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); IntAlignInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity(); IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); - IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits); + IntPtrTy = llvm::IntegerType::get(LLVMContext, + C.getTargetInfo().getMaxPointerWidth()); Int8PtrTy = Int8Ty->getPointerTo(0); Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); Index: cfe/trunk/lib/CodeGen/CodeGenTypeCache.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenTypeCache.h +++ cfe/trunk/lib/CodeGen/CodeGenTypeCache.h @@ -80,9 +80,14 @@ union { unsigned char PointerAlignInBytes; unsigned char PointerSizeInBytes; + }; + + /// The size and alignment of size_t. + union { unsigned char SizeSizeInBytes; // sizeof(size_t) unsigned char SizeAlignInBytes; }; + CharUnits getSizeSize() const { return CharUnits::fromQuantity(SizeSizeInBytes); } Index: cfe/trunk/test/CodeGenOpenCL/size_t.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/size_t.cl +++ cfe/trunk/test/CodeGenOpenCL/size_t.cl @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir-unknown-unknown -o - | FileCheck --check-prefix=SZ32 %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple spir64-unknown-unknown -o - | FileCheck --check-prefix=SZ64 --check-prefix=SZ64ONLY %s +// RUN: %clang_cc1 %s -cl-std=CL2.0 -finclude-default-header -emit-llvm -O0 -triple amdgcn-- -o - | FileCheck --check-prefix=SZ64 --check-prefix=AMDONLY %s + +//SZ32: define{{.*}} i32 @test_ptrtoint_private(i8* %x) +//SZ32: ptrtoint i8* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_ptrtoint_private(i8* %x) +//SZ64: ptrtoint i8* %{{.*}} to i64 +size_t test_ptrtoint_private(private char* x) { + return (size_t)x; +} + +//SZ32: define{{.*}} i32 @test_ptrtoint_global(i8 addrspace(1)* %x) +//SZ32: ptrtoint i8 addrspace(1)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_ptrtoint_global(i8 addrspace(1)* %x) +//SZ64: ptrtoint i8 addrspace(1)* %{{.*}} to i64 +intptr_t test_ptrtoint_global(global char* x) { + return (intptr_t)x; +} + +//SZ32: define{{.*}} i32 @test_ptrtoint_constant(i8 addrspace(2)* %x) +//SZ32: ptrtoint i8 addrspace(2)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_ptrtoint_constant(i8 addrspace(2)* %x) +//SZ64: ptrtoint i8 addrspace(2)* %{{.*}} to i64 +uintptr_t test_ptrtoint_constant(constant char* x) { + return (uintptr_t)x; +} + +//SZ32: define{{.*}} i32 @test_ptrtoint_local(i8 addrspace(3)* %x) +//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_ptrtoint_local(i8 addrspace(3)* %x) +//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64 +size_t test_ptrtoint_local(local char* x) { + return (size_t)x; +} + +//SZ32: define{{.*}} i32 @test_ptrtoint_generic(i8 addrspace(4)* %x) +//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_ptrtoint_generic(i8 addrspace(4)* %x) +//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64 +size_t test_ptrtoint_generic(generic char* x) { + return (size_t)x; +} + +//SZ32: define{{.*}} i8* @test_inttoptr_private(i32 %x) +//SZ32: inttoptr i32 %{{.*}} to i8* +//SZ64: define{{.*}} i8* @test_inttoptr_private(i64 %x) +//AMDONLY: trunc i64 %{{.*}} to i32 +//AMDONLY: inttoptr i32 %{{.*}} to i8* +//SZ64ONLY: inttoptr i64 %{{.*}} to i8* +private char* test_inttoptr_private(size_t x) { + return (private char*)x; +} + +//SZ32: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i32 %x) +//SZ32: inttoptr i32 %{{.*}} to i8 addrspace(1)* +//SZ64: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i64 %x) +//SZ64: inttoptr i64 %{{.*}} to i8 addrspace(1)* +global char* test_inttoptr_global(size_t x) { + return (global char*)x; +} + +//SZ32: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i32 %y) +//SZ32: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32 +//SZ64: define{{.*}} i8 addrspace(3)* @test_add_local(i8 addrspace(3)* %x, i64 %y) +//AMDONLY: trunc i64 %{{.*}} to i32 +//AMDONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i32 +//SZ64ONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i64 +local char* test_add_local(local char* x, ptrdiff_t y) { + return x + y; +} + +//SZ32: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i32 %y) +//SZ32: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i32 +//SZ64: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i64 %y) +//SZ64: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i64 +global char* test_add_global(global char* x, ptrdiff_t y) { + return x + y; +} + +//SZ32: define{{.*}} i32 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y) +//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32 +//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y) +//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64 +//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64 +ptrdiff_t test_sub_local(local char* x, local char *y) { + return x - y; +} + +//SZ32: define{{.*}} i32 @test_sub_private(i8* %x, i8* %y) +//SZ32: ptrtoint i8* %{{.*}} to i32 +//SZ32: ptrtoint i8* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_sub_private(i8* %x, i8* %y) +//SZ64: ptrtoint i8* %{{.*}} to i64 +//SZ64: ptrtoint i8* %{{.*}} to i64 +ptrdiff_t test_sub_private(private char* x, private char *y) { + return x - y; +} + +//SZ32: define{{.*}} i32 @test_sub_mix(i8* %x, i8 addrspace(4)* %y) +//SZ32: ptrtoint i8* %{{.*}} to i32 +//SZ32: ptrtoint i8 addrspace(4)* %{{.*}} to i32 +//SZ64: define{{.*}} i64 @test_sub_mix(i8* %x, i8 addrspace(4)* %y) +//SZ64: ptrtoint i8* %{{.*}} to i64 +//SZ64: ptrtoint i8 addrspace(4)* %{{.*}} to i64 +ptrdiff_t test_sub_mix(private char* x, generic char *y) { + return x - y; +} +