diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h index e54e3429be461..3c80817566854 100644 --- a/clang/include/clang/AST/SYCLKernelInfo.h +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -21,15 +21,25 @@ namespace clang { class SYCLKernelInfo { public: - SYCLKernelInfo( - CanQualType KernelNameType, - const FunctionDecl *KernelEntryPointDecl, - const std::string &KernelName) - : - KernelNameType(KernelNameType), - KernelEntryPointDecl(KernelEntryPointDecl), - KernelName(KernelName) - {} + // 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, + const FunctionDecl *KernelEntryPointDecl, + const std::string &KernelName) + : KernelNameType(KernelNameType), + KernelEntryPointDecl(KernelEntryPointDecl), KernelName(KernelName) {} CanQualType GetKernelNameType() const { return KernelNameType; @@ -43,10 +53,33 @@ class SYCLKernelInfo { return KernelName; } + size_t GetParamCount() const { return Params.size(); } + + void addParamDesc(kernel_param_kind_t Kind, QualType Ty) { + KernelParamDesc PD; + PD.Kind = Kind; + PD.Type = Ty; + Params.push_back(PD); + } + + const kernel_param_kind_t &GetParamKind(int i) const { + return Params[i].Kind; + } + + 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; + QualType Type; + KernelParamDesc() = default; + }; + CanQualType KernelNameType; const FunctionDecl *KernelEntryPointDecl; std::string KernelName; + SmallVector Params; }; } // namespace clang 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..d804a3b32a05b 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4598,6 +4598,67 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> { let Prototype = "char const*(...)"; } +// SYCL +def SYCLKernelName : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_name"]; + 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, Const, Constexpr, CustomTypeChecking]; + 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(...)"; +} + +def SYCLKernelParamAccessTarget : LangBuiltin<"SYCL_LANG"> { + let Spellings = ["__builtin_sycl_kernel_param_access_target"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + 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/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e19b169513411..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,6 +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_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/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index af7952c00d787..159890f181068 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()) @@ -13781,9 +13788,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 +13826,32 @@ 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 void CreateSYCLKernelParamDesc(ASTContext &Ctx, const FunctionDecl *FD, + SYCLKernelInfo &KernelInfo) { + if (FD->getNumParams() == 0) + return; + + for (const ParmVarDecl *KernelParam : FD->parameters()) { + KernelInfo.addParamDesc(SYCLKernelInfo::kind_std_layout, + KernelParam->getType()); + } +} + +static SYCLKernelInfo BuildSYCLKernelInfo(ASTContext &Context, + CanQualType KernelNameType, + const FunctionDecl *FD) { + // Get the mangled name. + std::string KernelCallerName = + GetSYCLKernelCallerName(Context, KernelNameType); + + SYCLKernelInfo KernelInfo{KernelNameType, FD, KernelCallerName}; + + CreateSYCLKernelParamDesc(Context, FD, KernelInfo); - return { KernelNameType, FD, KernelName }; + return KernelInfo; } void ASTContext::registerSYCLEntryPointFunction(FunctionDecl *FD) { 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..9d14638934897 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" @@ -2538,6 +2539,22 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF, return RValue::get(CGF->Builder.CreateCall(UBF, Args)); } +static const SYCLKernelInfo *GetSYCLKernelInfo(ASTContext &Ctx, + const CallExpr *E) { + // Argument to the builtin is a type trait which is used to retrieve the + // kernel name type. + // FIXME: Improve the comment. + RecordDecl *RD = E->getArg(0)->getType()->castAs()->getDecl(); + IdentifierTable &IdentTable = Ctx.Idents; + auto Name = DeclarationName(&(IdentTable.get("type"))); + NamedDecl *ND = (RD->lookup(Name)).front(); + TypedefNameDecl *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) { @@ -5992,6 +6009,81 @@ 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: { + // 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."); + 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. + const Expr *ParamNoExpr = E->getArg(1); + Expr::EvalResult Result; + ParamNoExpr->EvaluateAsInt(Result, getContext()); + unsigned ParamNo = Result.Val.getInt().getZExtValue(); + 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. + 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)); + } + 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)); + } + 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/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 9fac7301c0a97..736f7b47d1290 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3168,6 +3168,24 @@ 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. 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()) { + // 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,20 +3215,8 @@ 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); - } + // 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 @@ -3515,6 +3521,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/lib/CodeGen/CodeGenSYCL.cpp b/clang/lib/CodeGen/CodeGenSYCL.cpp index 780c045fe15ad..a1d92f1f4de75 100644 --- a/clang/lib/CodeGen/CodeGenSYCL.cpp +++ b/clang/lib/CodeGen/CodeGenSYCL.cpp @@ -45,12 +45,15 @@ 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(); + assert(KernelEntryPointAttr && "Missing sycl_kernel_entry_point attribute"); + 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); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 07cd0727eb3f4..c42cf9cb0abe6 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2450,6 +2450,26 @@ 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 +3272,55 @@ 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_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) + << 1; + return ExprError(); + } + + if (CheckBuiltinSyclKernelName(*this, TheCall)) { + Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_sycl_kernel_name_invalid_arg); + return ExprError(); + } + + 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: + 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) + << 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-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/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/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp b/clang/test/CodeGenSYCL/builtin-sycl-kernel-param-kind.cpp new file mode 100644 index 0000000000000..bfc3ab3646bd5 --- /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 1, 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/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 } 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..18e4515a6ad58 --- /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; expected a class or structure with a member typedef or type alias alias named 'type'}} + const char* test5 = __builtin_sycl_kernel_name("str"); // expected-error {{invalid argument; expected a class or structure with a member typedef or type alias alias named 'type'}} + const char* test6 = __builtin_sycl_kernel_name(kernel_id_2(), kernel_id_2()); // expected-error {{builtin takes one argument}} +} + diff --git a/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp b/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp new file mode 100644 index 0000000000000..831aed34e66e5 --- /dev/null +++ b/clang/test/SemaSYCL/builtin-sycl-kernel-param-count.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s + +class kernel_name_1; +class kernel_name_2; +class kernel_name_3; +typedef kernel_name_3 kernel_name_TD; + +template +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; 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}} +} + 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}} +} +