Skip to content

Commit 0937042

Browse files
committed
Merge remote-tracking branch 'remote/sycl' into opt-report
2 parents f99e200 + d482ac3 commit 0937042

35 files changed

+1279
-81
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 163 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4496,10 +4496,22 @@ SYCLIntegrationHeader::SYCLIntegrationHeader(bool _UnnamedLambdaSupport,
44964496
: UnnamedLambdaSupport(_UnnamedLambdaSupport), S(_S) {}
44974497

44984498
void SYCLIntegrationFooter::addVarDecl(const VarDecl *VD) {
4499+
// Skip the dependent version of these variables, we only care about them
4500+
// after instantiation.
4501+
if (VD->getDeclContext()->isDependentContext())
4502+
return;
44994503
// Step 1: ensure that this is of the correct type-spec-constant template
45004504
// specialization).
4501-
if (!Util::isSyclSpecIdType(VD->getType()))
4502-
return;
4505+
if (!Util::isSyclSpecIdType(VD->getType())) {
4506+
// Handle the case where this could be a deduced type, such as a deduction
4507+
// guide. We have to do this here since this function, unlike most of the
4508+
// rest of this file, is called during Sema instead of after it. We will
4509+
// also have to filter out after deduction later.
4510+
QualType Ty = VD->getType().getCanonicalType();
4511+
4512+
if (!Ty->isUndeducedType())
4513+
return;
4514+
}
45034515
// Step 2: ensure that this is a static member, or a namespace-scope.
45044516
// Note that isLocalVarDeclorParm excludes thread-local and static-local
45054517
// intentionally, as there is no way to 'spell' one of those in the
@@ -4541,26 +4553,162 @@ void SYCLIntegrationFooter::emitSpecIDName(raw_ostream &O, const VarDecl *VD) {
45414553
O << "";
45424554
}
45434555

4544-
bool SYCLIntegrationFooter::emit(raw_ostream &O) {
4556+
template <typename BeforeFn, typename AfterFn>
4557+
static void PrintNSHelper(BeforeFn Before, AfterFn After, raw_ostream &OS,
4558+
const DeclContext *DC) {
4559+
if (DC->isTranslationUnit())
4560+
return;
4561+
4562+
const auto *CurDecl = cast<Decl>(DC);
4563+
// Ensure we are in the canonical version, so that we know we have the 'full'
4564+
// name of the thing.
4565+
CurDecl = CurDecl->getCanonicalDecl();
4566+
4567+
// We are intentionally skipping linkage decls and record decls. Namespaces
4568+
// can appear in a linkage decl, but not a record decl, so we don't have to
4569+
// worry about the names getting messed up from that. We handle record decls
4570+
// later when printing the name of the thing.
4571+
const auto *NS = dyn_cast<NamespaceDecl>(CurDecl);
4572+
if (NS)
4573+
Before(OS, NS);
4574+
4575+
if (const DeclContext *NewDC = CurDecl->getDeclContext())
4576+
PrintNSHelper(Before, After, OS, NewDC);
4577+
4578+
if (NS)
4579+
After(OS, NS);
4580+
}
4581+
4582+
static void PrintNamespaces(raw_ostream &OS, const DeclContext *DC) {
4583+
PrintNSHelper([](raw_ostream &OS, const NamespaceDecl *NS) {},
4584+
[](raw_ostream &OS, const NamespaceDecl *NS) {
4585+
if (NS->isInline())
4586+
OS << "inline ";
4587+
OS << "namespace ";
4588+
if (!NS->isAnonymousNamespace())
4589+
OS << NS->getName() << " ";
4590+
OS << "{\n";
4591+
},
4592+
OS, DC);
4593+
}
4594+
4595+
static void PrintNSClosingBraces(raw_ostream &OS, const DeclContext *DC) {
4596+
PrintNSHelper(
4597+
[](raw_ostream &OS, const NamespaceDecl *NS) {
4598+
OS << "} // ";
4599+
if (NS->isInline())
4600+
OS << "inline ";
4601+
4602+
OS << "namespace ";
4603+
if (!NS->isAnonymousNamespace())
4604+
OS << NS->getName();
4605+
4606+
OS << '\n';
4607+
},
4608+
[](raw_ostream &OS, const NamespaceDecl *NS) {}, OS, DC);
4609+
}
4610+
4611+
static std::string EmitSpecIdShim(raw_ostream &OS, unsigned &ShimCounter,
4612+
const std::string &LastShim,
4613+
const NamespaceDecl *AnonNS) {
4614+
std::string NewShimName =
4615+
"__sycl_detail::__spec_id_shim_" + std::to_string(ShimCounter) + "()";
4616+
// Print opening-namespace
4617+
PrintNamespaces(OS, Decl::castToDeclContext(AnonNS));
4618+
OS << "namespace __sycl_detail {\n";
4619+
OS << "static constexpr decltype(" << LastShim << ") &__spec_id_shim_"
4620+
<< ShimCounter << "() {\n";
4621+
OS << " return " << LastShim << ";\n";
4622+
OS << "}\n";
4623+
OS << "} // namespace __sycl_detail \n";
4624+
PrintNSClosingBraces(OS, Decl::castToDeclContext(AnonNS));
4625+
4626+
++ShimCounter;
4627+
return std::move(NewShimName);
4628+
}
4629+
4630+
// Emit the list of shims required for a DeclContext, calls itself recursively.
4631+
static void EmitSpecIdShims(raw_ostream &OS, unsigned &ShimCounter,
4632+
const DeclContext *DC,
4633+
std::string &NameForLastShim) {
4634+
if (DC->isTranslationUnit()) {
4635+
NameForLastShim = "::" + NameForLastShim;
4636+
return;
4637+
}
4638+
4639+
const auto *CurDecl = cast<Decl>(DC)->getCanonicalDecl();
4640+
4641+
// We skip linkage decls, since they don't modify the Qualified name.
4642+
if (const auto *RD = dyn_cast<RecordDecl>(CurDecl)) {
4643+
NameForLastShim = RD->getNameAsString() + "::" + NameForLastShim;
4644+
} else if (const auto *ND = dyn_cast<NamespaceDecl>(CurDecl)) {
4645+
if (ND->isAnonymousNamespace()) {
4646+
// Print current shim, reset 'name for last shim'.
4647+
NameForLastShim = EmitSpecIdShim(OS, ShimCounter, NameForLastShim, ND);
4648+
} else {
4649+
NameForLastShim = ND->getNameAsString() + "::" + NameForLastShim;
4650+
}
4651+
} else {
4652+
// FIXME: I don't believe there are other declarations that these variables
4653+
// could possibly find themselves in. LinkageDecls don't change the
4654+
// qualified name, so there is nothing to do here. At one point we should
4655+
// probably convince ourselves that this is entire list and remove this
4656+
// comment.
4657+
assert((isa<LinkageSpecDecl, ExternCContextDecl>(CurDecl)) &&
4658+
"Unhandled decl type");
4659+
}
4660+
4661+
EmitSpecIdShims(OS, ShimCounter, CurDecl->getDeclContext(), NameForLastShim);
4662+
}
4663+
4664+
// Emit the list of shims required for a variable declaration.
4665+
// Returns a string containing the FQN of the 'top most' shim, including its
4666+
// function call parameters.
4667+
static std::string EmitSpecIdShims(raw_ostream &OS, unsigned &ShimCounter,
4668+
const VarDecl *VD) {
4669+
assert(VD->isInAnonymousNamespace() &&
4670+
"Function assumes this is in an anonymous namespace");
4671+
std::string RelativeName = VD->getNameAsString();
4672+
EmitSpecIdShims(OS, ShimCounter, VD->getDeclContext(), RelativeName);
4673+
return std::move(RelativeName);
4674+
}
4675+
4676+
bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
45454677
PrintingPolicy Policy{S.getLangOpts()};
45464678
Policy.adjustForCPlusPlusFwdDecl();
45474679
Policy.SuppressTypedefs = true;
45484680
Policy.SuppressUnwrittenScope = true;
45494681

4550-
for (const VarDecl *D : SpecConstants) {
4551-
O << "template<>\n";
4552-
O << "inline const char *get_spec_constant_symbolic_ID<";
4553-
// Emit the FQN for this, but we probably need to do some funny-business for
4554-
// anonymous namespaces.
4555-
D->printQualifiedName(O, Policy);
4556-
O << ">() {\n";
4557-
O << " return \"";
4558-
emitSpecIDName(O, D);
4559-
O << "\";\n";
4560-
O << "}\n";
4682+
// Used to uniquely name the 'shim's as we generate the names in each
4683+
// anonymous namespace.
4684+
unsigned ShimCounter = 0;
4685+
for (const VarDecl *VD : SpecConstants) {
4686+
VD = VD->getCanonicalDecl();
4687+
if (VD->isInAnonymousNamespace()) {
4688+
std::string TopShim = EmitSpecIdShims(OS, ShimCounter, VD);
4689+
OS << "namespace sycl {\n";
4690+
OS << "namespace detail {\n";
4691+
OS << "template<>\n";
4692+
OS << "inline const char *get_spec_constant_symbolic_ID<" << TopShim
4693+
<< ">() {\n";
4694+
OS << " return " << TopShim << ";\n";
4695+
} else {
4696+
OS << "namespace sycl {\n";
4697+
OS << "namespace detail {\n";
4698+
OS << "template<>\n";
4699+
OS << "inline const char *get_spec_constant_symbolic_ID<::";
4700+
VD->printQualifiedName(OS, Policy);
4701+
OS << ">() {\n";
4702+
OS << " return \"";
4703+
emitSpecIDName(OS, VD);
4704+
OS << "\";\n";
4705+
}
4706+
OS << "}\n";
4707+
OS << "} // namespace detail\n";
4708+
OS << "} // namespace sycl\n";
45614709
}
45624710

4563-
O << "#include <CL/sycl/detail/spec_const_integration.hpp>\n";
4711+
OS << "#include <CL/sycl/detail/spec_const_integration.hpp>\n";
45644712
return true;
45654713
}
45664714

clang/test/CodeGenSYCL/Inputs/sycl.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ template <typename T> class specialization_id {
321321
T MDefaultValue;
322322
};
323323

324+
#if __cplusplus >= 201703L
325+
template<typename T> specialization_id(T) -> specialization_id<T>;
326+
#endif // C++17.
327+
324328
#define ATTR_SYCL_KERNEL __attribute__((sycl_kernel))
325329
template <typename KernelName = auto_name, typename KernelType>
326330
ATTR_SYCL_KERNEL void kernel_single_task(const KernelType &kernelFunc) { // #KernelSingleTask

0 commit comments

Comments
 (0)