[clang] 4eaf584 - [clang] Fix function pointer address space

Elizabeth Andrews via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 13 08:12:28 PST 2022


Author: Elizabeth Andrews
Date: 2022-01-13T08:06:19-08:00
New Revision: 4eaf5846d0e738264d9328b4a919bc352ea83b7a

URL: https://github.com/llvm/llvm-project/commit/4eaf5846d0e738264d9328b4a919bc352ea83b7a
DIFF: https://github.com/llvm/llvm-project/commit/4eaf5846d0e738264d9328b4a919bc352ea83b7a.diff

LOG: [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

Added: 
    clang/test/CodeGen/avr/functionptr-addrspace.c
    clang/test/CodeGenSYCL/functionptr-addrspace.cpp

Modified: 
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/Basic/TargetInfo.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/Basic/TargetInfo.cpp
    clang/lib/Basic/Targets/AVR.h
    clang/lib/CodeGen/CodeGenTypes.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 7a9e3a643d6f4..c5946b662cb29 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2727,13 +2727,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   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;
 

diff  --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 46eb190333aa2..686a365b8c12d 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -212,6 +212,7 @@ class TargetInfo : public virtual TransferrableTargetInfo,
   unsigned char RegParmMax, SSERegParmMax;
   TargetCXXABI TheCXXABI;
   const LangASMap *AddrSpaceMap;
+  unsigned ProgramAddrSpace;
 
   mutable StringRef PlatformName;
   mutable VersionTuple PlatformMinVersion;
@@ -767,6 +768,9 @@ class TargetInfo : public virtual TransferrableTargetInfo,
     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); }
 

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6f3c0dc14867a..9d63724c919a0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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);

diff  --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index ddb20008bc9da..4fd31647bab24 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -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.

diff  --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h
index 89a80ca6a39a3..a281e2c2cd744 100644
--- a/clang/lib/Basic/Targets/AVR.h
+++ b/clang/lib/Basic/Targets/AVR.h
@@ -55,6 +55,7 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
     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");
   }
 

diff  --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 77721510dfd0f..4839e22c4b144 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -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;
   }

diff  --git a/clang/test/CodeGen/avr/functionptr-addrspace.c b/clang/test/CodeGen/avr/functionptr-addrspace.c
new file mode 100644
index 0000000000000..90ec121319074
--- /dev/null
+++ b/clang/test/CodeGen/avr/functionptr-addrspace.c
@@ -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)*

diff  --git a/clang/test/CodeGenSYCL/functionptr-addrspace.cpp b/clang/test/CodeGenSYCL/functionptr-addrspace.cpp
new file mode 100644
index 0000000000000..26b7c3340ac37
--- /dev/null
+++ b/clang/test/CodeGenSYCL/functionptr-addrspace.cpp
@@ -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;
+}


        


More information about the cfe-commits mailing list