From bbbf20e91afc865cdf815e4e829f0b52e51a0157 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Tue, 6 Aug 2024 13:23:45 -0700 Subject: [PATCH 01/13] [SYCL] Do not emit SYCL kernel entry point function eagerly In SYCL device compilation, SYCL kernel entry point functions trigger the generation of SYCL kernel caller functions. This is done when handling deferred emissions. --- clang/lib/CodeGen/CodeGenModule.cpp | 3 + .../CodeGenSYCL/kernel-caller-generation.cpp | 81 ++++++++++++------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 9fac7301c0a97..17d637b01453e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3515,6 +3515,9 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // Defer until all versions have been semantically checked. if (FD->hasAttr() && !FD->isMultiVersion()) return false; + // Defer emission of SYCL kernel entry point functions. + if (LangOpts.SYCLIsDevice && FD->hasAttr()) + return false; } if (const auto *VD = dyn_cast(Global)) { if (Context.getInlineVariableDefinitionKind(VD) == diff --git a/clang/test/CodeGenSYCL/kernel-caller-generation.cpp b/clang/test/CodeGenSYCL/kernel-caller-generation.cpp index 2557c162c7734..6b67ec3d18184 100644 --- a/clang/test/CodeGenSYCL/kernel-caller-generation.cpp +++ b/clang/test/CodeGenSYCL/kernel-caller-generation.cpp @@ -1,4 +1,13 @@ -// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -triple spir64 %s -o - | FileCheck %s +// RUN: %clang_cc1 -fsycl-is-device -emit-llvm -triple spir64 %s -o - | FileCheck --check-prefix=CHECK-DEVICE %s +// RUN: %clang_cc1 -fsycl-is-host -emit-llvm -triple x86_64 %s -o - | FileCheck --check-prefix=CHECK-HOST %s + +// Test the generation of SYCL kernel caller function. The arguments of the SYCL kernel +// caller function correspond to either the SYCL Kernel Object, or decomposed fields of +// the SYCL kernel object if special SYCL types are captured (not yet supported). In the +// latter case, the SYCL kernel object is reconstited in the body of the SYCL caller +// function. The body of the SYCL kernel caller function then invokes the SYCL kernel +// i.e. the operator method of the SYCL kernel object. SYCL kernel caller should not be +// generated during host compilation. template __attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) { @@ -9,9 +18,10 @@ struct single_purpose_kernel_name; struct single_purpose_kernel { void operator()() const; }; + __attribute__((sycl_kernel_entry_point(single_purpose_kernel_name))) -void single_purpose_kernel_task(single_purpose_kernel k) { - k(); +void single_purpose_kernel_task(single_purpose_kernel kernelFunc) { + kernelFunc(); } int main() { @@ -20,40 +30,53 @@ int main() { [=]() { (void) capture; }); + single_purpose_kernel obj; + single_purpose_kernel_task(obj); } +// CHECK-HOST-NOT: __sycl_kernel_caller + +// IR for compiler generated SYCL kernel caller function corresponding to +// single_purpose_kernel_name: + +// CHECK-DEVICE: Function Attrs: convergent mustprogress noinline norecurse nounwind optnone +// FIXME: Pointer Alignment mismatch with syclos must be clarified and confirmed. +// CHECK-DEVICE: define dso_local spir_kernel void @_Z20__sycl_kernel_callerI26single_purpose_kernel_nameEvv +// CHECK-DEVICE-SAME: (ptr noundef byval(%struct.single_purpose_kernel) align 1 %kernelFunc) #[[ATTR0:[0-9]+]] { +// CHECK-DEVICE-NEXT: entry: +// CHECK-DEVICE-NEXT: %kernelFunc.ascast = addrspacecast ptr %kernelFunc to ptr addrspace(4) +// CHECK-DEVICE-NEXT: call spir_func void @_ZNK21single_purpose_kernelclEv +// CHECK-DEVICE-SAME: (ptr addrspace(4) noundef align 1 dereferenceable_or_null(1) %kernelFunc.ascast) #[[ATTR1:[0-9]+]] +// CHECK-DEVICE-NEXT: ret void +// CHECK-DEVICE-NEXT:} -// IR for compiler generated SYCL kernel caller function : -// The arguments of the SYCL kernel caller function correspond to either the SYCL Kernel -// Object, or decomposed fields of the SYCL kernel object if special SYCL types are -// captured (not yet supported). In the latter case, the SYCL kernel object is reconstited -// in the body of the SYCL caller function. The body of the SYCL kernel caller function -// then invokes the SYCL kernel i.e. the operator method of the SYCL kernel object. +// IR for compiler generated SYCL kernel caller function corresponding to +// test_kernel: -// CHECK: Function Attrs: convergent mustprogress noinline norecurse nounwind optnone +// CHECK-DEVICE: Function Attrs: convergent mustprogress noinline norecurse nounwind optnone // FIXME: Pointer Alignment mismatch with syclos must be clarified and confirmed. -// CHECK: define dso_local spir_kernel void @_Z20__sycl_kernel_callerIZ4mainE11test_kernelEvv(ptr noundef byval(%class.anon) align 4 %kernelFunc) #[[ATTR0:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: %kernelFunc.ascast = addrspacecast ptr %kernelFunc to ptr addrspace(4) -// CHECK-NEXT: call spir_func void @_ZZ4mainENKUlvE_clEv -// CHECK-SAME: (ptr addrspace(4) noundef align 4 dereferenceable_or_null(4) %kernelFunc.ascast) #[[ATTR1:[0-9]+]] -// CHECK-NEXT: ret void -// CHECK-NEXT:} +// CHECK-DEVICE: define dso_local spir_kernel void @_Z20__sycl_kernel_callerIZ4mainE11test_kernelEvv(ptr noundef byval(%class.anon) align 4 %kernelFunc) #[[ATTR0]] { +// CHECK-DEVICE-NEXT: entry: +// CHECK-DEVICE-NEXT: %kernelFunc.ascast = addrspacecast ptr %kernelFunc to ptr addrspace(4) +// CHECK-DEVICE-NEXT: call spir_func void @_ZZ4mainENKUlvE_clEv +// CHECK-DEVICE-SAME: (ptr addrspace(4) noundef align 4 dereferenceable_or_null(4) %kernelFunc.ascast) #[[ATTR1]] +// CHECK-DEVICE-NEXT: ret void +// CHECK-DEVICE-NEXT:} // IR for operator method of kernel object: -// CHECK: define internal spir_func void @_ZZ4mainENKUlvE_clEv +// CHECK-DEVICE: define internal spir_func void @_ZZ4mainENKUlvE_clEv // FIXME: Pointer Alignment mismatch with syclos must be clarified and confirmed. // FIXME: !srcloc metadata present in syclos (with incorrect value?). Why is this not present in llvm.org ? -// CHECK-SAME: (ptr addrspace(4) noundef align 4 dereferenceable_or_null(4) %this) #[[ATTR0]] align 2 { -// CHECK-NEXT: entry: -// CHECK-NEXT: %this.addr = alloca ptr addrspace(4), align 8 -// CHECK-NEXT: %this.addr.ascast = addrspacecast ptr %this.addr to ptr addrspace(4) -// CHECK-NEXT: store ptr addrspace(4) %this, ptr addrspace(4) %this.addr.ascast, align 8 -// CHECK-NEXT: %this1 = load ptr addrspace(4), ptr addrspace(4) %this.addr.ascast, align 8 -// CHECK-NEXT: %[[CAPTURE:.+]] = getelementptr inbounds %class.anon, ptr addrspace(4) %this1, i32 0, i32 0 -// CHECK-NEXT: ret void -// CHECK-NEXT:} +// CHECK-DEVICE-SAME: (ptr addrspace(4) noundef align 4 dereferenceable_or_null(4) %this) #[[ATTR0]] align 2 { +// CHECK-DEVICE-NEXT: entry: +// CHECK-DEVICE-NEXT: %this.addr = alloca ptr addrspace(4), align 8 +// CHECK-DEVICE-NEXT: %this.addr.ascast = addrspacecast ptr %this.addr to ptr addrspace(4) +// CHECK-DEVICE-NEXT: store ptr addrspace(4) %this, ptr addrspace(4) %this.addr.ascast, align 8 +// CHECK-DEVICE-NEXT: %this1 = load ptr addrspace(4), ptr addrspace(4) %this.addr.ascast, align 8 +// CHECK-DEVICE-NEXT: %[[CAPTURE:.+]] = getelementptr inbounds %class.anon, ptr addrspace(4) %this1, i32 0, i32 0 +// CHECK-DEVICE-NEXT: ret void +// CHECK-DEVICE-NEXT:} // FIXME:: Additional function attribute "sycl-optlevel"="0" generated in syclos vs llvm.org by a LLVM pass. -// CHECK: #[[ATTR0]] = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: #[[ATTR1]] = { convergent nounwind } +// CHECK-DEVICE: #[[ATTR0]] = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK-DEVICE: #[[ATTR1]] = { convergent nounwind } From 27f484079887c12f7ab0b3d78578d9c91512b6cc Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Thu, 8 Aug 2024 18:05:48 -0700 Subject: [PATCH 02/13] [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 f955d21169556..9f78465571a1f 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -43,6 +43,7 @@ enum LanguageID : uint16_t { OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue. ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages. HLSL_LANG = 0x1000, // builtin requires HLSL. + 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 7bef5fd7ad40f..ed64dc323cac1 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4598,6 +4598,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 HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_all"]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e19b169513411..d0bef21ae540c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12199,6 +12199,9 @@ def err_sycl_kernel_name_type : Error< def err_sycl_kernel_name_conflict : Error< "'sycl_kernel_entry_point' kernel name argument conflicts with a previous" " declaration">; +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 warn_cuda_maxclusterrank_sm_90 : Warning< "maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring " diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp index b116abbe034f7..d7a4723076601 100644 --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -116,6 +116,9 @@ static bool builtinIsSupported(const Builtin::Info &BuiltinInfo, /* 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 511e1fd4016d7..badda44bd108d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/ADT/APFloat.h" @@ -5992,6 +5993,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()->getDecl(); + IdentifierTable &IdentTable = Ctx.Idents; + auto Name = DeclarationName(&(IdentTable.get("type"))); + NamedDecl *ND = (RD->lookup(Name)).front(); + TypeAliasDecl *TD = cast(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 07cd0727eb3f4..ab35dae566a84 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2450,6 +2450,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(); + + 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(Lookup.front())) + return true; + + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -3252,6 +3271,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 +struct kernel_id_t { + using type = KN; +}; + +struct kernel_id_nt { + using type = kernel_name_3; +}; + +template +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + const char* test1 = __builtin_sycl_kernel_name(kernel_id_t()); + const char* test2 = __builtin_sycl_kernel_name(kernel_id_t()); + const char* test3 = __builtin_sycl_kernel_name(kernel_id_nt()); + const char* test4 = __builtin_sycl_kernel_name(kernel_id_t()); +} + +// 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 +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 +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + const char* test1 = __builtin_sycl_kernel_name(kernel_id_1()); // Valid + const char* test2 = __builtin_sycl_kernel_name(kernel_id_1()); // 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 250cbc9ce5a25af13127b3e712b0f98106b68e66 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Thu, 8 Aug 2024 17:37:22 -0700 Subject: [PATCH 03/13] [SYCL] Add support for builtin-sycl-kernel-param-count.cpp --- clang/include/clang/AST/SYCLKernelInfo.h | 18 +++--- clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/AST/ASTContext.cpp | 38 +++++++++++-- clang/lib/CodeGen/CGBuiltin.cpp | 36 ++++++++---- clang/lib/Sema/SemaChecking.cpp | 3 +- .../builtin-sycl-kernel-param-count.cpp | 55 +++++++++++++++++++ .../builtin-sycl-kernel-param-count.cpp | 44 +++++++++++++++ 7 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 clang/test/CodeGenSYCL/builtin-sycl-kernel-param-count.cpp create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index e54e3429be461..4e8276c97f5dc 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -21,15 +21,12 @@ namespace clang { class SYCLKernelInfo { public: - SYCLKernelInfo( - CanQualType KernelNameType, - const FunctionDecl *KernelEntryPointDecl, - const std::string &KernelName) - : - KernelNameType(KernelNameType), - KernelEntryPointDecl(KernelEntryPointDecl), - KernelName(KernelName) - {} + SYCLKernelInfo(CanQualType KernelNameType, + const FunctionDecl *KernelEntryPointDecl, + const std::string &KernelName, int ParamCount) + : KernelNameType(KernelNameType), + KernelEntryPointDecl(KernelEntryPointDecl), KernelName(KernelName), + ParamCount(ParamCount) {} CanQualType GetKernelNameType() const { return KernelNameType; @@ -43,10 +40,13 @@ class SYCLKernelInfo { return KernelName; } + const int &GetParamCount() const { return ParamCount; } + private: CanQualType KernelNameType; const FunctionDecl *KernelEntryPointDecl; std::string KernelName; + int ParamCount; }; } // namespace clang diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index ed64dc323cac1..fed0747006662 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4605,6 +4605,12 @@ def SYCLKernelName : LangBuiltin<"SYCL_LANG"> { let Prototype = "char const*(...)"; } +def SYCLKernelParamCount : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_count"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "int(...)"; +} + // HLSL def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_all"]; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index af7952c00d787..2666f3e8f807c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13781,9 +13781,8 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, } } -static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, - CanQualType KernelNameType, - const FunctionDecl *FD) { +static std::string GetSYCLKernelCallerName(ASTContext &Context, + CanQualType KernelNameType) { // FIXME: Host and device compilations must agree on a name for the generated // FIXME: SYCL kernel caller function. The name is provided to the SYCL // FIXME: library on the host via __builtin_sycl_kernel_name() and the SYCL @@ -13820,9 +13819,38 @@ static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, Buffer.reserve(128); llvm::raw_string_ostream Out(Buffer); MC->mangleSYCLKernelCallerName(KernelNameType, Out); - std::string KernelName = Out.str(); + return Out.str(); +} + +static int GetSYCLKernelCallerParamCount(const FunctionDecl *FD) { + // The parameters of the compiler generated SYCL kernel caller function + // are generated using the parameters of the SYCL kernel entry point + // function. The first parameter of the SYCL kernel entry point function + // (i.e. FD), is the SYCL kernel object. If the SYCL kernel object does + // not contain SYCL special types, it can be passed as-is to the device. + // In this case, parameters of the SYCL kernel caller function are the + // same as that of the the SYCL kernel entry point function. However, if + // the SYCL kernel object contains a SYCL special type, it is decomposed + // to it's data members and the parameters of the kernel caller function + // are generated using these decomposed fields, instead of the kernel + // object. + + // FIXME: SYCL special types are not currently supported and therefore we + // assume there is no decomposition and return the parameter count of SYCL + // kernel entry point function. + return FD->param_size(); +} + +static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, + CanQualType KernelNameType, + const FunctionDecl *FD) { + // Get the mangled name. + std::string KernelCallerName = + GetSYCLKernelCallerName(Context, KernelNameType); + // Get number of arguments. + int ParamCount = GetSYCLKernelCallerParamCount(FD); - return { KernelNameType, FD, KernelName }; + return {KernelNameType, FD, KernelCallerName, ParamCount}; } void ASTContext::registerSYCLEntryPointFunction(FunctionDecl *FD) { diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index badda44bd108d..0816b0d198812 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2539,6 +2539,20 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx, const CallExpr *E) { + // 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()->getDecl(); + IdentifierTable &IdentTable = Ctx.Idents; + auto Name = DeclarationName(&(IdentTable.get("type"))); + NamedDecl *ND = (RD->lookup(Name)).front(); + TypeAliasDecl *TD = cast(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) { @@ -5994,24 +6008,22 @@ 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()->getDecl(); - IdentifierTable &IdentTable = Ctx.Idents; - auto Name = DeclarationName(&(IdentTable.get("type"))); - NamedDecl *ND = (RD->lookup(Name)).front(); - TypeAliasDecl *TD = cast(ND); - QualType KernelNameType = TD->getUnderlyingType().getCanonicalType(); - - // Retrieve the mangled name corresponding to kernel name type. - const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType); + // Retrieve the kernel info corresponding to kernel name type. + const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); 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()); } + case Builtin::BI__builtin_sycl_kernel_param_count: { + // Retrieve the kernel info corresponding to kernel name type. + const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); + assert(KernelInfo && "Type does not correspond to a SYCL kernel name."); + // Emit total number of parameters of kernel caller function. + int test = KernelInfo->GetParamCount(); + return RValue::get(llvm::ConstantInt::get(Int32Ty, test)); + } } // 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 ab35dae566a84..4fca043ef90c8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3271,7 +3271,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } - case Builtin::BI__builtin_sycl_kernel_name: { + case Builtin::BI__builtin_sycl_kernel_name: + case Builtin::BI__builtin_sycl_kernel_param_count: { // Builtin takes 1 argument if (TheCall->getNumArgs() != 1) { Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count); diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-count.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-count.cpp new file mode 100644 index 0000000000000..8cc3f6a35ee71 --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-count.cpp @@ -0,0 +1,55 @@ +// 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; +class single_purpose_kernel_name; + +template +struct kernel_id_t { + using type = KN; +}; + +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) { + kernelFunc(); +} + +// Overloading kernel_single_task +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc, int a) { + kernelFunc(); +} + +struct SYCLKernel { + int m; + public: + void operator()() const {} +}; + +__attribute__((sycl_kernel_entry_point(single_purpose_kernel_name))) +void single_purpose_kernel_task(SYCLKernel kernelFunc, int a, int b) { + kernelFunc(); +} + + +void test() { + SYCLKernel Obj; + kernel_single_task(Obj); + kernel_single_task(Obj, 1); + single_purpose_kernel_task(Obj, 1, 2); + int test1 = __builtin_sycl_kernel_param_count(kernel_id_t()); // Returns 1 as corresponding entry point function has 1 argument + int test2 = __builtin_sycl_kernel_param_count(kernel_id_t()); // Returns 2 as corresponding entry point function has 2 arguments + int test3 = __builtin_sycl_kernel_param_count(kernel_id_t()); // Returns 3 as corresponding entry point function has 3 arguments +} + +// CHECK: define dso_local void @_Z4testv() +// CHECK: %test1 = alloca i32, align 4 +// CHECK: %test2 = alloca i32, align 4 +// CHECK: %test3 = alloca i32, align 4 +// CHECK: store i32 1, ptr %test1, align 4 +// CHECK: store i32 2, ptr %test2, align 4 +// CHECK: store i32 3, ptr %test3, align 4 + 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..4c92dcc4907ab --- /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 +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 +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + int test1 = __builtin_sycl_kernel_param_count(kernel_id_1()); // Valid + int test2 = __builtin_sycl_kernel_param_count(kernel_id_1()); // 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; argument must be a class or struct type with a member type alias named 'type'}} + int test5 = __builtin_sycl_kernel_param_count("str"); // expected-error {{invalid argument; argument must be a class or struct type with a member type alias named 'type'}} + int test6 = __builtin_sycl_kernel_param_count(kernel_id_2(), kernel_id_2()); // expected-error {{builtin requires exactly 1 argument}} +} + From e0504d523162bc8d2148977283a1c6d7cd380e82 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 9 Aug 2024 09:19:50 -0700 Subject: [PATCH 04/13] [SYCL] Add missing changes in Tom's fork --- clang/lib/AST/ASTContext.cpp | 9 ++++++++- clang/lib/CodeGen/CodeGenModule.cpp | 31 +++++++++++++++-------------- clang/lib/CodeGen/CodeGenSYCL.cpp | 12 ++++++----- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2666f3e8f807c..2ebbc73e5d23f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -11994,8 +11994,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // SYCL kernel entry point functions are used to generate and emit // the offload kernel. - if (LangOpts.SYCLIsDevice && FD->hasAttr()) + if (LangOpts.SYCLIsDevice) { + if (D->hasAttr()) return true; + // FIXME: Existing tests fail if we limit emission to the kernel caller + // function and functions called from it. Once the sycl_device attribute + // is implemented, modify this check (and tests) to include it and + // return false. + // return false; + } // Constructors and destructors are required. if (FD->hasAttr() || FD->hasAttr()) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 17d637b01453e..aaf1e57b8a870 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3168,6 +3168,22 @@ void CodeGenModule::EmitDeferred() { CurDeclsToEmit.swap(DeferredDeclsToEmit); for (GlobalDecl &D : CurDeclsToEmit) { + // If the Decl corresponds to a SYCL kernel entry point function, generate + // and emit the corresponding the SYCL kernel caller function i.e the + // offload kernel. + if (const auto *FD = D.getDecl()->getAsFunction()) { + if (LangOpts.SYCLIsDevice && FD->hasAttr() && + FD->isDefined()) { + // Generate and emit the offload kernel + EmitSYCLKernelCaller(FD, getContext()); + // The offload kernel invokes the operator method of the SYCL kernel + // object i.e. the SYCL kernel function is invoked. Emit this function. + EmitDeferred(); + // Do not emit the SYCL kernel entry point function. + continue; + } + } + // We should call GetAddrOfGlobal with IsForDefinition set to true in order // to get GlobalValue with exactly the type we need, not something that // might had been created for another decl with the same mangled name but @@ -3197,21 +3213,6 @@ void CodeGenModule::EmitDeferred() { if (LangOpts.OpenMP && OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(D)) continue; - // If the Decl corresponds to a SYCL kernel entry point function, generate - // and emit the corresponding SYCL kernel caller function, i.e the - // offload kernel. Otherwise, emit the definition and move on to the next - // one. - const FunctionDecl *FD = nullptr; - if (LangOpts.SYCLIsDevice && - (FD = D.getDecl()->getAsFunction()) != nullptr && - FD->hasAttr() && - FD->isDefined()) { - // Generate and emit the offload kernel - EmitSYCLKernelCaller(FD, getContext()); - } else { - EmitGlobalDefinition(D, GV); - } - // If we found out that we need to emit more decls, do that recursively. // This has the advantage that the decls are emitted in a DFS and related // ones are close together, which is convenient for testing. diff --git a/clang/lib/CodeGen/CodeGenSYCL.cpp b/clang/lib/CodeGen/CodeGenSYCL.cpp index 780c045fe15ad..e4a91c30af885 100644 --- a/clang/lib/CodeGen/CodeGenSYCL.cpp +++ b/clang/lib/CodeGen/CodeGenSYCL.cpp @@ -45,12 +45,14 @@ void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn, llvm::FunctionType *FnTy = getTypes().GetFunctionType(FnInfo); // Retrieve the generated name for the SYCL kernel caller function - const auto *SKEPAttr = KernelEntryPointFn->getAttr(); - assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute"); - CanQualType KernelNameType = Ctx.getCanonicalType(SKEPAttr->getKernelName()); - const SYCLKernelInfo &SKI = Ctx.SYCLKernels.at(KernelNameType); + const auto *KernelEntryPointAttr = + KernelEntryPointFn->getAttr(); + CanQualType KernelNameType = + Ctx.getCanonicalType(KernelEntryPointAttr->getKernelName()); + const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType); + assert(KernelInfo && "Type does not correspond to a kernel name"); auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalVariable::ExternalLinkage, - SKI.GetKernelName(), &getModule()); + KernelInfo->GetKernelName(), &getModule()); // Emit the SYCL kernel caller function CodeGenFunction CGF(*this); From e95f817e448a4e8be7d9f6debbaef345bcaa6519 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Tue, 13 Aug 2024 14:46:12 -0700 Subject: [PATCH 05/13] [SYCL] Fix incorrect merge with Tom's fork --- clang/lib/CodeGen/CodeGenModule.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index aaf1e57b8a870..598760adbef97 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3213,6 +3213,9 @@ void CodeGenModule::EmitDeferred() { if (LangOpts.OpenMP && OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(D)) continue; + // Otherwise, emit the definition and move on to the next one. + EmitGlobalDefinition(D, GV); + // If we found out that we need to emit more decls, do that recursively. // This has the advantage that the decls are emitted in a DFS and related // ones are close together, which is convenient for testing. From 31831f20443d2018041d2d963ed30d0611655a17 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Tue, 13 Aug 2024 19:08:03 -0700 Subject: [PATCH 06/13] [SYCL] Apply review comments - Builtins --- clang/include/clang/Basic/Builtins.td | 4 ++-- clang/include/clang/Basic/DiagnosticSemaKinds.td | 9 ++++++--- clang/lib/CodeGen/CGBuiltin.cpp | 10 ++++++---- clang/lib/Sema/SemaChecking.cpp | 9 ++++++--- clang/test/SemaSYCL/builtin-sycl-kernel-name.cpp | 6 +++--- .../test/SemaSYCL/builtin-sycl-kernel-param-count.cpp | 6 +++--- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index fed0747006662..13d0e61bbb3e9 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4601,13 +4601,13 @@ 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*(...)"; } def SYCLKernelParamCount : LangBuiltin<"SYCL_LANG"> { let Spellings = ["__builtin_sycl_kernel_param_count"]; - let Attributes = [NoThrow, CustomTypeChecking]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; let Prototype = "int(...)"; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d0bef21ae540c..4763affc0af25 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -744,6 +744,9 @@ def warn_unreachable_association : Warning< InGroup; /// 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; @@ -12199,9 +12202,9 @@ def err_sycl_kernel_name_type : Error< def err_sycl_kernel_name_conflict : Error< "'sycl_kernel_entry_point' kernel name argument conflicts with a previous" " declaration">; -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'">; def warn_cuda_maxclusterrank_sm_90 : Warning< "maxclusterrank requires sm_90 or higher, CUDA arch provided: %0, ignoring " diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 0816b0d198812..46dd827dd0431 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2539,14 +2539,16 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } -const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx, const CallExpr *E) { - // Argument to the builtin is a kernel_id_t type trait which is used - // to retrieve the kernel name type. +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()->getDecl(); IdentifierTable &IdentTable = Ctx.Idents; auto Name = DeclarationName(&(IdentTable.get("type"))); NamedDecl *ND = (RD->lookup(Name)).front(); - TypeAliasDecl *TD = cast(ND); + TypedefNameDecl *TD = cast(ND); CanQualType KernelNameType = Ctx.getCanonicalType(TD->getUnderlyingType()); // Retrieve KernelInfo using the kernel name. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4fca043ef90c8..fd1076e705b23 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2463,7 +2463,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(Lookup.front())) + if (Lookup.empty() || !Lookup.isSingleResult() || + !isa(Lookup.front())) return true; return false; @@ -3275,12 +3276,14 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin_sycl_kernel_param_count: { // 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()); // Valid const char* test2 = __builtin_sycl_kernel_name(kernel_id_1()); // 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 index 4c92dcc4907ab..831aed34e66e5 100644 --- a/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp +++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp @@ -37,8 +37,8 @@ void test() { int test1 = __builtin_sycl_kernel_param_count(kernel_id_1()); // Valid int test2 = __builtin_sycl_kernel_param_count(kernel_id_1()); // 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; argument must be a class or struct type with a member type alias named 'type'}} - int test5 = __builtin_sycl_kernel_param_count("str"); // expected-error {{invalid argument; argument must be a class or struct type with a member type alias named 'type'}} - int test6 = __builtin_sycl_kernel_param_count(kernel_id_2(), kernel_id_2()); // expected-error {{builtin requires exactly 1 argument}} + 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 3d08e3b289fb844035d05d9fc2684d47d81bc8fc Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Tue, 13 Aug 2024 19:08:58 -0700 Subject: [PATCH 07/13] [SYCL] Apply review comments - kernel generation --- clang/lib/CodeGen/CodeGenModule.cpp | 4 +++- clang/lib/CodeGen/CodeGenSYCL.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 598760adbef97..736f7b47d1290 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3170,7 +3170,9 @@ void CodeGenModule::EmitDeferred() { for (GlobalDecl &D : CurDeclsToEmit) { // If the Decl corresponds to a SYCL kernel entry point function, generate // and emit the corresponding the SYCL kernel caller function i.e the - // offload kernel. + // offload kernel. The generation of the offload kernel needs to happen + // first in this loop, in order to avoid generating IR for the SYCL kernel + // entry point function. if (const auto *FD = D.getDecl()->getAsFunction()) { if (LangOpts.SYCLIsDevice && FD->hasAttr() && FD->isDefined()) { diff --git a/clang/lib/CodeGen/CodeGenSYCL.cpp b/clang/lib/CodeGen/CodeGenSYCL.cpp index e4a91c30af885..a1d92f1f4de75 100644 --- a/clang/lib/CodeGen/CodeGenSYCL.cpp +++ b/clang/lib/CodeGen/CodeGenSYCL.cpp @@ -47,6 +47,7 @@ void CodeGenModule::EmitSYCLKernelCaller(const FunctionDecl *KernelEntryPointFn, // Retrieve the generated name for the SYCL kernel caller function const auto *KernelEntryPointAttr = KernelEntryPointFn->getAttr(); + assert(KernelEntryPointAttr && "Missing sycl_kernel_entry_point attribute"); CanQualType KernelNameType = Ctx.getCanonicalType(KernelEntryPointAttr->getKernelName()); const SYCLKernelInfo *KernelInfo = Ctx.findSYCLKernelInfo(KernelNameType); From e9b255ed287616f747e074dff5213ca1a8dc089f Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Wed, 14 Aug 2024 17:14:01 -0700 Subject: [PATCH 08/13] [SYCL] Implement builtins Implemented support for __builtin_sycl_kernel_param_kind, __builtin_sycl_kernel_param_size and __builtin_sycl_kernel_param_offset Changes cause ast-dump-sycl-kernel-call-stmt.cpp to fail. The failure occurs when we try to obtain the size of a parameter with an instantiated type. The failure is because the definition of the type is not instantiated when attempting to obtain it's size. It is unclear why this is happening. Maybe KernelInfo is being collected too early? Further debugging is required. --- clang/include/clang/AST/SYCLKernelInfo.h | 24 ++++++++ clang/include/clang/Basic/Builtins.td | 18 ++++++ clang/lib/AST/ASTContext.cpp | 24 +++++++- clang/lib/CodeGen/CGBuiltin.cpp | 36 +++++++++++- clang/lib/Sema/SemaChecking.cpp | 27 +++++++++ .../builtin-sycl-kernel-param-kind.cpp | 55 ++++++++++++++++++ .../builtin-sycl-kernel-param-offset.cpp | 55 ++++++++++++++++++ .../builtin-sycl-kernel-param-size.cpp | 56 +++++++++++++++++++ .../builtin-sycl-kernel-param-kind.cpp | 44 +++++++++++++++ .../builtin-sycl-kernel-param-offset.cpp | 44 +++++++++++++++ .../builtin-sycl-kernel-param-size.cpp | 44 +++++++++++++++ 11 files changed, 424 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp create mode 100644 clang/test/CodeGenSYCL/builtin-sycl-kernel-param-offset.cpp create mode 100644 clang/test/CodeGenSYCL/builtin-sycl-kernel-param-size.cpp create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-param-kind.cpp create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-param-offset.cpp create mode 100644 clang/test/SemaSYCL/builtin-sycl-kernel-param-size.cpp diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index 4e8276c97f5dc..30f17177a8854 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -20,6 +20,9 @@ namespace clang { class SYCLKernelInfo { +public: + enum kernel_param_kind_t { kind_std_layout, kind_other }; + public: SYCLKernelInfo(CanQualType KernelNameType, const FunctionDecl *KernelEntryPointDecl, @@ -42,11 +45,32 @@ class SYCLKernelInfo { const int &GetParamCount() const { return ParamCount; } + void addParamDesc(kernel_param_kind_t Kind, int Size) { + KernelParamDesc PD; + PD.Kind = Kind; + PD.Size = Size; + Params.push_back(PD); + } + + const kernel_param_kind_t &GetParamKind(int i) const { + return Params[i].Kind; + } + + const int &GetParamSize(int i) const { return Params[i].Size; } + private: + // Kernel caller function parameter descriptor. + struct KernelParamDesc { + kernel_param_kind_t Kind = kind_other; + int Size = 0; + KernelParamDesc() = default; + }; + CanQualType KernelNameType; const FunctionDecl *KernelEntryPointDecl; std::string KernelName; int ParamCount; + SmallVector Params; }; } // namespace clang diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 13d0e61bbb3e9..fd12ea9ce0374 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4611,6 +4611,24 @@ def SYCLKernelParamCount : LangBuiltin<"SYCL_LANG"> { let Prototype = "int(...)"; } +def SYCLKernelParamKind : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_kind"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} + +def SYCLKernelParamSize : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_size"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} + +def SYCLKernelParamOffset : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_offset"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} + // HLSL def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_all"]; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2ebbc73e5d23f..2302a8f3bfb2b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13848,6 +13848,24 @@ static int GetSYCLKernelCallerParamCount(const FunctionDecl *FD) { return FD->param_size(); } +static void CreateSYCLKernelParamDesc(ASTContext &Ctx, const FunctionDecl *FD, + SYCLKernelInfo &KernelInfo) { + llvm::ArrayRef KernelParameters = FD->parameters(); + + if (KernelParameters.size() == 0) + return; + + // First parameter always corresponds to SYCL Kernel Object. + KernelInfo.addParamDesc( + SYCLKernelInfo::kind_std_layout, + Ctx.getTypeSizeInChars(KernelParameters[0]->getType()).getQuantity()); + for (size_t I = 1; I < KernelParameters.size(); I++) { + KernelInfo.addParamDesc( + SYCLKernelInfo::kind_other, + Ctx.getTypeSizeInChars(KernelParameters[I]->getType()).getQuantity()); + } +} + static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, CanQualType KernelNameType, const FunctionDecl *FD) { @@ -13857,7 +13875,11 @@ static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, // Get number of arguments. int ParamCount = GetSYCLKernelCallerParamCount(FD); - return {KernelNameType, FD, KernelCallerName, ParamCount}; + SYCLKernelInfo KernelInfo{KernelNameType, FD, KernelCallerName, ParamCount}; + + CreateSYCLKernelParamDesc(Context, FD, KernelInfo); + + return KernelInfo; } void ASTContext::registerSYCLEntryPointFunction(FunctionDecl *FD) { diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 46dd827dd0431..2b8b1fb17aeb7 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6019,12 +6019,44 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Str.getPointer()); } case Builtin::BI__builtin_sycl_kernel_param_count: { + // Retrieve the kernel info corresponding to kernel name type. + const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); + assert(KernelInfo && "Type does not correspond to a SYCL kernel name."); + return RValue::get( + llvm::ConstantInt::get(Int32Ty, KernelInfo->GetParamCount())); + } + case Builtin::BI__builtin_sycl_kernel_param_kind: { + // Retrieve the kernel info corresponding to kernel name type. + const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); + assert(KernelInfo && "Type does not correspond to a SYCL kernel name."); + // Emit total number of parameters of kernel caller function. + const Expr *ParamNoExpr = E->getArg(1); + Expr::EvalResult Result; + ParamNoExpr->EvaluateAsInt(Result, getContext()); + unsigned ParamNo = Result.Val.getInt().getZExtValue(); + return RValue::get( + llvm::ConstantInt::get(Int32Ty, KernelInfo->GetParamKind(ParamNo))); + } + case Builtin::BI__builtin_sycl_kernel_param_size: { // Retrieve the kernel info corresponding to kernel name type. const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); assert(KernelInfo && "Type does not correspond to a SYCL kernel name."); // Emit total number of parameters of kernel caller function. - int test = KernelInfo->GetParamCount(); - return RValue::get(llvm::ConstantInt::get(Int32Ty, test)); + const Expr *ParamNoExpr = E->getArg(1); + Expr::EvalResult Result; + ParamNoExpr->EvaluateAsInt(Result, getContext()); + unsigned ParamNo = Result.Val.getInt().getZExtValue(); + return RValue::get( + llvm::ConstantInt::get(Int32Ty, KernelInfo->GetParamSize(ParamNo))); + } + case Builtin::BI__builtin_sycl_kernel_param_offset: { + // Retrieve the kernel info corresponding to kernel name type. + const SYCLKernelInfo *KernelInfo = GetSYCLKernelInfo(getContext(), E); + assert(KernelInfo && "Type does not correspond to a SYCL kernel name."); + // FIXME: Offset is used only when kernel object is decomposed to identify + // offset of field in kernel object. What should the offset be for + // additional non-kernel object parameters? + return RValue::get(llvm::ConstantInt::get(Int32Ty, 0)); } } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fd1076e705b23..e3582c8319615 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3289,6 +3289,33 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, break; } + case Builtin::BI__builtin_sycl_kernel_param_kind: + case Builtin::BI__builtin_sycl_kernel_param_offset: + case Builtin::BI__builtin_sycl_kernel_param_size: { + // Builtin takes 1 argument + if (TheCall->getNumArgs() != 2) { + Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count) + << 2; + return ExprError(); + } + + if (CheckBuiltinSyclKernelName(*this, TheCall)) { + Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_sycl_kernel_name_invalid_arg); + return ExprError(); + } + + const Expr *Arg = TheCall->getArg(1); + QualType ArgTy = Arg->getType(); + + if (!ArgTy->isIntegerType()) { + Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << 2 << /* integer ty */ 8 << ArgTy; + return ExprError(); + } + + break; + } case Builtin::BI__builtin_popcountg: if (BuiltinPopcountg(*this, TheCall)) return ExprError(); diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp new file mode 100644 index 0000000000000..c0082c3df211a --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp @@ -0,0 +1,55 @@ +// 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; +class single_purpose_kernel_name; + +template +struct kernel_id_t { + using type = KN; +}; + +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) { + kernelFunc(); +} + +// Overloading kernel_single_task +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc, int a) { + kernelFunc(); +} + +struct SYCLKernel { + int m; + public: + void operator()() const {} +}; + +__attribute__((sycl_kernel_entry_point(single_purpose_kernel_name))) +void single_purpose_kernel_task(SYCLKernel kernelFunc, int a, int b) { + kernelFunc(); +} + + +void test() { + SYCLKernel Obj; + kernel_single_task(Obj); + kernel_single_task(Obj, 1); + single_purpose_kernel_task(Obj, 1, 2); + int test1 = __builtin_sycl_kernel_param_kind(kernel_id_t(), 0); + int test2 = __builtin_sycl_kernel_param_kind(kernel_id_t(), 1); + int test3 = __builtin_sycl_kernel_param_kind(kernel_id_t(),2); +} + +// CHECK: define dso_local void @_Z4testv() +// CHECK: %test1 = alloca i32, align 4 +// CHECK: %test2 = alloca i32, align 4 +// CHECK: %test3 = alloca i32, align 4 +// CHECK: store i32 0, ptr %test1, align 4 +// CHECK: store i32 1, ptr %test2, align 4 +// CHECK: store i32 1, ptr %test3, align 4 + diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-offset.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-offset.cpp new file mode 100644 index 0000000000000..2ee5ce91a0892 --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-offset.cpp @@ -0,0 +1,55 @@ +// 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; +class single_purpose_kernel_name; + +template +struct kernel_id_t { + using type = KN; +}; + +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) { + kernelFunc(); +} + +// Overloading kernel_single_task +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc, int a) { + kernelFunc(); +} + +struct SYCLKernel { + int m; + public: + void operator()() const {} +}; + +__attribute__((sycl_kernel_entry_point(single_purpose_kernel_name))) +void single_purpose_kernel_task(SYCLKernel kernelFunc, int a, int b) { + kernelFunc(); +} + + +void test() { + SYCLKernel Obj; + kernel_single_task(Obj); + kernel_single_task(Obj, 1); + single_purpose_kernel_task(Obj, 1, 2); + int test1 = __builtin_sycl_kernel_param_offset(kernel_id_t(), 0); + int test2 = __builtin_sycl_kernel_param_offset(kernel_id_t(), 1); + int test3 = __builtin_sycl_kernel_param_offset(kernel_id_t(),2); +} + +// CHECK: define dso_local void @_Z4testv() +// CHECK: %test1 = alloca i32, align 4 +// CHECK: %test2 = alloca i32, align 4 +// CHECK: %test3 = alloca i32, align 4 +// CHECK: store i32 0, ptr %test1, align 4 +// CHECK: store i32 0, ptr %test2, align 4 +// CHECK: store i32 0, ptr %test3, align 4 + diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-size.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-size.cpp new file mode 100644 index 0000000000000..591c6cb0f28cf --- /dev/null +++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-size.cpp @@ -0,0 +1,56 @@ +// 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; +class single_purpose_kernel_name; + +template +struct kernel_id_t { + using type = KN; +}; + +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc) { + kernelFunc(); +} + +// Overloading kernel_single_task +template +__attribute__((sycl_kernel_entry_point(name))) void kernel_single_task(const Func kernelFunc, int a) { + kernelFunc(); +} + +struct SYCLKernel { + int m; + float n; + public: + void operator()() const {} +}; + +__attribute__((sycl_kernel_entry_point(single_purpose_kernel_name))) +void single_purpose_kernel_task(SYCLKernel kernelFunc, int a, long b) { + kernelFunc(); +} + + +void test() { + SYCLKernel Obj; + kernel_single_task(Obj); + kernel_single_task(Obj, 1); + single_purpose_kernel_task(Obj, 1, 2); + int test1 = __builtin_sycl_kernel_param_size(kernel_id_t(), 0); + int test2 = __builtin_sycl_kernel_param_size(kernel_id_t(), 1); + int test3 = __builtin_sycl_kernel_param_size(kernel_id_t(),2); +} + +// CHECK: define dso_local void @_Z4testv() +// CHECK: %test1 = alloca i32, align 4 +// CHECK: %test2 = alloca i32, align 4 +// CHECK: %test3 = alloca i32, align 4 +// CHECK: store i32 8, ptr %test1, align 4 +// CHECK: store i32 4, ptr %test2, align 4 +// CHECK: store i32 8, ptr %test3, align 4 + diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-param-kind.cpp b/clang/test/SemaSYCL/builtin-sycl-kernel-param-kind.cpp new file mode 100644 index 0000000000000..7b81dbbf2fe1d --- /dev/null +++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-kind.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 +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 +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + int test1 = __builtin_sycl_kernel_param_kind(kernel_id_1(), 0); // Valid + int test2 = __builtin_sycl_kernel_param_kind(kernel_id_1(), 0); // Valid + int test3 = __builtin_sycl_kernel_param_kind(kernel_id_2(), 0); // Valid + int test4 = __builtin_sycl_kernel_param_kind(kernel_id_3(), 0); // 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_kind(kernel_id_2(), "str"); // expected-error {{2nd argument must be an 'int' (was 'const char[4]')}} + int test6 = __builtin_sycl_kernel_param_kind(kernel_id_2()); // expected-error {{builtin requires exactly 2 arguments}} +} + diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-param-offset.cpp b/clang/test/SemaSYCL/builtin-sycl-kernel-param-offset.cpp new file mode 100644 index 0000000000000..6de8e3ebd9775 --- /dev/null +++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-offset.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 +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 +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + int test1 = __builtin_sycl_kernel_param_offset(kernel_id_1(), 0); // Valid + int test2 = __builtin_sycl_kernel_param_offset(kernel_id_1(), 0); // Valid + int test3 = __builtin_sycl_kernel_param_offset(kernel_id_2(), 0); // Valid + int test4 = __builtin_sycl_kernel_param_offset(kernel_id_3(), 0); // 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_offset(kernel_id_2(), "str"); // expected-error {{2nd argument must be an 'int' (was 'const char[4]')}} + int test6 = __builtin_sycl_kernel_param_offset(kernel_id_2()); // expected-error {{builtin requires exactly 2 arguments}} +} + diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-param-size.cpp b/clang/test/SemaSYCL/builtin-sycl-kernel-param-size.cpp new file mode 100644 index 0000000000000..d84f2333e7223 --- /dev/null +++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-size.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 +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 +__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(Obj); + kernel_single_task(Obj); + kernel_single_task(Obj); + int test1 = __builtin_sycl_kernel_param_size(kernel_id_1(), 0); // Valid + int test2 = __builtin_sycl_kernel_param_size(kernel_id_1(), 0); // Valid + int test3 = __builtin_sycl_kernel_param_size(kernel_id_2(), 0); // Valid + int test4 = __builtin_sycl_kernel_param_size(kernel_id_3(), 0); // 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_size(kernel_id_2(), "str"); // expected-error {{2nd argument must be an 'int' (was 'const char[4]')}} + int test6 = __builtin_sycl_kernel_param_size(kernel_id_2()); // expected-error {{builtin requires exactly 2 arguments}} +} + From 914bf9ad23e1b65c6a4ff24c64c6ffbc01f59362 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 16 Aug 2024 09:59:28 -0700 Subject: [PATCH 09/13] [SYCL] Dummy implementation of __builtin_sycl_kernel_param_access_target This is a dummy implementation so that the library will compile. Actual implementation will be done after SYCL special types are supported. --- clang/include/clang/Basic/Builtins.td | 6 ++++++ clang/lib/CodeGen/CGBuiltin.cpp | 5 +++++ clang/lib/Sema/SemaChecking.cpp | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index fd12ea9ce0374..942ecdb4691fe 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4629,6 +4629,12 @@ def SYCLKernelParamOffset : LangBuiltin<"SYCL_LANG"> { let Prototype = "int(...)"; } +def SYCLKernelParamAccessTarget : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_access_target"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} + // HLSL def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_all"]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 2b8b1fb17aeb7..8727a0c43b224 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6058,6 +6058,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // additional non-kernel object parameters? return RValue::get(llvm::ConstantInt::get(Int32Ty, 0)); } + case Builtin::BI__builtin_sycl_kernel_param_access_target: { + // FIXME: This is a dummy value. This builtin will be implemented when + // support for special sycl types is implemented. + return RValue::get(llvm::ConstantInt::get(Int32Ty, 0)); + } } // 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 e3582c8319615..58d09bd6c06dc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3291,7 +3291,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_sycl_kernel_param_kind: case Builtin::BI__builtin_sycl_kernel_param_offset: - case Builtin::BI__builtin_sycl_kernel_param_size: { + case Builtin::BI__builtin_sycl_kernel_param_size: + case Builtin::BI__builtin_sycl_kernel_param_access_target: { // Builtin takes 1 argument if (TheCall->getNumArgs() != 2) { Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count) From 60d2caafa05f312eec73b59b00db9de0cf4f72e7 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 16 Aug 2024 10:42:45 -0700 Subject: [PATCH 10/13] [SYCL] Handling of kernel entry point parameters should be generic The old design required the SYCL kernel object to be the first parameter of the kernel entry point function. In the new design, all parameters of the kernel entry point function are treated in a similar manner. We do not have a designated spot for the kernel object. --- clang/include/clang/AST/SYCLKernelInfo.h | 15 +++++++++++++-- clang/lib/AST/ASTContext.cpp | 14 ++++---------- .../builtin-sycl-kernel-param-kind.cpp | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index 30f17177a8854..76bd7a28ff6b2 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -21,7 +21,18 @@ namespace clang { class SYCLKernelInfo { public: - enum kernel_param_kind_t { kind_std_layout, kind_other }; + // FIXME: Added full enum to match the library implementation. + // Why does kind_first and kind_last exist? + enum kernel_param_kind_t { + kind_first, + kind_accessor = kind_first, + kind_std_layout, + kind_sampler, + kind_pointer, + kind_specialization_constants_buffer, + kind_stream, + kind_last = kind_stream + }; public: SYCLKernelInfo(CanQualType KernelNameType, @@ -61,7 +72,7 @@ class SYCLKernelInfo { private: // Kernel caller function parameter descriptor. struct KernelParamDesc { - kernel_param_kind_t Kind = kind_other; + kernel_param_kind_t Kind = kind_last; int Size = 0; KernelParamDesc() = default; }; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2302a8f3bfb2b..36571ebb109b1 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13850,19 +13850,13 @@ static int GetSYCLKernelCallerParamCount(const FunctionDecl *FD) { static void CreateSYCLKernelParamDesc(ASTContext &Ctx, const FunctionDecl *FD, SYCLKernelInfo &KernelInfo) { - llvm::ArrayRef KernelParameters = FD->parameters(); - - if (KernelParameters.size() == 0) + if (FD->getNumParams() == 0) return; - // First parameter always corresponds to SYCL Kernel Object. - KernelInfo.addParamDesc( - SYCLKernelInfo::kind_std_layout, - Ctx.getTypeSizeInChars(KernelParameters[0]->getType()).getQuantity()); - for (size_t I = 1; I < KernelParameters.size(); I++) { + for (const ParmVarDecl *KernelParam : FD->parameters()) { KernelInfo.addParamDesc( - SYCLKernelInfo::kind_other, - Ctx.getTypeSizeInChars(KernelParameters[I]->getType()).getQuantity()); + SYCLKernelInfo::kind_std_layout, + Ctx.getTypeSizeInChars(KernelParam->getType()).getQuantity()); } } diff --git a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp index c0082c3df211a..bfc3ab3646bd5 100644 --- a/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp +++ b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp @@ -49,7 +49,7 @@ void test() { // CHECK: %test1 = alloca i32, align 4 // CHECK: %test2 = alloca i32, align 4 // CHECK: %test3 = alloca i32, align 4 -// CHECK: store i32 0, ptr %test1, align 4 +// CHECK: store i32 1, ptr %test1, align 4 // CHECK: store i32 1, ptr %test2, align 4 // CHECK: store i32 1, ptr %test3, align 4 From 0f4b443f00ee77f5af567e6f71612730f87edbad Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 16 Aug 2024 13:51:19 -0700 Subject: [PATCH 11/13] [SYCL] Simplify implementation of __builtin_sycl_kernel_param_count --- clang/include/clang/AST/SYCLKernelInfo.h | 8 +++----- clang/lib/AST/ASTContext.cpp | 23 +---------------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index 76bd7a28ff6b2..53380db431b1a 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -37,10 +37,9 @@ class SYCLKernelInfo { public: SYCLKernelInfo(CanQualType KernelNameType, const FunctionDecl *KernelEntryPointDecl, - const std::string &KernelName, int ParamCount) + const std::string &KernelName) : KernelNameType(KernelNameType), - KernelEntryPointDecl(KernelEntryPointDecl), KernelName(KernelName), - ParamCount(ParamCount) {} + KernelEntryPointDecl(KernelEntryPointDecl), KernelName(KernelName) {} CanQualType GetKernelNameType() const { return KernelNameType; @@ -54,7 +53,7 @@ class SYCLKernelInfo { return KernelName; } - const int &GetParamCount() const { return ParamCount; } + size_t GetParamCount() const { return Params.size(); } void addParamDesc(kernel_param_kind_t Kind, int Size) { KernelParamDesc PD; @@ -80,7 +79,6 @@ class SYCLKernelInfo { CanQualType KernelNameType; const FunctionDecl *KernelEntryPointDecl; std::string KernelName; - int ParamCount; SmallVector Params; }; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 36571ebb109b1..3a5584cf1e0c0 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13829,25 +13829,6 @@ static std::string GetSYCLKernelCallerName(ASTContext &Context, return Out.str(); } -static int GetSYCLKernelCallerParamCount(const FunctionDecl *FD) { - // The parameters of the compiler generated SYCL kernel caller function - // are generated using the parameters of the SYCL kernel entry point - // function. The first parameter of the SYCL kernel entry point function - // (i.e. FD), is the SYCL kernel object. If the SYCL kernel object does - // not contain SYCL special types, it can be passed as-is to the device. - // In this case, parameters of the SYCL kernel caller function are the - // same as that of the the SYCL kernel entry point function. However, if - // the SYCL kernel object contains a SYCL special type, it is decomposed - // to it's data members and the parameters of the kernel caller function - // are generated using these decomposed fields, instead of the kernel - // object. - - // FIXME: SYCL special types are not currently supported and therefore we - // assume there is no decomposition and return the parameter count of SYCL - // kernel entry point function. - return FD->param_size(); -} - static void CreateSYCLKernelParamDesc(ASTContext &Ctx, const FunctionDecl *FD, SYCLKernelInfo &KernelInfo) { if (FD->getNumParams() == 0) @@ -13866,10 +13847,8 @@ static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, // Get the mangled name. std::string KernelCallerName = GetSYCLKernelCallerName(Context, KernelNameType); - // Get number of arguments. - int ParamCount = GetSYCLKernelCallerParamCount(FD); - SYCLKernelInfo KernelInfo{KernelNameType, FD, KernelCallerName, ParamCount}; + SYCLKernelInfo KernelInfo{KernelNameType, FD, KernelCallerName}; CreateSYCLKernelParamDesc(Context, FD, KernelInfo); From 9b283678043d91a47f3ae2fc92b1fb77be6ada7d Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 16 Aug 2024 15:35:13 -0700 Subject: [PATCH 12/13] [SYCL] Fix crashing test Getting the size of parameter requires it to be a complete type. When the parameter sizes were previously stored in SYCLKernelInfo, the compiler hit an assert in cases where the definition of the type was not yet instantiated by the compiler. This PR moves the code calculating size to the point of invocation of the builtin (instead of kernel invocation), hoping the type is fully instantiated by the compiler by then. This needs to be verified by adding new builtin tests. The existing crashing test now passes because it doesn't invoke the builtin. --- clang/include/clang/AST/SYCLKernelInfo.h | 8 ++++---- clang/lib/AST/ASTContext.cpp | 5 ++--- clang/lib/CodeGen/CGBuiltin.cpp | 6 ++++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index 53380db431b1a..3c80817566854 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -55,10 +55,10 @@ class SYCLKernelInfo { size_t GetParamCount() const { return Params.size(); } - void addParamDesc(kernel_param_kind_t Kind, int Size) { + void addParamDesc(kernel_param_kind_t Kind, QualType Ty) { KernelParamDesc PD; PD.Kind = Kind; - PD.Size = Size; + PD.Type = Ty; Params.push_back(PD); } @@ -66,13 +66,13 @@ class SYCLKernelInfo { return Params[i].Kind; } - const int &GetParamSize(int i) const { return Params[i].Size; } + const QualType &GetParamTy(int i) const { return Params[i].Type; } private: // Kernel caller function parameter descriptor. struct KernelParamDesc { kernel_param_kind_t Kind = kind_last; - int Size = 0; + QualType Type; KernelParamDesc() = default; }; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 3a5584cf1e0c0..159890f181068 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13835,9 +13835,8 @@ static void CreateSYCLKernelParamDesc(ASTContext &Ctx, const FunctionDecl *FD, return; for (const ParmVarDecl *KernelParam : FD->parameters()) { - KernelInfo.addParamDesc( - SYCLKernelInfo::kind_std_layout, - Ctx.getTypeSizeInChars(KernelParam->getType()).getQuantity()); + KernelInfo.addParamDesc(SYCLKernelInfo::kind_std_layout, + KernelParam->getType()); } } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8727a0c43b224..7bbd4d468ebc3 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6046,8 +6046,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Expr::EvalResult Result; ParamNoExpr->EvaluateAsInt(Result, getContext()); unsigned ParamNo = Result.Val.getInt().getZExtValue(); - return RValue::get( - llvm::ConstantInt::get(Int32Ty, KernelInfo->GetParamSize(ParamNo))); + QualType ParamTy = KernelInfo->GetParamTy(ParamNo); + // FIXME: Add check to ensure complete type. + return RValue::get(llvm::ConstantInt::get( + Int32Ty, getContext().getTypeSizeInChars(ParamTy).getQuantity())); } case Builtin::BI__builtin_sycl_kernel_param_offset: { // Retrieve the kernel info corresponding to kernel name type. From 582049af639ea55ccf414c79f3d09514980a7753 Mon Sep 17 00:00:00 2001 From: Elizabeth Andrews Date: Fri, 16 Aug 2024 17:00:56 -0700 Subject: [PATCH 13/13] [SYCL] Dummy implementation of code location builtins The following builtins were implemented to point to the location of the SYCL kernel object. In the new design, the SYCL kernel object does not having 'special' designation since all members of the entry point function will be treated in a similar manner. It is unclear what these builtins should now return or whether they should even exist. This PR is a dummy implementation to make library compile while we investigate. __builtin_sycl_kernel_file_name(kernel-name) __builtin_sycl_kernel_function_name(kernel-name) __builtin_sycl_kernel_line_number(kernel-name) __builtin_sycl_kernel_column_number(kernel-name) --- clang/include/clang/Basic/Builtins.td | 24 ++++++++++++++++++++++++ clang/lib/CodeGen/CGBuiltin.cpp | 19 +++++++++++++++++++ clang/lib/Sema/SemaChecking.cpp | 6 +++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 942ecdb4691fe..d804a3b32a05b 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4635,6 +4635,30 @@ def SYCLKernelParamAccessTarget : LangBuiltin<"SYCL_LANG"> { let Prototype = "int(...)"; } +def SYCLKernelFileName : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_file_name"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "char const*(...)"; +} + +def SYCLKernelFunctionName : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_function_name"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "char const*(...)"; +} + +def SYCLKernelLineNumber : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_line_number"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "unsigned int(...)"; +} + +def SYCLKernelColumnNumber : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_column_number"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "unsigned int(...)"; +} + // HLSL def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_all"]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7bbd4d468ebc3..9d14638934897 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6065,6 +6065,25 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // support for special sycl types is implemented. return RValue::get(llvm::ConstantInt::get(Int32Ty, 0)); } + case Builtin::BI__builtin_sycl_kernel_file_name: + case Builtin::BI__builtin_sycl_kernel_function_name: { + // FIXME: This is a dummy value. These builtins provide information + // about the kernel object. In the new design, the we do not have + // special status for the kernel object, so it is unclear what these + // builtins should return, or if they even need to exist. Support will + // be added or removed after investigation. + auto Str = CGM.GetAddrOfConstantCString("DummyString", ""); + return RValue::get(Str.getPointer()); + } + case Builtin::BI__builtin_sycl_kernel_line_number: + case Builtin::BI__builtin_sycl_kernel_column_number: { + // FIXME: This is a dummy value. These builtins provide information + // about the kernel object. In the new design, the we do not have + // special status for the kernel object, so it is unclear what these + // builtins should return, or if they even need to exist. Support will + // be added or removed after investigation. + return RValue::get(llvm::ConstantInt::get(Int32Ty, 0)); + } } // 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 58d09bd6c06dc..c42cf9cb0abe6 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3273,7 +3273,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, break; } case Builtin::BI__builtin_sycl_kernel_name: - case Builtin::BI__builtin_sycl_kernel_param_count: { + case Builtin::BI__builtin_sycl_kernel_param_count: + case Builtin::BI__builtin_sycl_kernel_file_name: + case Builtin::BI__builtin_sycl_kernel_function_name: + case Builtin::BI__builtin_sycl_kernel_line_number: + case Builtin::BI__builtin_sycl_kernel_column_number: { // Builtin takes 1 argument if (TheCall->getNumArgs() != 1) { Diag(TheCall->getBeginLoc(), diag::err_builtin_invalid_argument_count)