From c3cdacbbffca2c274a5a4076d615d51232bff8ba Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 6 Nov 2024 09:09:04 -0800 Subject: [PATCH 1/9] [SYCL][clang] Emit default template arguments in integration header For free function kernels support clang forward declares the kernel itself as well as its parameter types. In case a free function kernel has a parameter that is templated and has a default template argument, all template arguments including arguments that match default arguments must be printed in kernel's forward declarations, for example ``` template struct Arg { T val; }; // For the kernel SYCL_EXT_ONEAPI_FUNCTION_PROPERTY( (ext::oneapi::experimental::nd_range_kernel<1>)) void foo(Arg arg) { arg.val = 42; } // Integration header must contain void foo(Arg arg); ``` Unfortunately, even though integration header emission already has extensive support for forward declarations priting, some modifications to clang's type printing are still required. infrastructure, since neither of existing PrintingPolicy flags help to reach the correct result. Using `SuppressDefaultTemplateArgs = true` doesn't help without printing canonical types, printing canonical types for the case like ``` template SYCL_EXT_ONEAPI_FUNCTION_PROPERTY( (ext::oneapi::experimental::nd_range_kernel<1>)) void foo(Arg arg) { arg.val = 42; } // Printing canonical types is causing the following integration header template void foo(Arg arg); ``` Using `SkipCanonicalizationOfTemplateTypeParms` field of printing policy doesn't help here since at the one point where it is checked we take canonical type of `Arg`, not its parameters and it will contain template argument types in canonical type after that. --- clang/include/clang/AST/PrettyPrinter.h | 13 +++++++-- clang/lib/AST/TypePrinter.cpp | 38 +++++++++++++++++++------ clang/lib/Sema/SemaSYCL.cpp | 6 +++- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 8f7d00db7ad99..ef4af4dab4277 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -66,9 +66,10 @@ struct PrintingPolicy { SuppressLifetimeQualifiers(false), SuppressTypedefs(false), SuppressFinalSpecifier(false), SuppressTemplateArgsInCXXConstructors(false), - SuppressDefaultTemplateArgs(true), Bool(LO.Bool), - Nullptr(LO.CPlusPlus11 || LO.C23), NullptrTypeInNamespace(LO.CPlusPlus), - Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), + SuppressDefaultTemplateArgs(true), EnforceDefaultTemplateArgs(false), + Bool(LO.Bool), Nullptr(LO.CPlusPlus11 || LO.C23), + NullptrTypeInNamespace(LO.CPlusPlus), Restrict(LO.C99), + Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), UseVoidForZeroParams(!LO.CPlusPlus), SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), @@ -237,6 +238,12 @@ struct PrintingPolicy { LLVM_PREFERRED_TYPE(bool) unsigned SuppressDefaultTemplateArgs : 1; + + /// When true, print template arguments that match the default argument for + /// the parameter, even if they're not specified in the source. + LLVM_PREFERRED_TYPE(bool) + unsigned EnforceDefaultTemplateArgs : 1; + /// Whether we can use 'bool' rather than '_Bool' (even if the language /// doesn't actually have 'bool', because, e.g., it is defined as a macro). LLVM_PREFERRED_TYPE(bool) diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index cdee23798189c..940aaf06056a3 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2397,15 +2397,35 @@ template static void printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) { - // Drop trailing template arguments that match default arguments. - if (TPL && Policy.SuppressDefaultTemplateArgs && - !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack && + llvm::SmallVector OrigArgs; + for (const TA &A : Args) + OrigArgs.push_back(getArgument(A)); + if (TPL && !Policy.PrintCanonicalTypes && !IsPack && Args.size() <= TPL->size()) { - llvm::SmallVector OrigArgs; - for (const TA &A : Args) - OrigArgs.push_back(getArgument(A)); - while (!Args.empty() && getArgument(Args.back()).getIsDefaulted()) - Args = Args.drop_back(); + // Drop trailing template arguments that match default arguments. + if (Policy.SuppressDefaultTemplateArgs) { + while (!OrigArgs.empty() && getArgument(OrigArgs.back()).getIsDefaulted()) + OrigArgs.pop_back(); + } else if (Policy.EnforceDefaultTemplateArgs) { + for (unsigned I = Args.size(); I < TPL->size(); ++I) { + auto Param = TPL->getParam(I); + if (auto *TTPD = dyn_cast(Param)) { + if (!TTPD->hasDefaultArgument()) + break; + OrigArgs.push_back(getArgument(TTPD->getDefaultArgument())); + } else if (auto *TTPD = dyn_cast(Param)) { + if (!TTPD->hasDefaultArgument()) + break; + OrigArgs.push_back(getArgument(TTPD->getDefaultArgument())); + } else if (auto *NTTPD = dyn_cast(Param)) { + if (!NTTPD->hasDefaultArgument()) + break; + OrigArgs.push_back(getArgument(NTTPD->getDefaultArgument())); + } else { + llvm_unreachable("unexpected template parameter"); + } + } + } } const char *Comma = Policy.MSVCFormatting ? "," : ", "; @@ -2414,7 +2434,7 @@ printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, bool NeedSpace = false; bool FirstArg = true; - for (const auto &Arg : Args) { + for (const auto &Arg : OrigArgs) { // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 996443bcbc8fd..e2930dd2bbc9c 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -6464,6 +6464,7 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { O << "\n"; O << "// Forward declarations of kernel and its argument types:\n"; + Policy.SuppressDefaultTemplateArgs = false; FwdDeclEmitter.Visit(K.SyclKernel->getType()); O << "\n"; @@ -6476,11 +6477,12 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { FirstParam = false; else ParmList += ", "; - ParmList += Param->getType().getCanonicalType().getAsString(); + ParmList += Param->getType().getCanonicalType().getAsString(Policy); } FunctionTemplateDecl *FTD = K.SyclKernel->getPrimaryTemplate(); Policy.SuppressDefinition = true; Policy.PolishForDeclaration = true; + Policy.EnforceDefaultTemplateArgs = true; if (FTD) { FTD->print(O, Policy); } else { @@ -6509,6 +6511,8 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { } O << ";\n"; O << "}\n"; + Policy.SuppressDefaultTemplateArgs = true; + Policy.EnforceDefaultTemplateArgs = false; // Generate is_kernel, is_single_task_kernel and nd_range_kernel functions. O << "namespace sycl {\n"; From da51a197e6a7f6c98ca5c36604a6bac7b914bbdf Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Wed, 6 Nov 2024 09:41:25 -0800 Subject: [PATCH 2/9] Groom TypePrinter.cpp --- clang/lib/AST/TypePrinter.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 940aaf06056a3..366c065accf40 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2218,15 +2218,6 @@ static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP, A.print(PP, OS, IncludeType); } -static void printArgument(const TemplateArgumentLoc &A, - const PrintingPolicy &PP, llvm::raw_ostream &OS, - bool IncludeType) { - const TemplateArgument::ArgKind &Kind = A.getArgument().getKind(); - if (Kind == TemplateArgument::ArgKind::Type) - return A.getTypeSourceInfo()->getType().print(OS, PP); - return A.getArgument().print(PP, OS, IncludeType); -} - static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg, TemplateArgument Pattern, ArrayRef Args, @@ -2397,30 +2388,35 @@ template static void printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) { - llvm::SmallVector OrigArgs; + llvm::SmallVector ArgsToPrint; for (const TA &A : Args) - OrigArgs.push_back(getArgument(A)); + ArgsToPrint.push_back(getArgument(A)); if (TPL && !Policy.PrintCanonicalTypes && !IsPack && Args.size() <= TPL->size()) { // Drop trailing template arguments that match default arguments. if (Policy.SuppressDefaultTemplateArgs) { - while (!OrigArgs.empty() && getArgument(OrigArgs.back()).getIsDefaulted()) - OrigArgs.pop_back(); + while (!ArgsToPrint.empty() && + getArgument(ArgsToPrint.back()).getIsDefaulted()) + ArgsToPrint.pop_back(); } else if (Policy.EnforceDefaultTemplateArgs) { for (unsigned I = Args.size(); I < TPL->size(); ++I) { auto Param = TPL->getParam(I); if (auto *TTPD = dyn_cast(Param)) { + // If we met a non default-argument past provided list of arguments, + // it is either a pack which must be the last arguments, or provided + // argument list was problematic. Bail out either way. Do the same + // for each kind of template argument. if (!TTPD->hasDefaultArgument()) break; - OrigArgs.push_back(getArgument(TTPD->getDefaultArgument())); + ArgsToPrint.push_back(getArgument(TTPD->getDefaultArgument())); } else if (auto *TTPD = dyn_cast(Param)) { if (!TTPD->hasDefaultArgument()) break; - OrigArgs.push_back(getArgument(TTPD->getDefaultArgument())); + ArgsToPrint.push_back(getArgument(TTPD->getDefaultArgument())); } else if (auto *NTTPD = dyn_cast(Param)) { if (!NTTPD->hasDefaultArgument()) break; - OrigArgs.push_back(getArgument(NTTPD->getDefaultArgument())); + ArgsToPrint.push_back(getArgument(NTTPD->getDefaultArgument())); } else { llvm_unreachable("unexpected template parameter"); } @@ -2434,7 +2430,7 @@ printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, bool NeedSpace = false; bool FirstArg = true; - for (const auto &Arg : OrigArgs) { + for (const auto &Arg : ArgsToPrint) { // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); From 6ba506324731fc83d1c5d3e143feddb383efa19e Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Fri, 8 Nov 2024 06:29:42 -0800 Subject: [PATCH 3/9] Force namespace printing --- clang/include/clang/AST/PrettyPrinter.h | 5 +++++ clang/lib/AST/TypePrinter.cpp | 2 +- clang/lib/Sema/SemaSYCL.cpp | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index ef4af4dab4277..885e8e462e642 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -76,6 +76,7 @@ struct PrintingPolicy { MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), + EnforceScopeForElaboratedTypes(false), SuppressDefinition(false), SuppressDefaultTemplateArguments(false), PrintCanonicalTypes(false), SkipCanonicalizationOfTemplateTypeParms(false), @@ -342,6 +343,10 @@ struct PrintingPolicy { LLVM_PREFERRED_TYPE(bool) unsigned FullyQualifiedName : 1; + /// Enforce fully qualified name printing for elaborated types. + LLVM_PREFERRED_TYPE(bool) + unsigned EnforceScopeForElaboratedTypes : 1; + /// When true does not print definition of a type. E.g. /// \code /// template class C0 : public C1 {...} diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 366c065accf40..c6e8b64929f64 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -101,7 +101,7 @@ class ElaboratedTypePolicyRAII { SuppressTagKeyword = Policy.SuppressTagKeyword; SuppressScope = Policy.SuppressScope; Policy.SuppressTagKeyword = true; - Policy.SuppressScope = true; + Policy.SuppressScope = !Policy.EnforceScopeForElaboratedTypes; } ~ElaboratedTypePolicyRAII() { diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index e2930dd2bbc9c..df3edfe9e29b1 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -6483,6 +6483,8 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { Policy.SuppressDefinition = true; Policy.PolishForDeclaration = true; Policy.EnforceDefaultTemplateArgs = true; + Policy.FullyQualifiedName = true; + Policy.EnforceScopeForElaboratedTypes = true; if (FTD) { FTD->print(O, Policy); } else { @@ -6513,6 +6515,8 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { O << "}\n"; Policy.SuppressDefaultTemplateArgs = true; Policy.EnforceDefaultTemplateArgs = false; + Policy.FullyQualifiedName = false; + Policy.EnforceScopeForElaboratedTypes = false; // Generate is_kernel, is_single_task_kernel and nd_range_kernel functions. O << "namespace sycl {\n"; From 3e0e4bbbc70db43d3017d9166d9077e6e92843f5 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Fri, 8 Nov 2024 08:02:47 -0800 Subject: [PATCH 4/9] [WIP] Add test --- ...ee_function_default_template_arguments.cpp | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp diff --git a/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp new file mode 100644 index 0000000000000..c7d533ded81c1 --- /dev/null +++ b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown -sycl-std=2020 -fsycl-int-header=%t.h %s +// RUN: FileCheck -input-file=%t.h %s + +// This test checks integration header contents free functions kernels in +// presense of template arguments. + +#include "mock_properties.hpp" +#include "sycl.hpp" + +namespace ns { + +struct notatuple { + int a; +}; + +template struct Arg { + T val; +}; + +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", + 2)]] void +simple(Arg){ +} + +} + + +template +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void +templated(ns::Arg, T end) { +} + +template void templated(ns::Arg, int); + +using namespace ns; From 4f091c0d0613233b1729dbb0f83594123bfb5ed1 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Mon, 11 Nov 2024 05:51:53 -0800 Subject: [PATCH 5/9] Fix nns printing and add a couple of tests --- clang/lib/AST/TypePrinter.cpp | 6 ++-- ...ee_function_default_template_arguments.cpp | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index c6e8b64929f64..aed229af94afc 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1726,8 +1726,10 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T, Policy.SuppressScope = OldSupressScope; return; } - if (Qualifier && !(Policy.SuppressTypedefs && - T->getNamedType()->getTypeClass() == Type::Typedef)) + if (Qualifier && + !(Policy.SuppressTypedefs && + T->getNamedType()->getTypeClass() == Type::Typedef) && + !Policy.EnforceScopeForElaboratedTypes) Qualifier->print(OS, Policy); } diff --git a/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp index c7d533ded81c1..f4b068f237734 100644 --- a/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp +++ b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp @@ -33,3 +33,38 @@ templated(ns::Arg, T end) { template void templated(ns::Arg, int); using namespace ns; + +template +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void +templated2(Arg, T end) { +} + +template void templated2(Arg, int); + +// CHECK: Definition of _ZN16__sycl_kernel_ns6simpleENS_3ArgIciLi12ENS_9notatupleEJEEE as a free function kernel + +// CHECK: Forward declarations of kernel and its argument types: +// CHECK-NEXT: namespace ns { +// CHECK-NEXT: struct notatuple; +// CHECK-NEXT: } +// CHECK-NEXT: namespace ns { +// CHECK-NEXT: template struct Arg; +// CHECK-NEXT: } + +// CHECK: void ns::simple(ns::Arg); +// CHECK-NEXT: static constexpr auto __sycl_shim1() { +// CHECK-NEXT: return (void (*)(struct ns::Arg))simple; +// CHECK-NEXT: } + +// CHECK: Definition of _Z23__sycl_kernel_templatedIiEvN2ns3ArgIT_fLi3ENS0_9notatupleEJEEES2_ as a free function kernel +// CHECK: template void templated(ns::Arg, T end); +// CHECK-NEXT: static constexpr auto __sycl_shim2() { +// CHECK-NEXT: return (void (*)(struct ns::Arg, int))templated; +// CHECK-NEXT: } + +// CHECK: Definition of _Z24__sycl_kernel_templated2IiEvN2ns3ArgIT_NS0_9notatupleELi12ES3_JEEES2_ as a free function kernel +// CHECK: Forward declarations of kernel and its argument types: +// CHECK: template void templated2(ns::Arg, T end); +// CHECK-NEXT: static constexpr auto __sycl_shim3() { +// CHECK-NEXT: return (void (*)(struct ns::Arg, int))templated2; +// CHECK-NEXT: } From 7e2272fa6971af25b184886e004556cd77d9a14b Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Mon, 11 Nov 2024 08:52:38 -0800 Subject: [PATCH 6/9] Add more tests, clean SemaSYCL --- clang/lib/Sema/SemaSYCL.cpp | 20 +++++--- ...ee_function_default_template_arguments.cpp | 46 +++++++++++++++---- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index df3edfe9e29b1..f4f98ffa8f058 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -6464,7 +6464,6 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { O << "\n"; O << "// Forward declarations of kernel and its argument types:\n"; - Policy.SuppressDefaultTemplateArgs = false; FwdDeclEmitter.Visit(K.SyclKernel->getType()); O << "\n"; @@ -6472,6 +6471,7 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { O << "extern \"C\" "; std::string ParmList; bool FirstParam = true; + Policy.SuppressDefaultTemplateArgs = false; for (ParmVarDecl *Param : K.SyclKernel->parameters()) { if (FirstParam) FirstParam = false; @@ -6482,9 +6482,21 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { FunctionTemplateDecl *FTD = K.SyclKernel->getPrimaryTemplate(); Policy.SuppressDefinition = true; Policy.PolishForDeclaration = true; - Policy.EnforceDefaultTemplateArgs = true; Policy.FullyQualifiedName = true; Policy.EnforceScopeForElaboratedTypes = true; + + // SuppressDefaultTemplateArguments is a downstream addition that suppresses + // default template arguments in function declarations. It should be set to + // true to emit function declaration that won't cause any compilation errors + // when present in the integration header. + // SuppressDefaultTemplateArgs is a flag from community code which adds + // suppression of template arguments that match default template arguments + // in template-ids printing. + Policy.SuppressDefaultTemplateArguments = true; + // EnforceDefaultTemplateArgs is a downstream addition that forces printing + // template arguments that match default template arguments while printing + // template-ids, even if the source code doesn't referece them. + Policy.EnforceDefaultTemplateArgs = true; if (FTD) { FTD->print(O, Policy); } else { @@ -6513,10 +6525,6 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { } O << ";\n"; O << "}\n"; - Policy.SuppressDefaultTemplateArgs = true; - Policy.EnforceDefaultTemplateArgs = false; - Policy.FullyQualifiedName = false; - Policy.EnforceScopeForElaboratedTypes = false; // Generate is_kernel, is_single_task_kernel and nd_range_kernel functions. O << "namespace sycl {\n"; diff --git a/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp index f4b068f237734..808f7b93d8112 100644 --- a/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp +++ b/clang/test/CodeGenSYCL/free_function_default_template_arguments.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown -sycl-std=2020 -fsycl-int-header=%t.h %s // RUN: FileCheck -input-file=%t.h %s -// This test checks integration header contents free functions kernels in -// presense of template arguments. +// This test checks integration header contents for free functions kernels with +// parameter types that have default template arguments. #include "mock_properties.hpp" #include "sycl.hpp" @@ -13,6 +13,13 @@ struct notatuple { int a; }; +namespace ns1 { +template +class hasDefaultArg { + +}; +} + template struct Arg { T val; }; @@ -24,6 +31,11 @@ simple(Arg){ } +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", + 2)]] void +simple1(ns::Arg>){ +} + template [[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void @@ -41,7 +53,12 @@ templated2(Arg, T end) { template void templated2(Arg, int); -// CHECK: Definition of _ZN16__sycl_kernel_ns6simpleENS_3ArgIciLi12ENS_9notatupleEJEEE as a free function kernel +template +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void +templated3(Arg, int, int>, T end) { +} + +template void templated3(Arg, int, int>, int); // CHECK: Forward declarations of kernel and its argument types: // CHECK-NEXT: namespace ns { @@ -56,15 +73,28 @@ template void templated2(Arg, int); // CHECK-NEXT: return (void (*)(struct ns::Arg))simple; // CHECK-NEXT: } -// CHECK: Definition of _Z23__sycl_kernel_templatedIiEvN2ns3ArgIT_fLi3ENS0_9notatupleEJEEES2_ as a free function kernel -// CHECK: template void templated(ns::Arg, T end); +// CHECK: Forward declarations of kernel and its argument types: +// CHECK: namespace ns { +// CHECK: namespace ns1 { +// CHECK-NEXT: template class hasDefaultArg; +// CHECK-NEXT: } + +// CHECK: void simple1(ns::Arg, int, 12, ns::notatuple>); // CHECK-NEXT: static constexpr auto __sycl_shim2() { +// CHECK-NEXT: return (void (*)(struct ns::Arg, int, 12, struct ns::notatuple>))simple1; +// CHECK-NEXT: } + +// CHECK: template void templated(ns::Arg, T end); +// CHECK-NEXT: static constexpr auto __sycl_shim3() { // CHECK-NEXT: return (void (*)(struct ns::Arg, int))templated; // CHECK-NEXT: } -// CHECK: Definition of _Z24__sycl_kernel_templated2IiEvN2ns3ArgIT_NS0_9notatupleELi12ES3_JEEES2_ as a free function kernel -// CHECK: Forward declarations of kernel and its argument types: // CHECK: template void templated2(ns::Arg, T end); -// CHECK-NEXT: static constexpr auto __sycl_shim3() { +// CHECK-NEXT: static constexpr auto __sycl_shim4() { // CHECK-NEXT: return (void (*)(struct ns::Arg, int))templated2; // CHECK-NEXT: } + +// CHECK: template void templated3(ns::Arg, int, int>, T end); +// CHECK-NEXT: static constexpr auto __sycl_shim5() { +// CHECK-NEXT: return (void (*)(struct ns::Arg, int, int>, int))templated3; +// CHECK-NEXT: } From e2066845182eb8c100ad2e126bb6c406513b2be8 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Mon, 11 Nov 2024 08:53:58 -0800 Subject: [PATCH 7/9] Fix format --- clang/include/clang/AST/PrettyPrinter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 885e8e462e642..b6768f068164b 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -76,9 +76,8 @@ struct PrintingPolicy { MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - EnforceScopeForElaboratedTypes(false), - SuppressDefinition(false), SuppressDefaultTemplateArguments(false), - PrintCanonicalTypes(false), + EnforceScopeForElaboratedTypes(false), SuppressDefinition(false), + SuppressDefaultTemplateArguments(false), PrintCanonicalTypes(false), SkipCanonicalizationOfTemplateTypeParms(false), PrintInjectedClassNameWithArguments(true), UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false), From aded78ea6d1d44d8d261cf6d0f03c3204b282447 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Mon, 11 Nov 2024 09:00:27 -0800 Subject: [PATCH 8/9] Fix format again --- clang/include/clang/AST/PrettyPrinter.h | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index b6768f068164b..4f4a6644b02cd 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -238,7 +238,6 @@ struct PrintingPolicy { LLVM_PREFERRED_TYPE(bool) unsigned SuppressDefaultTemplateArgs : 1; - /// When true, print template arguments that match the default argument for /// the parameter, even if they're not specified in the source. LLVM_PREFERRED_TYPE(bool) From 30ff224291c62dd6f919ddcdbad2150c50358409 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" Date: Thu, 14 Nov 2024 07:24:40 -0800 Subject: [PATCH 9/9] Try to clarify comments with an example --- clang/lib/Sema/SemaSYCL.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index f4f98ffa8f058..363013def4fbd 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -6485,17 +6485,31 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { Policy.FullyQualifiedName = true; Policy.EnforceScopeForElaboratedTypes = true; + // Now we need to print the declaration of the kernel itself. + // Example: + // template struct Arg { + // T val; + // }; + // For the following free function kernel: + // template + // SYCL_EXT_ONEAPI_FUNCTION_PROPERTY( + // (ext::oneapi::experimental::nd_range_kernel<1>)) + // void foo(Arg arg) {} + // Integration header must contain the following declaration: + // template + // void foo(Arg arg); // SuppressDefaultTemplateArguments is a downstream addition that suppresses - // default template arguments in function declarations. It should be set to - // true to emit function declaration that won't cause any compilation errors - // when present in the integration header. - // SuppressDefaultTemplateArgs is a flag from community code which adds - // suppression of template arguments that match default template arguments - // in template-ids printing. + // default template arguments in the function declaration. It should be set + // to true to emit function declaration that won't cause any compilation + // errors when present in the integration header. + // To print Arg in the function declaration and shim functions we + // need to disable default arguments printing suppression via community flag + // SuppressDefaultTemplateArgs, otherwise they will be suppressed even for + // canonical types or if even written in the original source code. Policy.SuppressDefaultTemplateArguments = true; // EnforceDefaultTemplateArgs is a downstream addition that forces printing // template arguments that match default template arguments while printing - // template-ids, even if the source code doesn't referece them. + // template-ids, even if the source code doesn't reference them. Policy.EnforceDefaultTemplateArgs = true; if (FTD) { FTD->print(O, Policy);