[clang] Fix function pointer address space
Functions pointers should be created with program address space. This patch introduces program address space in TargetInfo. Targets with non-default (default is 0) address space for functions should explicitly set this value. This patch fixes a crash on lvalue reference to function pointer (in device code) when using oneAPI DPC++ compiler. Differential Revision: https://reviews.llvm.org/D111566
This commit is contained in:
@@ -2727,13 +2727,9 @@ public:
|
||||
QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
|
||||
QualType typeDomain) const;
|
||||
|
||||
unsigned getTargetAddressSpace(QualType T) const {
|
||||
return getTargetAddressSpace(T.getQualifiers());
|
||||
}
|
||||
unsigned getTargetAddressSpace(QualType T) const;
|
||||
|
||||
unsigned getTargetAddressSpace(Qualifiers Q) const {
|
||||
return getTargetAddressSpace(Q.getAddressSpace());
|
||||
}
|
||||
unsigned getTargetAddressSpace(Qualifiers Q) const;
|
||||
|
||||
unsigned getTargetAddressSpace(LangAS AS) const;
|
||||
|
||||
|
||||
@@ -212,6 +212,7 @@ protected:
|
||||
unsigned char RegParmMax, SSERegParmMax;
|
||||
TargetCXXABI TheCXXABI;
|
||||
const LangASMap *AddrSpaceMap;
|
||||
unsigned ProgramAddrSpace;
|
||||
|
||||
mutable StringRef PlatformName;
|
||||
mutable VersionTuple PlatformMinVersion;
|
||||
@@ -767,6 +768,9 @@ public:
|
||||
return getTypeWidth(IntMaxType);
|
||||
}
|
||||
|
||||
/// Return the address space for functions for the given target.
|
||||
unsigned getProgramAddressSpace() const { return ProgramAddrSpace; }
|
||||
|
||||
// Return the size of unwind_word for this target.
|
||||
virtual unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
|
||||
|
||||
|
||||
@@ -11575,6 +11575,15 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
|
||||
return getTargetInfo().getNullPointerValue(AS);
|
||||
}
|
||||
|
||||
unsigned ASTContext::getTargetAddressSpace(QualType T) const {
|
||||
return T->isFunctionType() ? getTargetInfo().getProgramAddressSpace()
|
||||
: getTargetAddressSpace(T.getQualifiers());
|
||||
}
|
||||
|
||||
unsigned ASTContext::getTargetAddressSpace(Qualifiers Q) const {
|
||||
return getTargetAddressSpace(Q.getAddressSpace());
|
||||
}
|
||||
|
||||
unsigned ASTContext::getTargetAddressSpace(LangAS AS) const {
|
||||
if (isTargetAddressSpace(AS))
|
||||
return toTargetAddressSpace(AS);
|
||||
|
||||
@@ -150,6 +150,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
|
||||
PlatformMinVersion = VersionTuple();
|
||||
|
||||
MaxOpenCLWorkGroupSize = 1024;
|
||||
ProgramAddrSpace = 0;
|
||||
}
|
||||
|
||||
// Out of line virtual dtor for TargetInfo.
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
Int16Type = SignedInt;
|
||||
Char32Type = UnsignedLong;
|
||||
SigAtomicType = SignedChar;
|
||||
ProgramAddrSpace = 1;
|
||||
resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
|
||||
}
|
||||
|
||||
|
||||
@@ -643,11 +643,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
||||
llvm::Type *PointeeType = ConvertTypeForMem(ETy);
|
||||
if (PointeeType->isVoidTy())
|
||||
PointeeType = llvm::Type::getInt8Ty(getLLVMContext());
|
||||
|
||||
unsigned AS = PointeeType->isFunctionTy()
|
||||
? getDataLayout().getProgramAddressSpace()
|
||||
: Context.getTargetAddressSpace(ETy);
|
||||
|
||||
unsigned AS = Context.getTargetAddressSpace(ETy);
|
||||
ResultType = llvm::PointerType::get(PointeeType, AS);
|
||||
break;
|
||||
}
|
||||
@@ -748,7 +744,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
||||
llvm::Type *PointeeType = CGM.getLangOpts().OpenCL
|
||||
? CGM.getGenericBlockLiteralType()
|
||||
: ConvertTypeForMem(FTy);
|
||||
unsigned AS = Context.getTargetAddressSpace(FTy);
|
||||
// Block pointers lower to function type. For function type,
|
||||
// getTargetAddressSpace() returns default address space for
|
||||
// function pointer i.e. program address space. Therefore, for block
|
||||
// pointers, it is important to pass qualifiers when calling
|
||||
// getTargetAddressSpace(), to ensure that we get the address space
|
||||
// for data pointers and not function pointers.
|
||||
unsigned AS = Context.getTargetAddressSpace(FTy.getQualifiers());
|
||||
ResultType = llvm::PointerType::get(PointeeType, AS);
|
||||
break;
|
||||
}
|
||||
|
||||
8
clang/test/CodeGen/avr/functionptr-addrspace.c
Normal file
8
clang/test/CodeGen/avr/functionptr-addrspace.c
Normal file
@@ -0,0 +1,8 @@
|
||||
// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
int main() {
|
||||
int (*p)();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK: %p = alloca i16 (...) addrspace(1)*
|
||||
25
clang/test/CodeGenSYCL/functionptr-addrspace.cpp
Normal file
25
clang/test/CodeGenSYCL/functionptr-addrspace.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -triple spir64 -verify -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
template <typename Name, typename Func>
|
||||
__attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
|
||||
kernelFunc();
|
||||
}
|
||||
|
||||
// CHECK: define dso_local spir_func{{.*}}invoke_function{{.*}}(i32 ()* %fptr, i32 addrspace(4)* %ptr)
|
||||
void invoke_function(int (*fptr)(), int *ptr) {}
|
||||
|
||||
int f() { return 0; }
|
||||
|
||||
int main() {
|
||||
kernel_single_task<class fake_kernel>([=]() {
|
||||
int (*p)() = f;
|
||||
int (&r)() = *p;
|
||||
int a = 10;
|
||||
invoke_function(p, &a);
|
||||
invoke_function(r, &a);
|
||||
invoke_function(f, &a);
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user