https://github.com/Fznamznon created 
https://github.com/llvm/llvm-project/pull/140230

None

>From eeea84b4989b4497cc804f403258b986c09cf5ab Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andr...@intel.com>
Date: Thu, 8 Aug 2024 18:05:48 -0700
Subject: [PATCH 1/5] [SYCL] Add support for __builtin_sycl_kernel_name

The builtin takes the kernel name type as it's argument
and returns the mangled name for the kernel caller
function.
---
 clang/include/clang/Basic/Builtins.h          |  1 +
 clang/include/clang/Basic/Builtins.td         |  7 +++
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 +
 clang/lib/Basic/Builtins.cpp                  |  3 +
 clang/lib/CodeGen/CGBuiltin.cpp               | 20 +++++++
 clang/lib/Sema/SemaChecking.cpp               | 33 ++++++++++
 .../CodeGenSYCL/builtin-sycl-kernel-name.cpp  | 60 +++++++++++++++++++
 .../SemaSYCL/builtin-sycl-kernel-name.cpp     | 44 ++++++++++++++
 8 files changed, 171 insertions(+)
 create mode 100644 clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
 create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp

diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index 3a5e31de2bc50..0bea100b7e6de 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -45,6 +45,7 @@ enum LanguageID : uint16_t {
   ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages.
   HLSL_LANG = 0x1000,        // builtin requires HLSL.
   C23_LANG = 0x2000,         // builtin requires C23 or later.
+  SYCL_LANG = 0x2000,        // builtin requires SYCL.
   ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
   ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG,  // builtin requires GNU mode.
   ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG     // builtin requires MS mode.
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 11b1e247237a7..13e02898e55aa 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4794,6 +4794,13 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
   let Prototype = "char const*(...)";
 }
 
+// SYCL
+def SYCLKernelName : LangBuiltin<"SYCL_LANG"> {
+  let Spellings = ["__builtin_sycl_kernel_name"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "char const*(...)";
+}
+
 // HLSL
 def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_adduint64"];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6e940a318b61d..d9f7487f2596e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12789,6 +12789,9 @@ def err_sycl_entry_point_deduced_return_type : Error<
 def warn_cuda_maxclusterrank_sm_90 : Warning<
   "maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring "
   "%1 attribute">, InGroup<IgnoredAttributes>;
+def err_builtin_invalid_argument_count : Error<"builtin requires exactly 1 
argument">;
+def err_builtin_invalid_argument : Error<"invalid argument; argument must be a 
class or struct type"
+                                         " with a member type alias named 
'type'">;
 
 // VTable pointer authentication errors
 def err_non_polymorphic_vtable_pointer_auth : Error<
diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp
index 885abdc152e3a..f8275656c5d0c 100644
--- a/clang/lib/Basic/Builtins.cpp
+++ b/clang/lib/Basic/Builtins.cpp
@@ -185,6 +185,9 @@ static bool builtinIsSupported(const llvm::StringTable 
&Strings,
   /* CUDA Unsupported */
   if (!LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG)
     return false;
+  /*  SYCL Unsupported */
+  if (!LangOpts.isSYCL() && BuiltinInfo.Langs == SYCL_LANG)
+    return false;
   /* CPlusPlus Unsupported */
   if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
     return false;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4fdf2113cb9dc..b7638ed0b27f1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -29,6 +29,7 @@
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Intrinsics.h"
@@ -6219,6 +6220,25 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
     auto Str = CGM.GetAddrOfConstantCString(Name, "");
     return RValue::get(Str.getPointer());
   }
+  case Builtin::BI__builtin_sycl_kernel_name: {
+    ASTContext &Ctx = getContext();
+    // Argument to the builtin is a kernel_id_t type trait which is used
+    // to retrieve the kernel name type.
+    RecordDecl *RD = E->getArg(0)->getType()->castAs<RecordType>()->getDecl();
+    IdentifierTable &IdentTable = Ctx.Idents;
+    auto Name = DeclarationName(&(IdentTable.get("type")));
+    NamedDecl *ND = (RD->lookup(Name)).front();
+    TypeAliasDecl *TD = cast<TypeAliasDecl>(ND);
+    QualType KernelNameType = TD->getUnderlyingType().getCanonicalType();
+
+    // Retrieve the mangled name corresponding to kernel name type.
+    const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType);
+    assert(KernelInfo && "Type does not correspond to a SYCL kernel name.");
+    
+    // Emit the mangled name.
+    auto Str = CGM.GetAddrOfConstantCString(KernelInfo->GetKernelName(), "");
+    return RValue::get(Str.getPointer());
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index d7c62b44a5c50..32148c1e2d9dc 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2219,6 +2219,25 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, 
CallExpr *TheCall) {
   return false;
 }
 
+// The argument must be a class or struct with a member
+// named type.
+static bool CheckBuiltinSyclKernelName(Sema &S, CallExpr *TheCall) {
+  QualType ArgTy = TheCall->getArg(0)->getType();
+  const auto *RT = ArgTy->getAs<RecordType>();
+
+  if(!RT)
+    return true;
+
+  RecordDecl *RD = RT->getDecl();
+  IdentifierTable &IdentTable = S.Context.Idents;
+  auto Name = DeclarationName(&(IdentTable.get("type")));
+  DeclContext::lookup_result Lookup = RD->lookup(Name);
+  if (Lookup.empty() || !Lookup.isSingleResult() || 
!isa<TypeAliasDecl>(Lookup.front()))
+    return true;
+
+  return false;
+}
+
 ExprResult
 Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
                                CallExpr *TheCall) {
@@ -3030,6 +3049,20 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     }
     break;
   }
+  case Builtin::BI__builtin_sycl_kernel_name: {
+    // Builtin takes 1 argument
+    if (TheCall->getNumArgs() != 1) {
+      Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count);
+      return ExprError();
+    }
+
+    if (CheckBuiltinSyclKernelName(*this, TheCall)) {
+      Diag(TheCall->getArg(0)->getBeginLoc(), 
diag::err_builtin_invalid_argument);
+      return ExprError();
+    }
+
+    break;
+  }
   case Builtin::BI__builtin_popcountg:
     if (BuiltinPopcountg(*this, TheCall))
       return ExprError();
diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
new file mode 100644
index 0000000000000..8749d30e54f6e
--- /dev/null
+++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64 %s -o - | 
FileCheck %s
+
+// Test IR generated by __builtin_sycl_kernel_name(). This builtin accepts a 
SYCL
+// kernel name type and returns it's mangled name.
+
+class kernel_name_1;
+class kernel_name_2;
+typedef kernel_name_2 kernel_name_TD;
+class kernel_name_3;
+class kernel_name_4;
+typedef kernel_name_4 kernel_name_TD2;
+
+template<typename KN>
+struct kernel_id_t {
+  using type = KN;
+};
+
+struct kernel_id_nt {
+  using type = kernel_name_3;
+};
+
+template <typename name, typename Func>
+__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const 
Func kernelFunc) {
+  kernelFunc();
+}
+
+struct SYCLKernel {
+  int m;
+  public:
+  void operator()() const {}
+};
+
+void test() {
+  SYCLKernel Obj;
+  kernel_single_task<kernel_name_1>(Obj);
+  kernel_single_task<kernel_name_TD>(Obj);
+  kernel_single_task<kernel_name_3>(Obj);
+  kernel_single_task<kernel_name_TD2>(Obj);
+  const char* test1 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_1>());
+  const char* test2 = 
__builtin_sycl_kernel_name(kernel_id_t<kernel_name_TD>());
+  const char* test3 = __builtin_sycl_kernel_name(kernel_id_nt());
+  const char* test4 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_4>());
+}
+
+// Kernel names retrieved from KernelInfo map
+// CHECK: @0 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_1Evv\00", align 1
+// CHECK: @1 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_2Evv\00", align 1
+// CHECK: @2 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_3Evv\00", align 1
+// CHECK: @3 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_4Evv\00", align 1
+
+// CHECK: define dso_local void @_Z4testv()
+// CHECK: %test1 = alloca ptr, align 8
+// CHECK: %test2 = alloca ptr, align 8
+// CHECK: %test3 = alloca ptr, align 8
+// CHECK: %test4 = alloca ptr, align 8
+// CHECK: store ptr @0, ptr %test1, align 8
+// CHECK: store ptr @1, ptr %test2, align 8
+// CHECK: store ptr @2, ptr %test3, align 8
+// CHECK: store ptr @3, ptr %test4, align 8
+
diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
new file mode 100644
index 0000000000000..65573aa9a7548
--- /dev/null
+++ b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s
+
+class kernel_name_1;
+class kernel_name_2;
+class kernel_name_3;
+typedef kernel_name_3 kernel_name_TD;
+
+template<typename KN>
+struct kernel_id_1 {
+  using type = KN;
+};
+
+struct kernel_id_2 {
+  using type = kernel_name_2;
+};
+
+struct kernel_id_3 {
+  using invalid_name = kernel_name_2;
+};
+
+template <typename name, typename Func>
+__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const 
Func kernelFunc) {
+  kernelFunc();
+}
+
+struct SYCLKernel {
+  int m;
+  public:
+  void operator()() const {}
+};
+
+void test() {
+  SYCLKernel Obj;
+  kernel_single_task<kernel_name_1>(Obj);
+  kernel_single_task<kernel_name_2>(Obj);
+  kernel_single_task<kernel_name_TD>(Obj);
+  const char* test1 = 
__builtin_sycl_kernel_name(kernel_id_1<kernel_name_1>()); // Valid
+  const char* test2 = 
__builtin_sycl_kernel_name(kernel_id_1<kernel_name_TD>()); // Valid
+  const char* test3 = __builtin_sycl_kernel_name(kernel_id_2()); // Valid
+  const char* test4 = __builtin_sycl_kernel_name(kernel_id_3()); // 
expected-error {{invalid argument; argument must be a class or struct type with 
a member type alias named 'type'}}
+  const char* test5 = __builtin_sycl_kernel_name("str"); // expected-error 
{{invalid argument; argument must be a class or struct type with a member type 
alias named 'type'}}
+  const char* test6 = __builtin_sycl_kernel_name(kernel_id_2(), 
kernel_id_2()); // expected-error {{builtin requires exactly 1 argument}}
+}
+

>From bef098187f090af3083eb00744def8477dee0d9a Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andr...@intel.com>
Date: Tue, 13 Aug 2024 19:08:03 -0700
Subject: [PATCH 2/5] [SYCL] Apply review comments - Builtins

---
 clang/include/clang/Basic/Builtins.td         |  2 +-
 .../clang/Basic/DiagnosticSemaKinds.td        |  9 ++--
 clang/lib/CodeGen/CGBuiltin.cpp               | 16 +++++++
 clang/lib/Sema/SemaChecking.cpp               |  9 ++--
 .../SemaSYCL/builtin-sycl-kernel-name.cpp     |  6 +--
 .../builtin-sycl-kernel-param-count.cpp       | 44 +++++++++++++++++++
 6 files changed, 76 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 13e02898e55aa..632dc8538a2a9 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4797,7 +4797,7 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
 // SYCL
 def SYCLKernelName : LangBuiltin<"SYCL_LANG"> {
   let Spellings = ["__builtin_sycl_kernel_name"];
-  let Attributes = [NoThrow, CustomTypeChecking];
+  let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
   let Prototype = "char const*(...)";
 }
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d9f7487f2596e..2da2045415596 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -815,6 +815,9 @@ def warn_unreachable_association : Warning<
   InGroup<UnreachableCodeGenericAssoc>;
 
 /// Built-in functions.
+def err_builtin_invalid_argument_count : Error<
+  "builtin %plural{0:takes no arguments|1:takes one argument|"
+  ":requires exactly %0 arguments}0">;
 def ext_implicit_lib_function_decl : ExtWarn<
   "implicitly declaring library function '%0' with type %1">,
   InGroup<ImplicitFunctionDeclare>;
@@ -12789,9 +12792,9 @@ def err_sycl_entry_point_deduced_return_type : Error<
 def warn_cuda_maxclusterrank_sm_90 : Warning<
   "maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring "
   "%1 attribute">, InGroup<IgnoredAttributes>;
-def err_builtin_invalid_argument_count : Error<"builtin requires exactly 1 
argument">;
-def err_builtin_invalid_argument : Error<"invalid argument; argument must be a 
class or struct type"
-                                         " with a member type alias named 
'type'">;
+def err_sycl_kernel_name_invalid_arg : Error<"invalid argument; expected a 
class "
+                                             "or structure with a member 
typedef "
+                                             "or type alias alias named 
'type'">;
 
 // VTable pointer authentication errors
 def err_non_polymorphic_vtable_pointer_auth : Error<
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b7638ed0b27f1..de3b4a42c433d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2527,6 +2527,22 @@ static RValue 
EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF,
   return RValue::get(CGF->Builder.CreateCall(UBF, Args));
 }
 
+static const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx,
+                                               const CallExpr *E) {
+  // Argument to the builtin is a type trait which is used to retrieve the
+  // kernel name type.
+  // FIXME: Improve the comment.
+  RecordDecl *RD = E->getArg(0)->getType()->castAs<RecordType>()->getDecl();
+  IdentifierTable &IdentTable = Ctx.Idents;
+  auto Name = DeclarationName(&(IdentTable.get("type")));
+  NamedDecl *ND = (RD->lookup(Name)).front();
+  TypedefNameDecl *TD = cast<TypedefNameDecl>(ND);
+  CanQualType KernelNameType = Ctx.getCanonicalType(TD->getUnderlyingType());
+
+  // Retrieve KernelInfo using the kernel name.
+  return Ctx.findSYCLKernelInfo(KernelNameType);
+}
+
 RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned 
BuiltinID,
                                         const CallExpr *E,
                                         ReturnValueSlot ReturnValue) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 32148c1e2d9dc..34786d3372bf4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2232,7 +2232,8 @@ static bool CheckBuiltinSyclKernelName(Sema &S, CallExpr 
*TheCall) {
   IdentifierTable &IdentTable = S.Context.Idents;
   auto Name = DeclarationName(&(IdentTable.get("type")));
   DeclContext::lookup_result Lookup = RD->lookup(Name);
-  if (Lookup.empty() || !Lookup.isSingleResult() || 
!isa<TypeAliasDecl>(Lookup.front()))
+  if (Lookup.empty() || !Lookup.isSingleResult() ||
+      !isa<TypedefNameDecl>(Lookup.front()))
     return true;
 
   return false;
@@ -3052,12 +3053,14 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
   case Builtin::BI__builtin_sycl_kernel_name: {
     // Builtin takes 1 argument
     if (TheCall->getNumArgs() != 1) {
-      Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count);
+      Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count)
+          << 1;
       return ExprError();
     }
 
     if (CheckBuiltinSyclKernelName(*this, TheCall)) {
-      Diag(TheCall->getArg(0)->getBeginLoc(), 
diag::err_builtin_invalid_argument);
+      Diag(TheCall->getArg(0)->getBeginLoc(),
+           diag::err_sycl_kernel_name_invalid_arg);
       return ExprError();
     }
 
diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
index 65573aa9a7548..18e4515a6ad58 100644
--- a/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
+++ b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
@@ -37,8 +37,8 @@ void test() {
   const char* test1 = 
__builtin_sycl_kernel_name(kernel_id_1<kernel_name_1>()); // Valid
   const char* test2 = 
__builtin_sycl_kernel_name(kernel_id_1<kernel_name_TD>()); // Valid
   const char* test3 = __builtin_sycl_kernel_name(kernel_id_2()); // Valid
-  const char* test4 = __builtin_sycl_kernel_name(kernel_id_3()); // 
expected-error {{invalid argument; argument must be a class or struct type with 
a member type alias named 'type'}}
-  const char* test5 = __builtin_sycl_kernel_name("str"); // expected-error 
{{invalid argument; argument must be a class or struct type with a member type 
alias named 'type'}}
-  const char* test6 = __builtin_sycl_kernel_name(kernel_id_2(), 
kernel_id_2()); // expected-error {{builtin requires exactly 1 argument}}
+  const char* test4 = __builtin_sycl_kernel_name(kernel_id_3()); // 
expected-error {{invalid argument; expected a class or structure with a member 
typedef or type alias alias named 'type'}}
+  const char* test5 = __builtin_sycl_kernel_name("str"); // expected-error 
{{invalid argument; expected a class or structure with a member typedef or type 
alias alias named 'type'}}
+  const char* test6 = __builtin_sycl_kernel_name(kernel_id_2(), 
kernel_id_2()); // expected-error {{builtin takes one argument}}
 }
 
diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp 
b/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp
new file mode 100644
index 0000000000000..831aed34e66e5
--- /dev/null
+++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s
+
+class kernel_name_1;
+class kernel_name_2;
+class kernel_name_3;
+typedef kernel_name_3 kernel_name_TD;
+
+template<typename KN>
+struct kernel_id_1 {
+  using type = KN;
+};
+
+struct kernel_id_2 {
+  using type = kernel_name_2;
+};
+
+struct kernel_id_3 {
+  using invalid_name = kernel_name_2;
+};
+
+template <typename name, typename Func>
+__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const 
Func kernelFunc) {
+  kernelFunc();
+}
+
+struct SYCLKernel {
+  int m;
+  public:
+  void operator()() const {}
+};
+
+void test() {
+  SYCLKernel Obj;
+  kernel_single_task<kernel_name_1>(Obj);
+  kernel_single_task<kernel_name_2>(Obj);
+  kernel_single_task<kernel_name_TD>(Obj);
+  int test1 = __builtin_sycl_kernel_param_count(kernel_id_1<kernel_name_1>()); 
// Valid
+  int test2 = 
__builtin_sycl_kernel_param_count(kernel_id_1<kernel_name_TD>()); // Valid
+  int test3 = __builtin_sycl_kernel_param_count(kernel_id_2()); // Valid
+  int test4 = __builtin_sycl_kernel_param_count(kernel_id_3()); // 
expected-error {{invalid argument; expected a class or structure with a member 
typedef or type alias alias named 'type'}}
+  int test5 = __builtin_sycl_kernel_param_count("str"); // expected-error 
{{invalid argument; expected a class or structure with a member typedef or type 
alias alias named 'type'}}
+  int test6 = __builtin_sycl_kernel_param_count(kernel_id_2(), kernel_id_2()); 
// expected-error {{builtin takes one argument}}
+}
+

>From adcef733a7ee23dd64f50389fd0f3dab3c6e7a46 Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andr...@intel.com>
Date: Tue, 3 Sep 2024 16:45:28 -0700
Subject: [PATCH 3/5] Add constant evaluation support for builtins

---
 clang/include/clang/Basic/Builtins.h          |  2 +-
 clang/lib/AST/ExprConstant.cpp                | 38 +++++++++++++++++++
 .../CodeGenSYCL/builtin-sycl-kernel-name.cpp  |  7 ++++
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index 0bea100b7e6de..6d8914d7074d4 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -45,7 +45,7 @@ enum LanguageID : uint16_t {
   ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages.
   HLSL_LANG = 0x1000,        // builtin requires HLSL.
   C23_LANG = 0x2000,         // builtin requires C23 or later.
-  SYCL_LANG = 0x2000,        // builtin requires SYCL.
+  SYCL_LANG = 0x4000,        // builtin requires SYCL.
   ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
   ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG,  // builtin requires GNU mode.
   ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG     // builtin requires MS mode.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 86dbb349fd1a7..5be35c93f0aa1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -52,6 +52,7 @@
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/APFixedPoint.h"
 #include "llvm/ADT/Sequence.h"
@@ -9918,6 +9919,26 @@ static bool isOneByteCharacterType(QualType T) {
   return T->isCharType() || T->isChar8Type();
 }
 
+static const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx,
+                                               const CallExpr *E) {
+  // Argument to the builtin is a type trait which is used to retrieve the
+  // kernel name type.
+  // FIXME: Improve the comment.
+  const Expr *NameExpr = E->getArg(0);
+  // FIXME: Implement diagnostic instead of assert.
+  assert(NameExpr->isEvaluatable(Ctx) &&
+         "KernelNameType should be evaluatable");
+  RecordDecl *RD = NameExpr->getType()->castAs<RecordType>()->getDecl();
+  IdentifierTable &IdentTable = Ctx.Idents;
+  auto Name = DeclarationName(&(IdentTable.get("type")));
+  NamedDecl *ND = (RD->lookup(Name)).front();
+  TypedefNameDecl *TD = cast<TypedefNameDecl>(ND);
+  CanQualType KernelNameType = Ctx.getCanonicalType(TD->getUnderlyingType());
+
+  // Retrieve KernelInfo using the kernel name.
+  return Ctx.findSYCLKernelInfo(KernelNameType);
+}
+
 bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
                                                 unsigned BuiltinOp) {
   if (IsOpaqueConstantCall(E))
@@ -10273,6 +10294,23 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const 
CallExpr *E,
         return false;
     }
   }
+  case Builtin::BI__builtin_sycl_kernel_name: {
+    const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(Info.Ctx, E);
+    assert(KernelInfo && "Type does not correspond to a SYCL kernel name.");
+    // Retrieve the mangled name corresponding to kernel name type.
+    std::string ResultStr = KernelInfo->GetKernelName();
+    APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
+               ResultStr.size() + 1);
+    QualType StrTy =
+        Info.Ctx.getConstantArrayType(Info.Ctx.CharTy.withConst(), Size,
+                                      nullptr, ArraySizeModifier::Normal, 0);
+    StringLiteral *SL =
+        StringLiteral::Create(Info.Ctx, ResultStr, StringLiteralKind::Ordinary,
+                              /*Pascal*/ false, StrTy, SourceLocation());
+    evaluateLValue(SL, Result);
+    Result.addArray(Info, E, cast<ConstantArrayType>(StrTy));
+    return true;
+  }
 
   default:
     return false;
diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
index 8749d30e54f6e..756d6f79153d7 100644
--- a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
+++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
@@ -10,6 +10,8 @@ class kernel_name_3;
 class kernel_name_4;
 typedef kernel_name_4 kernel_name_TD2;
 
+struct constexpr_kernel_name;
+
 template<typename KN>
 struct kernel_id_t {
   using type = KN;
@@ -36,10 +38,12 @@ void test() {
   kernel_single_task<kernel_name_TD>(Obj);
   kernel_single_task<kernel_name_3>(Obj);
   kernel_single_task<kernel_name_TD2>(Obj);
+  kernel_single_task<constexpr_kernel_name>(Obj);
   const char* test1 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_1>());
   const char* test2 = 
__builtin_sycl_kernel_name(kernel_id_t<kernel_name_TD>());
   const char* test3 = __builtin_sycl_kernel_name(kernel_id_nt());
   const char* test4 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_4>());
+  constexpr const char* test5 = 
__builtin_sycl_kernel_name(kernel_id_t<constexpr_kernel_name>());
 }
 
 // Kernel names retrieved from KernelInfo map
@@ -47,14 +51,17 @@ void test() {
 // CHECK: @1 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_2Evv\00", align 1
 // CHECK: @2 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_3Evv\00", align 1
 // CHECK: @3 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_4Evv\00", align 1
+// CHECK: @.str = private unnamed_addr constant [52 x i8] 
c"_Z20__sycl_kernel_callerI21constexpr_kernel_nameEvv\00", align 1
 
 // CHECK: define dso_local void @_Z4testv()
 // CHECK: %test1 = alloca ptr, align 8
 // CHECK: %test2 = alloca ptr, align 8
 // CHECK: %test3 = alloca ptr, align 8
 // CHECK: %test4 = alloca ptr, align 8
+// CHECK: %test5 = alloca ptr, align 8
 // CHECK: store ptr @0, ptr %test1, align 8
 // CHECK: store ptr @1, ptr %test2, align 8
 // CHECK: store ptr @2, ptr %test3, align 8
 // CHECK: store ptr @3, ptr %test4, align 8
+// CHECK: store ptr @.str, ptr %test5, align 8
 

>From 9565308912d4f231fe49cbda26bdebd6b733e57b Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andr...@intel.com>
Date: Fri, 6 Sep 2024 12:45:35 -0700
Subject: [PATCH 4/5] Add builtin test with templates

---
 .../CodeGenSYCL/builtin-sycl-kernel-name.cpp     | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
index 756d6f79153d7..1086465084ca1 100644
--- a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
+++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
@@ -8,6 +8,7 @@ class kernel_name_2;
 typedef kernel_name_2 kernel_name_TD;
 class kernel_name_3;
 class kernel_name_4;
+class kernel_name_5;
 typedef kernel_name_4 kernel_name_TD2;
 
 struct constexpr_kernel_name;
@@ -32,6 +33,14 @@ struct SYCLKernel {
   void operator()() const {}
 };
 
+template<typename KernelName>
+void test_template() {
+  SYCLKernel Obj;
+  kernel_single_task<KernelName>(Obj);
+  const char* test6 = __builtin_sycl_kernel_name(kernel_id_t<KernelName>());
+  constexpr const char* test7 = 
__builtin_sycl_kernel_name(kernel_id_t<KernelName>());
+}
+
 void test() {
   SYCLKernel Obj;
   kernel_single_task<kernel_name_1>(Obj);
@@ -44,6 +53,7 @@ void test() {
   const char* test3 = __builtin_sycl_kernel_name(kernel_id_nt());
   const char* test4 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_4>());
   constexpr const char* test5 = 
__builtin_sycl_kernel_name(kernel_id_t<constexpr_kernel_name>());
+  test_template<kernel_name_5>();
 }
 
 // Kernel names retrieved from KernelInfo map
@@ -52,6 +62,7 @@ void test() {
 // CHECK: @2 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_3Evv\00", align 1
 // CHECK: @3 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_4Evv\00", align 1
 // CHECK: @.str = private unnamed_addr constant [52 x i8] 
c"_Z20__sycl_kernel_callerI21constexpr_kernel_nameEvv\00", align 1
+// CHECK: @4 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_5Evv\00", align 1
 
 // CHECK: define dso_local void @_Z4testv()
 // CHECK: %test1 = alloca ptr, align 8
@@ -65,3 +76,8 @@ void test() {
 // CHECK: store ptr @3, ptr %test4, align 8
 // CHECK: store ptr @.str, ptr %test5, align 8
 
+// CHECK: define linkonce_odr void @_Z13test_templateI13kernel_name_5Evv()
+// CHECK: %test6 = alloca ptr, align 8
+// CHECK: %test7 = alloca ptr, align 8
+// CHECK: store ptr @4, ptr %test6, align 8
+// CHECK: store ptr @4, ptr %test7, align 8

>From 21d3a50e5038c565640ad00e60d7777a6b6ffae7 Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andr...@intel.com>
Date: Fri, 14 Mar 2025 16:59:45 -0700
Subject: [PATCH 5/5] Process builtin-sycl-kernel-name called before kernel
 invocation

Prior support for builtins depends on KernelInfo being available
at the time of builtin call. This is not always the case. If a
builtin is called prior to kernel invocation, KernelInfo is not
populated and the builtin will be unable to retrieve the information
it requires. In this case,a global variable is declared to hold the
required information, which is populated later when kernel
invocation is processed.

This PR implements support for this case for
builtin-sycl-kernel-name.
---
 clang/lib/CodeGen/CGBuiltin.cpp               | 83 ++++++++++++++-----
 clang/lib/CodeGen/CodeGenModule.cpp           | 10 ++-
 clang/lib/CodeGen/CodeGenModule.h             | 11 +++
 clang/lib/CodeGen/CodeGenSYCL.cpp             | 59 +++++++++++--
 .../CodeGenSYCL/builtin-sycl-kernel-name.cpp  | 19 +++++
 .../SemaSYCL/builtin-sycl-kernel-name.cpp     | 15 ++++
 6 files changed, 167 insertions(+), 30 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index de3b4a42c433d..2fbe6ae23b837 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2527,17 +2527,61 @@ static RValue 
EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF,
   return RValue::get(CGF->Builder.CreateCall(UBF, Args));
 }
 
-static const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx,
-                                               const CallExpr *E) {
-  // Argument to the builtin is a type trait which is used to retrieve the
-  // kernel name type.
-  // FIXME: Improve the comment.
+static const CanQualType GetKernelNameType(ASTContext &Ctx, const CallExpr *E) 
{
+  // The first argument to the builtin is an object that designates
+  // the SYCL kernel. The argument is evaluated and its value is
+  // discarded; the SYCL kernel is identified based on the argument
+  // type. The argument type is required to be a class or structure
+  // with a member typedef or type alias named 'type'. The target
+  // type of the 'type' member is the SYCL kernel name type.
   RecordDecl *RD = E->getArg(0)->getType()->castAs<RecordType>()->getDecl();
   IdentifierTable &IdentTable = Ctx.Idents;
   auto Name = DeclarationName(&(IdentTable.get("type")));
   NamedDecl *ND = (RD->lookup(Name)).front();
   TypedefNameDecl *TD = cast<TypedefNameDecl>(ND);
-  CanQualType KernelNameType = Ctx.getCanonicalType(TD->getUnderlyingType());
+  return Ctx.getCanonicalType(TD->getUnderlyingType());
+}
+
+static llvm::GlobalVariable *
+EmitKernelNameGlobal(CodeGenModule &CGM, ASTContext &Ctx, const CallExpr *E) {
+  CanQualType KernelNameType = GetKernelNameType(Ctx, E);
+
+  // SmallString<256> KernelNameSymbol;
+  // llvm::raw_svector_ostream Out(KernelNameSymbol);
+  // The mangling used for the name of the global variable storing the offload
+  // kernel name is identical to the mangling of the offload kernel name.
+  // 
CGM.getCXXABI().getMangleContext().mangleSYCLKernelCallerName(KernelNameType,
+  //                                                               Out);
+  //
+
+  auto DeviceDiscriminatorOverrider =
+      [](ASTContext &Ctx, const NamedDecl *ND) -> UnsignedOrNone {
+    if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
+      if (RD->isLambda())
+        return RD->getDeviceLambdaManglingNumber();
+    return std::nullopt;
+  };
+  std::unique_ptr<MangleContext> MC{ItaniumMangleContext::create(
+      Ctx, Ctx.getDiagnostics(), DeviceDiscriminatorOverrider)};
+
+  SmallString<256> KernelNameSymbol;
+  llvm::raw_svector_ostream Out(KernelNameSymbol);
+  //llvm::raw_string_ostream Out(KernelNameSymbol);
+  MC->mangleCanonicalTypeName(KernelNameType, Out);
+
+  llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+      CGM.getModule(), CGM.GlobalsInt8PtrTy,
+      /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr,
+      KernelNameSymbol);
+
+  CGM.AddSYCLKernelNameSymbol(KernelNameType, GV);
+
+  return GV;
+}
+
+static const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx,
+                                               const CallExpr *E) {
+  CanQualType KernelNameType = GetKernelNameType(Ctx, E);
 
   // Retrieve KernelInfo using the kernel name.
   return Ctx.findSYCLKernelInfo(KernelNameType);
@@ -6237,21 +6281,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const 
GlobalDecl GD, unsigned BuiltinID,
     return RValue::get(Str.getPointer());
   }
   case Builtin::BI__builtin_sycl_kernel_name: {
-    ASTContext &Ctx = getContext();
-    // Argument to the builtin is a kernel_id_t type trait which is used
-    // to retrieve the kernel name type.
-    RecordDecl *RD = E->getArg(0)->getType()->castAs<RecordType>()->getDecl();
-    IdentifierTable &IdentTable = Ctx.Idents;
-    auto Name = DeclarationName(&(IdentTable.get("type")));
-    NamedDecl *ND = (RD->lookup(Name)).front();
-    TypeAliasDecl *TD = cast<TypeAliasDecl>(ND);
-    QualType KernelNameType = TD->getUnderlyingType().getCanonicalType();
-
-    // Retrieve the mangled name corresponding to kernel name type.
-    const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType);
-    assert(KernelInfo && "Type does not correspond to a SYCL kernel name.");
-    
-    // Emit the mangled name.
+    // Retrieve the kernel info corresponding to kernel name type.
+    const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E);
+
+    // This indicates that the builtin was called before the kernel was
+    // invoked. In this case, a global variable is declared, and returned
+    // as the result of the call to the builtin. This global variable is
+    // later initialized to hold the name of the offload kernel when kernel
+    // invocation is processed.
+    if (!KernelInfo)
+      return RValue::get(EmitKernelNameGlobal(CGM, getContext(), E));
+
+    // Emit the mangled name from KernelInfo if available.
     auto Str = CGM.GetAddrOfConstantCString(KernelInfo->GetKernelName(), "");
     return RValue::get(Str.getPointer());
   }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 50041f883cfe5..f21e09387922e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3319,16 +3319,20 @@ void CodeGenModule::EmitDeferred() {
     // a SYCL kernel caller offload entry point function is generated and
     // emitted in place of each of these functions.
     if (const auto *FD = D.getDecl()->getAsFunction()) {
-      if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelEntryPointAttr>() &&
-          FD->isDefined()) {
+      if (FD->hasAttr<SYCLKernelEntryPointAttr>() && FD->isDefined()) {
         // Functions with an invalid sycl_kernel_entry_point attribute are
         // ignored during device compilation.
-        if (!FD->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
+        if (LangOpts.SYCLIsDevice &&
+            !FD->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
           // Generate and emit the SYCL kernel caller function.
           EmitSYCLKernelCaller(FD, getContext());
           // Recurse to emit any symbols directly or indirectly referenced
           // by the SYCL kernel caller function.
           EmitDeferred();
+        } else {
+          // Initialize the global variables corresponding to SYCL Builtins
+          // used to obtain information about the offload kernel.
+          InitSYCLKernelInfoSymbolsForBuiltins(FD, getContext());
         }
         // Do not emit the sycl_kernel_entry_point attributed function.
         continue;
diff --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index 1db5c3bc4e4ef..3f5f11def5648 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -677,6 +677,7 @@ class CodeGenModule : public CodeGenTypeCache {
   computeVTPointerAuthentication(const CXXRecordDecl *ThisClass);
 
   AtomicOptions AtomicOpts;
+  llvm::DenseMap<CanQualType, llvm::GlobalVariable *> SYCLKernelNameSymbols;
 
 public:
   CodeGenModule(ASTContext &C, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
@@ -1505,6 +1506,10 @@ class CodeGenModule : public CodeGenTypeCache {
   /// annotations are emitted during finalization of the LLVM code.
   void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
 
+  void AddSYCLKernelNameSymbol(CanQualType, llvm::GlobalVariable *);
+
+  llvm::GlobalVariable *GetSYCLKernelNameSymbol(CanQualType);
+
   bool isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
                           SourceLocation Loc) const;
 
@@ -1975,6 +1980,12 @@ class CodeGenModule : public CodeGenTypeCache {
   void EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn,
                             ASTContext &Ctx);
 
+  /// Initialize the global variables corresponding to SYCL Builtins used to
+  /// obtain information about the offload kernel.
+  void
+  InitSYCLKernelInfoSymbolsForBuiltins(const FunctionDecl *KernelEntryPointFn,
+                                       ASTContext &Ctx);
+
   /// Determine whether the definition must be emitted; if this returns \c
   /// false, the definition can be emitted lazily if it's used.
   bool MustBeEmitted(const ValueDecl *D);
diff --git a/clang/lib/CodeGen/CodeGenSYCL.cpp 
b/clang/lib/CodeGen/CodeGenSYCL.cpp
index b9a96fe8ab838..9f5efd126ba08 100644
--- a/clang/lib/CodeGen/CodeGenSYCL.cpp
+++ b/clang/lib/CodeGen/CodeGenSYCL.cpp
@@ -25,6 +25,24 @@ static void SetSYCLKernelAttributes(llvm::Function *Fn, 
CodeGenFunction &CGF) {
     Fn->addFnAttr(llvm::Attribute::MustProgress);
 }
 
+static CanQualType GetKernelNameType(const FunctionDecl *KernelEntryPointFn,
+                                     ASTContext &Ctx) {
+  const auto *KernelEntryPointAttr =
+      KernelEntryPointFn->getAttr<SYCLKernelEntryPointAttr>();
+  assert(KernelEntryPointAttr && "Missing sycl_kernel_entry_point attribute");
+  CanQualType KernelNameType =
+      Ctx.getCanonicalType(KernelEntryPointAttr->getKernelName());
+  return KernelNameType;
+}
+
+static const SYCLKernelInfo *
+GetKernelInfo(const FunctionDecl *KernelEntryPointFn, ASTContext &Ctx) {
+  CanQualType KernelNameType = GetKernelNameType(KernelEntryPointFn, Ctx);
+  const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType);
+  assert(KernelInfo && "Type does not correspond to a kernel name");
+  return KernelInfo;
+}
+
 void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl 
*KernelEntryPointFn,
                                          ASTContext &Ctx) {
   assert(Ctx.getLangOpts().SYCLIsDevice &&
@@ -52,12 +70,10 @@ void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl 
*KernelEntryPointFn,
       getTypes().arrangeSYCLKernelCallerDeclaration(Ctx.VoidTy, Args);
   llvm::FunctionType *FnTy = getTypes().GetFunctionType(FnInfo);
 
-  // Retrieve the generated name for the SYCL kernel caller function.
-  CanQualType KernelNameType =
-      Ctx.getCanonicalType(KernelEntryPointAttr->getKernelName());
-  const SYCLKernelInfo &KernelInfo = Ctx.getSYCLKernelInfo(KernelNameType);
-  auto *Fn = llvm::Function::Create(FnTy, llvm::Function::ExternalLinkage,
-                                    KernelInfo.GetKernelName(), &getModule());
+  // Retrieve the generated name for the SYCL kernel caller function
+  const SYCLKernelInfo *KernelInfo = GetKernelInfo(KernelEntryPointFn, Ctx);
+  auto *Fn = llvm::Function::Create(FnTy, 
llvm::GlobalVariable::ExternalLinkage,
+                                    KernelInfo->GetKernelName(), &getModule());
 
   // Emit the SYCL kernel caller function.
   CodeGenFunction CGF(*this);
@@ -70,3 +86,34 @@ void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl 
*KernelEntryPointFn,
   SetLLVMFunctionAttributesForDefinition(cast<Decl>(OutlinedFnDecl), Fn);
   CGF.FinishFunction();
 }
+
+void CodeGenModule::AddSYCLKernelNameSymbol(CanQualType KernelNameType,
+                                            llvm::GlobalVariable *GV) {
+  SYCLKernelNameSymbols[KernelNameType] = GV;
+}
+
+llvm::GlobalVariable *
+CodeGenModule::GetSYCLKernelNameSymbol(CanQualType KernelNameType) {
+  auto it = SYCLKernelNameSymbols.find(KernelNameType);
+  if (it != SYCLKernelNameSymbols.end())
+    return it->second;
+  return nullptr;
+}
+
+void CodeGenModule::InitSYCLKernelInfoSymbolsForBuiltins(
+    const FunctionDecl *KernelEntryPointFn, ASTContext &Ctx) {
+  CanQualType KernelNameType = GetKernelNameType(KernelEntryPointFn, Ctx);
+  llvm::GlobalVariable *GV = GetSYCLKernelNameSymbol(KernelNameType);
+  if (GV && !GV->hasInitializer()) {
+    const SYCLKernelInfo *KernelInfo = GetKernelInfo(KernelEntryPointFn, Ctx);
+    ConstantAddress KernelNameStrConstantAddr =
+        GetAddrOfConstantCString(KernelInfo->GetKernelName(), "");
+    llvm::Constant *KernelNameStr = KernelNameStrConstantAddr.getPointer();
+    // FIXME: It is unclear to me whether the right API here is
+    // replaceInitializer or setInitializer. Unfortunately since the branch I 
am
+    // working on is outdated, my workspace does not have replaceInitializer
+    // Hopefully the person continuing to work on builtins can check this out.
+    GV->setInitializer(KernelNameStr);
+    GV->setLinkage(llvm::GlobalValue::PrivateLinkage);
+  }
+}
diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
index 1086465084ca1..d5d596aea2d3f 100644
--- a/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
+++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-name.cpp
@@ -10,6 +10,7 @@ class kernel_name_3;
 class kernel_name_4;
 class kernel_name_5;
 typedef kernel_name_4 kernel_name_TD2;
+class kernel_name_6;
 
 struct constexpr_kernel_name;
 
@@ -56,13 +57,27 @@ void test() {
   test_template<kernel_name_5>();
 }
 
+void testBuiltinBeforeKernelInvocation2();
+
+void testBuiltinBeforeKernelInvocation1() {
+  const char* testBefore1 = 
__builtin_sycl_kernel_name(kernel_id_t<kernel_name_6>());
+}
+
+void testBuiltinBeforeKernelInvocation2() {
+  SYCLKernel Obj;
+  kernel_single_task<kernel_name_6>(Obj);
+  testBuiltinBeforeKernelInvocation2();
+}
+
 // Kernel names retrieved from KernelInfo map
 // CHECK: @0 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_1Evv\00", align 1
 // CHECK: @1 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_2Evv\00", align 1
 // CHECK: @2 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_3Evv\00", align 1
 // CHECK: @3 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_4Evv\00", align 1
 // CHECK: @.str = private unnamed_addr constant [52 x i8] 
c"_Z20__sycl_kernel_callerI21constexpr_kernel_nameEvv\00", align 1
+// CHECK: @_Z20__sycl_kernel_callerI13kernel_name_6Evv = private constant ptr 
@[[INIT:[0-9]+]]
 // CHECK: @4 = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_5Evv\00", align 1
+// CHECK: @[[INIT]] = private unnamed_addr constant [44 x i8] 
c"_Z20__sycl_kernel_callerI13kernel_name_6Evv\00", align 1
 
 // CHECK: define dso_local void @_Z4testv()
 // CHECK: %test1 = alloca ptr, align 8
@@ -81,3 +96,7 @@ void test() {
 // CHECK: %test7 = alloca ptr, align 8
 // CHECK: store ptr @4, ptr %test6, align 8
 // CHECK: store ptr @4, ptr %test7, align 8
+
+// CHECK: define dso_local void @_Z34testBuiltinBeforeKernelInvocation1v()
+// CHECK: %testBefore1 = alloca ptr, align 8
+// CHECK: store ptr @_Z20__sycl_kernel_callerI13kernel_name_6Evv, ptr 
%testBefore1, align 8
diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp 
b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
index 18e4515a6ad58..1881e4bf0bb8f 100644
--- a/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
+++ b/clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp
@@ -4,6 +4,8 @@ class kernel_name_1;
 class kernel_name_2;
 class kernel_name_3;
 typedef kernel_name_3 kernel_name_TD;
+class kernel_name_4;
+struct constexpr_kernel_name;
 
 template<typename KN>
 struct kernel_id_1 {
@@ -29,6 +31,19 @@ struct SYCLKernel {
   void operator()() const {}
 };
 
+void testBuiltinBeforeKernelInvocation2();
+void testBuiltinBeforeKernelInvocation1() {
+  const char* testBefore1 = 
__builtin_sycl_kernel_name(kernel_id_1<kernel_name_4>()); // Valid
+  constexpr const char* testBefore2 = 
__builtin_sycl_kernel_name(kernel_id_1<constexpr_kernel_name>()); // 
expected-error {{constexpr variable 'testBefore2' must be initialized by a 
constant expression}}
+}
+
+void testBuiltinBeforeKernelInvocation2() {
+  SYCLKernel Obj;
+  kernel_single_task<kernel_name_4>(Obj);
+  kernel_single_task<constexpr_kernel_name>(Obj);
+  testBuiltinBeforeKernelInvocation2();
+}
+
 void test() {
   SYCLKernel Obj;
   kernel_single_task<kernel_name_1>(Obj);

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to