Skip to content

Commit eeea84b

Browse files
elizabethandrewsFznamznon
authored andcommitted
[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.
1 parent 93f19cb commit eeea84b

File tree

8 files changed

+171
-0
lines changed

8 files changed

+171
-0
lines changed

clang/include/clang/Basic/Builtins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum LanguageID : uint16_t {
4545
ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages.
4646
HLSL_LANG = 0x1000, // builtin requires HLSL.
4747
C23_LANG = 0x2000, // builtin requires C23 or later.
48+
SYCL_LANG = 0x2000, // builtin requires SYCL.
4849
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
4950
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
5051
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.

clang/include/clang/Basic/Builtins.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,6 +4794,13 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
47944794
let Prototype = "char const*(...)";
47954795
}
47964796

4797+
// SYCL
4798+
def SYCLKernelName : LangBuiltin<"SYCL_LANG"> {
4799+
let Spellings = ["__builtin_sycl_kernel_name"];
4800+
let Attributes = [NoThrow, CustomTypeChecking];
4801+
let Prototype = "char const*(...)";
4802+
}
4803+
47974804
// HLSL
47984805
def HLSLAddUint64: LangBuiltin<"HLSL_LANG"> {
47994806
let Spellings = ["__builtin_hlsl_adduint64"];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12789,6 +12789,9 @@ def err_sycl_entry_point_deduced_return_type : Error<
1278912789
def warn_cuda_maxclusterrank_sm_90 : Warning<
1279012790
"maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring "
1279112791
"%1 attribute">, InGroup<IgnoredAttributes>;
12792+
def err_builtin_invalid_argument_count : Error<"builtin requires exactly 1 argument">;
12793+
def err_builtin_invalid_argument : Error<"invalid argument; argument must be a class or struct type"
12794+
" with a member type alias named 'type'">;
1279212795

1279312796
// VTable pointer authentication errors
1279412797
def err_non_polymorphic_vtable_pointer_auth : Error<

clang/lib/Basic/Builtins.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ static bool builtinIsSupported(const llvm::StringTable &Strings,
185185
/* CUDA Unsupported */
186186
if (!LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG)
187187
return false;
188+
/* SYCL Unsupported */
189+
if (!LangOpts.isSYCL() && BuiltinInfo.Langs == SYCL_LANG)
190+
return false;
188191
/* CPlusPlus Unsupported */
189192
if (!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG)
190193
return false;

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "clang/Basic/TargetBuiltins.h"
3030
#include "clang/Basic/TargetInfo.h"
3131
#include "clang/Basic/TargetOptions.h"
32+
#include "clang/Basic/IdentifierTable.h"
3233
#include "clang/Frontend/FrontendDiagnostic.h"
3334
#include "llvm/IR/InlineAsm.h"
3435
#include "llvm/IR/Intrinsics.h"
@@ -6219,6 +6220,25 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
62196220
auto Str = CGM.GetAddrOfConstantCString(Name, "");
62206221
return RValue::get(Str.getPointer());
62216222
}
6223+
case Builtin::BI__builtin_sycl_kernel_name: {
6224+
ASTContext &Ctx = getContext();
6225+
// Argument to the builtin is a kernel_id_t type trait which is used
6226+
// to retrieve the kernel name type.
6227+
RecordDecl *RD = E->getArg(0)->getType()->castAs<RecordType>()->getDecl();
6228+
IdentifierTable &IdentTable = Ctx.Idents;
6229+
auto Name = DeclarationName(&(IdentTable.get("type")));
6230+
NamedDecl *ND = (RD->lookup(Name)).front();
6231+
TypeAliasDecl *TD = cast<TypeAliasDecl>(ND);
6232+
QualType KernelNameType = TD->getUnderlyingType().getCanonicalType();
6233+
6234+
// Retrieve the mangled name corresponding to kernel name type.
6235+
const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType);
6236+
assert(KernelInfo && "Type does not correspond to a SYCL kernel name.");
6237+
6238+
// Emit the mangled name.
6239+
auto Str = CGM.GetAddrOfConstantCString(KernelInfo->GetKernelName(), "");
6240+
return RValue::get(Str.getPointer());
6241+
}
62226242
}
62236243

62246244
// If this is an alias for a lib function (e.g. __builtin_sin), emit

clang/lib/Sema/SemaChecking.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,6 +2219,25 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
22192219
return false;
22202220
}
22212221

2222+
// The argument must be a class or struct with a member
2223+
// named type.
2224+
static bool CheckBuiltinSyclKernelName(Sema &S, CallExpr *TheCall) {
2225+
QualType ArgTy = TheCall->getArg(0)->getType();
2226+
const auto *RT = ArgTy->getAs<RecordType>();
2227+
2228+
if(!RT)
2229+
return true;
2230+
2231+
RecordDecl *RD = RT->getDecl();
2232+
IdentifierTable &IdentTable = S.Context.Idents;
2233+
auto Name = DeclarationName(&(IdentTable.get("type")));
2234+
DeclContext::lookup_result Lookup = RD->lookup(Name);
2235+
if (Lookup.empty() || !Lookup.isSingleResult() || !isa<TypeAliasDecl>(Lookup.front()))
2236+
return true;
2237+
2238+
return false;
2239+
}
2240+
22222241
ExprResult
22232242
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
22242243
CallExpr *TheCall) {
@@ -3030,6 +3049,20 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
30303049
}
30313050
break;
30323051
}
3052+
case Builtin::BI__builtin_sycl_kernel_name: {
3053+
// Builtin takes 1 argument
3054+
if (TheCall->getNumArgs() != 1) {
3055+
Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count);
3056+
return ExprError();
3057+
}
3058+
3059+
if (CheckBuiltinSyclKernelName(*this, TheCall)) {
3060+
Diag(TheCall->getArg(0)->getBeginLoc(), diag::err_builtin_invalid_argument);
3061+
return ExprError();
3062+
}
3063+
3064+
break;
3065+
}
30333066
case Builtin::BI__builtin_popcountg:
30343067
if (BuiltinPopcountg(*this, TheCall))
30353068
return ExprError();
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64 %s -o - | FileCheck %s
2+
3+
// Test IR generated by __builtin_sycl_kernel_name(). This builtin accepts a SYCL
4+
// kernel name type and returns it's mangled name.
5+
6+
class kernel_name_1;
7+
class kernel_name_2;
8+
typedef kernel_name_2 kernel_name_TD;
9+
class kernel_name_3;
10+
class kernel_name_4;
11+
typedef kernel_name_4 kernel_name_TD2;
12+
13+
template<typename KN>
14+
struct kernel_id_t {
15+
using type = KN;
16+
};
17+
18+
struct kernel_id_nt {
19+
using type = kernel_name_3;
20+
};
21+
22+
template <typename name, typename Func>
23+
__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) {
24+
kernelFunc();
25+
}
26+
27+
struct SYCLKernel {
28+
int m;
29+
public:
30+
void operator()() const {}
31+
};
32+
33+
void test() {
34+
SYCLKernel Obj;
35+
kernel_single_task<kernel_name_1>(Obj);
36+
kernel_single_task<kernel_name_TD>(Obj);
37+
kernel_single_task<kernel_name_3>(Obj);
38+
kernel_single_task<kernel_name_TD2>(Obj);
39+
const char* test1 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_1>());
40+
const char* test2 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_TD>());
41+
const char* test3 = __builtin_sycl_kernel_name(kernel_id_nt());
42+
const char* test4 = __builtin_sycl_kernel_name(kernel_id_t<kernel_name_4>());
43+
}
44+
45+
// Kernel names retrieved from KernelInfo map
46+
// CHECK: @0 = private unnamed_addr constant [44 x i8] c"_Z20__sycl_kernel_callerI13kernel_name_1Evv\00", align 1
47+
// CHECK: @1 = private unnamed_addr constant [44 x i8] c"_Z20__sycl_kernel_callerI13kernel_name_2Evv\00", align 1
48+
// CHECK: @2 = private unnamed_addr constant [44 x i8] c"_Z20__sycl_kernel_callerI13kernel_name_3Evv\00", align 1
49+
// CHECK: @3 = private unnamed_addr constant [44 x i8] c"_Z20__sycl_kernel_callerI13kernel_name_4Evv\00", align 1
50+
51+
// CHECK: define dso_local void @_Z4testv()
52+
// CHECK: %test1 = alloca ptr, align 8
53+
// CHECK: %test2 = alloca ptr, align 8
54+
// CHECK: %test3 = alloca ptr, align 8
55+
// CHECK: %test4 = alloca ptr, align 8
56+
// CHECK: store ptr @0, ptr %test1, align 8
57+
// CHECK: store ptr @1, ptr %test2, align 8
58+
// CHECK: store ptr @2, ptr %test3, align 8
59+
// CHECK: store ptr @3, ptr %test4, align 8
60+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s
2+
3+
class kernel_name_1;
4+
class kernel_name_2;
5+
class kernel_name_3;
6+
typedef kernel_name_3 kernel_name_TD;
7+
8+
template<typename KN>
9+
struct kernel_id_1 {
10+
using type = KN;
11+
};
12+
13+
struct kernel_id_2 {
14+
using type = kernel_name_2;
15+
};
16+
17+
struct kernel_id_3 {
18+
using invalid_name = kernel_name_2;
19+
};
20+
21+
template <typename name, typename Func>
22+
__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) {
23+
kernelFunc();
24+
}
25+
26+
struct SYCLKernel {
27+
int m;
28+
public:
29+
void operator()() const {}
30+
};
31+
32+
void test() {
33+
SYCLKernel Obj;
34+
kernel_single_task<kernel_name_1>(Obj);
35+
kernel_single_task<kernel_name_2>(Obj);
36+
kernel_single_task<kernel_name_TD>(Obj);
37+
const char* test1 = __builtin_sycl_kernel_name(kernel_id_1<kernel_name_1>()); // Valid
38+
const char* test2 = __builtin_sycl_kernel_name(kernel_id_1<kernel_name_TD>()); // Valid
39+
const char* test3 = __builtin_sycl_kernel_name(kernel_id_2()); // Valid
40+
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'}}
41+
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'}}
42+
const char* test6 = __builtin_sycl_kernel_name(kernel_id_2(), kernel_id_2()); // expected-error {{builtin requires exactly 1 argument}}
43+
}
44+

0 commit comments

Comments
 (0)