Skip to content

Commit 4eaf584

Browse files
[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
1 parent 1fa4778 commit 4eaf584

File tree

8 files changed

+58
-12
lines changed

8 files changed

+58
-12
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2727,13 +2727,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
27272727
QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
27282728
QualType typeDomain) const;
27292729

2730-
unsigned getTargetAddressSpace(QualType T) const {
2731-
return getTargetAddressSpace(T.getQualifiers());
2732-
}
2730+
unsigned getTargetAddressSpace(QualType T) const;
27332731

2734-
unsigned getTargetAddressSpace(Qualifiers Q) const {
2735-
return getTargetAddressSpace(Q.getAddressSpace());
2736-
}
2732+
unsigned getTargetAddressSpace(Qualifiers Q) const;
27372733

27382734
unsigned getTargetAddressSpace(LangAS AS) const;
27392735

clang/include/clang/Basic/TargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
212212
unsigned char RegParmMax, SSERegParmMax;
213213
TargetCXXABI TheCXXABI;
214214
const LangASMap *AddrSpaceMap;
215+
unsigned ProgramAddrSpace;
215216

216217
mutable StringRef PlatformName;
217218
mutable VersionTuple PlatformMinVersion;
@@ -767,6 +768,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
767768
return getTypeWidth(IntMaxType);
768769
}
769770

771+
/// Return the address space for functions for the given target.
772+
unsigned getProgramAddressSpace() const { return ProgramAddrSpace; }
773+
770774
// Return the size of unwind_word for this target.
771775
virtual unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
772776

clang/lib/AST/ASTContext.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11575,6 +11575,15 @@ uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
1157511575
return getTargetInfo().getNullPointerValue(AS);
1157611576
}
1157711577

11578+
unsigned ASTContext::getTargetAddressSpace(QualType T) const {
11579+
return T->isFunctionType() ? getTargetInfo().getProgramAddressSpace()
11580+
: getTargetAddressSpace(T.getQualifiers());
11581+
}
11582+
11583+
unsigned ASTContext::getTargetAddressSpace(Qualifiers Q) const {
11584+
return getTargetAddressSpace(Q.getAddressSpace());
11585+
}
11586+
1157811587
unsigned ASTContext::getTargetAddressSpace(LangAS AS) const {
1157911588
if (isTargetAddressSpace(AS))
1158011589
return toTargetAddressSpace(AS);

clang/lib/Basic/TargetInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
150150
PlatformMinVersion = VersionTuple();
151151

152152
MaxOpenCLWorkGroupSize = 1024;
153+
ProgramAddrSpace = 0;
153154
}
154155

155156
// Out of line virtual dtor for TargetInfo.

clang/lib/Basic/Targets/AVR.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
5555
Int16Type = SignedInt;
5656
Char32Type = UnsignedLong;
5757
SigAtomicType = SignedChar;
58+
ProgramAddrSpace = 1;
5859
resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
5960
}
6061

clang/lib/CodeGen/CodeGenTypes.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -643,11 +643,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
643643
llvm::Type *PointeeType = ConvertTypeForMem(ETy);
644644
if (PointeeType->isVoidTy())
645645
PointeeType = llvm::Type::getInt8Ty(getLLVMContext());
646-
647-
unsigned AS = PointeeType->isFunctionTy()
648-
? getDataLayout().getProgramAddressSpace()
649-
: Context.getTargetAddressSpace(ETy);
650-
646+
unsigned AS = Context.getTargetAddressSpace(ETy);
651647
ResultType = llvm::PointerType::get(PointeeType, AS);
652648
break;
653649
}
@@ -748,7 +744,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
748744
llvm::Type *PointeeType = CGM.getLangOpts().OpenCL
749745
? CGM.getGenericBlockLiteralType()
750746
: ConvertTypeForMem(FTy);
751-
unsigned AS = Context.getTargetAddressSpace(FTy);
747+
// Block pointers lower to function type. For function type,
748+
// getTargetAddressSpace() returns default address space for
749+
// function pointer i.e. program address space. Therefore, for block
750+
// pointers, it is important to pass qualifiers when calling
751+
// getTargetAddressSpace(), to ensure that we get the address space
752+
// for data pointers and not function pointers.
753+
unsigned AS = Context.getTargetAddressSpace(FTy.getQualifiers());
752754
ResultType = llvm::PointerType::get(PointeeType, AS);
753755
break;
754756
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 -triple avr -emit-llvm %s -o - | FileCheck %s
2+
3+
int main() {
4+
int (*p)();
5+
return 0;
6+
}
7+
8+
// CHECK: %p = alloca i16 (...) addrspace(1)*
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -triple spir64 -verify -emit-llvm %s -o - | FileCheck %s
2+
3+
// expected-no-diagnostics
4+
5+
template <typename Name, typename Func>
6+
__attribute__((sycl_kernel)) void kernel_single_task(const Func &kernelFunc) {
7+
kernelFunc();
8+
}
9+
10+
// CHECK: define dso_local spir_func{{.*}}invoke_function{{.*}}(i32 ()* %fptr, i32 addrspace(4)* %ptr)
11+
void invoke_function(int (*fptr)(), int *ptr) {}
12+
13+
int f() { return 0; }
14+
15+
int main() {
16+
kernel_single_task<class fake_kernel>([=]() {
17+
int (*p)() = f;
18+
int (&r)() = *p;
19+
int a = 10;
20+
invoke_function(p, &a);
21+
invoke_function(r, &a);
22+
invoke_function(f, &a);
23+
});
24+
return 0;
25+
}

0 commit comments

Comments
 (0)