[clang] 9324cc2 - Change __builtin_sycl_unique_stable_name to just use an Itanium mangling
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 28 06:41:21 PDT 2021
Author: Erich Keane
Date: 2021-09-28T06:41:03-07:00
New Revision: 9324cc2ca951fe5fe11c85470cb08e699c59499c
URL: https://github.com/llvm/llvm-project/commit/9324cc2ca951fe5fe11c85470cb08e699c59499c
DIFF: https://github.com/llvm/llvm-project/commit/9324cc2ca951fe5fe11c85470cb08e699c59499c.diff
LOG: Change __builtin_sycl_unique_stable_name to just use an Itanium mangling
After significant problems in our downstream with the previous
implementation, the SYCL standard has opted to make using macros/etc to
change kernel-naming-lambdas in any way UB (even passively). As a
result, we are able to just emit the itanium mangling.
However, this DOES require a little work in the CXXABI, as the microsoft
and itanium mangler use different numbering schemes for lambdas. This
patch adds a pair of mangling contexts that use the normal 'itanium'
mangling strategy to fill in the "DeviceManglingNumber" used previously
by CUDA.
Differential Revision: https://reviews.llvm.org/D110281
Added:
Modified:
clang/docs/LanguageExtensions.rst
clang/include/clang/AST/ASTContext.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/AST/ItaniumCXXABI.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftCXXABI.cpp
clang/lib/Sema/SemaSYCL.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/CodeGenSYCL/unique_stable_name.cpp
clang/test/CodeGenSYCL/unique_stable_name_windows_diff.cpp
clang/test/SemaSYCL/unique_stable_name.cpp
Removed:
################################################################################
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 56e351183899b..5fe47199dcd21 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2521,12 +2521,9 @@ it in an instantiation which changes its value.
In order to produce the unique name, the current implementation of the bultin
uses Itanium mangling even if the host compilation uses a
diff erent name
mangling scheme at runtime. The mangler marks all the lambdas required to name
-the SYCL kernel and emits a stable local ordering of the respective lambdas,
-starting from ``10000``. The initial value of ``10000`` serves as an obvious
-
diff erentiator from ordinary lambda mangling numbers but does not serve any
-other purpose and may change in the future. The resulting pattern is
-demanglable. When non-lambda types are passed to the builtin, the mangler emits
-their usual pattern without any special treatment.
+the SYCL kernel and emits a stable local ordering of the respective lambdas.
+The resulting pattern is demanglable. When non-lambda types are passed to the
+builtin, the mangler emits their usual pattern without any special treatment.
**Syntax**:
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f1b057c8003f8..582134e586e0d 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3239,31 +3239,10 @@ OPT_LIST(V)
StringRef getCUIDHash() const;
- void AddSYCLKernelNamingDecl(const CXXRecordDecl *RD);
- bool IsSYCLKernelNamingDecl(const NamedDecl *RD) const;
- unsigned GetSYCLKernelNamingIndex(const NamedDecl *RD);
- /// A SourceLocation to store whether we have evaluated a kernel name already,
- /// and where it happened. If so, we need to diagnose an illegal use of the
- /// builtin.
- llvm::MapVector<const SYCLUniqueStableNameExpr *, std::string>
- SYCLUniqueStableNameEvaluatedValues;
-
private:
/// All OMPTraitInfo objects live in this collection, one per
/// `pragma omp [begin] declare variant` directive.
SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector;
-
- /// A list of the (right now just lambda decls) declarations required to
- /// name all the SYCL kernels in the translation unit, so that we can get the
- /// correct kernel name, as well as implement
- /// __builtin_sycl_unique_stable_name.
- llvm::DenseMap<const DeclContext *,
- llvm::SmallPtrSet<const CXXRecordDecl *, 4>>
- SYCLKernelNamingTypes;
- std::unique_ptr<ItaniumMangleContext> SYCLKernelFilterContext;
- void FilterSYCLKernelNamingDecls(
- const CXXRecordDecl *RD,
- llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls);
};
/// Insertion operator for diagnostics.
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0e803ee028ce9..5a3eab540d1fe 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6409,11 +6409,6 @@ def warn_gnu_null_ptr_arith : Warning<
def warn_pointer_sub_null_ptr : Warning<
"performing pointer subtraction with a null pointer %select{has|may have}0 undefined behavior">,
InGroup<NullPointerSubtraction>, DefaultIgnore;
-def err_kernel_invalidates_sycl_unique_stable_name
- : Error<"kernel instantiation changes the result of an evaluated "
- "'__builtin_sycl_unique_stable_name'">;
-def note_sycl_unique_stable_name_evaluated_here
- : Note<"'__builtin_sycl_unique_stable_name' evaluated here">;
def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 93d5558b8267c..d35f5c520a949 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -914,10 +914,6 @@ class Sema final {
OpaqueParser = P;
}
- // Does the work necessary to deal with a SYCL kernel lambda. At the moment,
- // this just marks the list of lambdas required to name the kernel.
- void AddSYCLKernelLambda(const FunctionDecl *FD);
-
class DelayedDiagnostics;
class DelayedDiagnosticsState {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 42c3dcfd98636..e2ebe737fdfdc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11801,86 +11801,3 @@ StringRef ASTContext::getCUIDHash() const {
CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
return CUIDHash;
}
-
-// Get the closest named parent, so we can order the sycl naming decls somewhere
-// that mangling is meaningful.
-static const DeclContext *GetNamedParent(const CXXRecordDecl *RD) {
- const DeclContext *DC = RD->getDeclContext();
-
- while (!isa<NamedDecl, TranslationUnitDecl>(DC))
- DC = DC->getParent();
- return DC;
-}
-
-void ASTContext::AddSYCLKernelNamingDecl(const CXXRecordDecl *RD) {
- assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
- RD = RD->getCanonicalDecl();
- const DeclContext *DC = GetNamedParent(RD);
-
- assert(RD->getLocation().isValid() &&
- "Invalid location on kernel naming decl");
-
- (void)SYCLKernelNamingTypes[DC].insert(RD);
-}
-
-bool ASTContext::IsSYCLKernelNamingDecl(const NamedDecl *ND) const {
- assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
- const auto *RD = dyn_cast<CXXRecordDecl>(ND);
- if (!RD)
- return false;
- RD = RD->getCanonicalDecl();
- const DeclContext *DC = GetNamedParent(RD);
-
- auto Itr = SYCLKernelNamingTypes.find(DC);
-
- if (Itr == SYCLKernelNamingTypes.end())
- return false;
-
- return Itr->getSecond().count(RD);
-}
-
-// Filters the Decls list to those that share the lambda mangling with the
-// passed RD.
-void ASTContext::FilterSYCLKernelNamingDecls(
- const CXXRecordDecl *RD,
- llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls) {
-
- if (!SYCLKernelFilterContext)
- SYCLKernelFilterContext.reset(
- ItaniumMangleContext::create(*this, getDiagnostics()));
-
- llvm::SmallString<128> LambdaSig;
- llvm::raw_svector_ostream Out(LambdaSig);
- SYCLKernelFilterContext->mangleLambdaSig(RD, Out);
-
- llvm::erase_if(Decls, [this, &LambdaSig](const CXXRecordDecl *LocalRD) {
- llvm::SmallString<128> LocalLambdaSig;
- llvm::raw_svector_ostream LocalOut(LocalLambdaSig);
- SYCLKernelFilterContext->mangleLambdaSig(LocalRD, LocalOut);
- return LambdaSig != LocalLambdaSig;
- });
-}
-
-unsigned ASTContext::GetSYCLKernelNamingIndex(const NamedDecl *ND) {
- assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
- assert(IsSYCLKernelNamingDecl(ND) &&
- "Lambda not involved in mangling asked for a naming index?");
-
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(ND)->getCanonicalDecl();
- const DeclContext *DC = GetNamedParent(RD);
-
- auto Itr = SYCLKernelNamingTypes.find(DC);
- assert(Itr != SYCLKernelNamingTypes.end() && "Not a valid DeclContext?");
-
- const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &Set = Itr->getSecond();
-
- llvm::SmallVector<const CXXRecordDecl *> Decls{Set.begin(), Set.end()};
-
- FilterSYCLKernelNamingDecls(RD, Decls);
-
- llvm::sort(Decls, [](const CXXRecordDecl *LHS, const CXXRecordDecl *RHS) {
- return LHS->getLambdaManglingNumber() < RHS->getLambdaManglingNumber();
- });
-
- return llvm::find(Decls, RD) - Decls.begin();
-}
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9fde21c7ee9e1..7972f9a1aee76 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -545,20 +545,10 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
QualType Ty) {
auto MangleCallback = [](ASTContext &Ctx,
const NamedDecl *ND) -> llvm::Optional<unsigned> {
- // This replaces the 'lambda number' in the mangling with a unique number
- // based on its order in the declaration. To provide some level of visual
- // notability (actual uniqueness from normal lambdas isn't necessary, as
- // these are used
diff erently), we add 10,000 to the number.
- // For example:
- // _ZTSZ3foovEUlvE10005_
- // Demangles to: typeinfo name for foo()::'lambda10005'()
- // Note that the mangler subtracts 2, since with normal lambdas the lambda
- // mangling number '0' is an anonymous struct mangle, and '1' is omitted.
- // So 10,002 results in the first number being 10,000.
- if (Ctx.IsSYCLKernelNamingDecl(ND))
- return 10'002 + Ctx.GetSYCLKernelNamingIndex(ND);
- return llvm::None;
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
+ return RD->getDeviceLambdaManglingNumber();
};
+
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
Context, Context.getDiagnostics(), MangleCallback)};
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index ea7818c43e321..0ac36708f0774 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8674,8 +8674,6 @@ class PointerExprEvaluator
bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E) {
std::string ResultStr = E->ComputeName(Info.Ctx);
- Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
-
QualType CharTy = Info.Ctx.CharTy.withConst();
APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
ResultStr.size() + 1);
diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp
index be10258a2d774..e99c21dcff73c 100644
--- a/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/clang/lib/AST/ItaniumCXXABI.cpp
@@ -181,6 +181,37 @@ class ItaniumNumberingContext : public MangleNumberingContext {
}
};
+// A version of this for SYCL that makes sure that 'device' mangling context
+// matches the lambda mangling number, so that __builtin_sycl_unique_stable_name
+// can be consistently generated between a MS and Itanium host by just referring
+// to the device mangling number.
+class ItaniumSYCLNumberingContext : public ItaniumNumberingContext {
+ llvm::DenseMap<const CXXMethodDecl *, unsigned> ManglingNumbers;
+ using ManglingItr = decltype(ManglingNumbers)::iterator;
+
+public:
+ ItaniumSYCLNumberingContext(ItaniumMangleContext *Mangler)
+ : ItaniumNumberingContext(Mangler) {}
+
+ unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
+ unsigned Number = ItaniumNumberingContext::getManglingNumber(CallOperator);
+ std::pair<ManglingItr, bool> emplace_result =
+ ManglingNumbers.try_emplace(CallOperator, Number);
+ (void)emplace_result;
+ assert(emplace_result.second && "Lambda number set multiple times?");
+ return Number;
+ }
+
+ using ItaniumNumberingContext::getManglingNumber;
+
+ unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
+ ManglingItr Itr = ManglingNumbers.find(CallOperator);
+ assert(Itr != ManglingNumbers.end() && "Lambda not yet mangled?");
+
+ return Itr->second;
+ }
+};
+
class ItaniumCXXABI : public CXXABI {
private:
std::unique_ptr<MangleContext> Mangler;
@@ -249,6 +280,9 @@ class ItaniumCXXABI : public CXXABI {
std::unique_ptr<MangleNumberingContext>
createMangleNumberingContext() const override {
+ if (Context.getLangOpts().isSYCL())
+ return std::make_unique<ItaniumSYCLNumberingContext>(
+ cast<ItaniumMangleContext>(Mangler.get()));
return std::make_unique<ItaniumNumberingContext>(
cast<ItaniumMangleContext>(Mangler.get()));
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b1ac62b0ac983..34ad2b0b1d043 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1518,9 +1518,16 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
// # Parameter types or 'v' for 'void'.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
- if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
- Context.getDiscriminatorOverride()(
- Context.getASTContext(), Record))) {
+ llvm::Optional<unsigned> DeviceNumber =
+ Context.getDiscriminatorOverride()(Context.getASTContext(), Record);
+
+ // If we have a device-number via the discriminator, use that to mangle
+ // the lambda, otherwise use the typical lambda-mangling-number. In either
+ // case, a '0' should be mangled as a normal unnamed class instead of as a
+ // lambda.
+ if (Record->isLambda() &&
+ ((DeviceNumber && *DeviceNumber > 0) ||
+ (!DeviceNumber && Record->getLambdaManglingNumber() > 0))) {
assert(!AdditionalAbiTags &&
"Lambda type cannot have additional abi tags");
mangleLambda(Record);
@@ -1960,8 +1967,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
// mangling number for this lambda.
llvm::Optional<unsigned> DeviceNumber =
Context.getDiscriminatorOverride()(Context.getASTContext(), Lambda);
- unsigned Number = DeviceNumber.hasValue() ? *DeviceNumber
- : Lambda->getLambdaManglingNumber();
+ unsigned Number =
+ DeviceNumber ? *DeviceNumber : Lambda->getLambdaManglingNumber();
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
if (Number > 1)
diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp
index 166aa3b3bd603..53d7e0b042ff1 100644
--- a/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -78,6 +78,19 @@ class MSHIPNumberingContext : public MicrosoftNumberingContext {
}
};
+class MSSYCLNumberingContext : public MicrosoftNumberingContext {
+ std::unique_ptr<MangleNumberingContext> DeviceCtx;
+
+public:
+ MSSYCLNumberingContext(MangleContext *DeviceMangler) {
+ DeviceCtx = createItaniumNumberingContext(DeviceMangler);
+ }
+
+ unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
+ return DeviceCtx->getManglingNumber(CallOperator);
+ }
+};
+
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
@@ -100,6 +113,10 @@ class MicrosoftCXXABI : public CXXABI {
DeviceMangler.reset(
Context.createMangleContext(Context.getAuxTargetInfo()));
}
+ else if (Context.getLangOpts().isSYCL()) {
+ DeviceMangler.reset(
+ ItaniumMangleContext::create(Context, Context.getDiagnostics()));
+ }
}
MemberPointerInfo
@@ -162,7 +179,11 @@ class MicrosoftCXXABI : public CXXABI {
if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) {
assert(DeviceMangler && "Missing device mangler");
return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
+ } else if (Context.getLangOpts().isSYCL()) {
+ assert(DeviceMangler && "Missing device mangler");
+ return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get());
}
+
return std::make_unique<MicrosoftNumberingContext>();
}
};
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index 3b48a53efc0d1..481725eb0924e 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -48,35 +48,3 @@ bool Sema::checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee) {
return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
}
-
-// The SYCL kernel's 'object type' used for diagnostics and naming/mangling is
-// the first parameter to a sycl_kernel labeled function template. In SYCL1.2.1,
-// this was passed by value, and in SYCL2020, it is passed by reference.
-static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller) {
- assert(KernelCaller->getNumParams() > 0 && "Insufficient kernel parameters");
- QualType KernelParamTy = KernelCaller->getParamDecl(0)->getType();
-
- // SYCL 2020 kernels are passed by reference.
- if (KernelParamTy->isReferenceType())
- return KernelParamTy->getPointeeType();
-
- // SYCL 1.2.1
- return KernelParamTy;
-}
-
-void Sema::AddSYCLKernelLambda(const FunctionDecl *FD) {
- auto MangleCallback = [](ASTContext &Ctx,
- const NamedDecl *ND) -> llvm::Optional<unsigned> {
- if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
- Ctx.AddSYCLKernelNamingDecl(RD);
- // We always want to go into the lambda mangling (skipping the unnamed
- // struct version), so make sure we return a value here.
- return 1;
- };
-
- QualType Ty = GetSYCLKernelObjectType(FD);
- std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
- Context, Context.getDiagnostics(), MangleCallback)};
- llvm::raw_null_ostream Out;
- Ctx->mangleTypeName(Ty, Out);
-}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 79fd065a7b69c..e5ccfc27db356 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -556,26 +556,6 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
static void instantiateDependentSYCLKernelAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const SYCLKernelAttr &Attr, Decl *New) {
- // Functions cannot be partially specialized, so if we are being instantiated,
- // we are obviously a complete specialization. Since this attribute is only
- // valid on function template declarations, we know that this is a full
- // instantiation of a kernel.
- S.AddSYCLKernelLambda(cast<FunctionDecl>(New));
-
- // Evaluate whether this would change any of the already evaluated
- // __builtin_sycl_unique_stable_name values.
- for (auto &Itr : S.Context.SYCLUniqueStableNameEvaluatedValues) {
- const std::string &CurName = Itr.first->ComputeName(S.Context);
- if (Itr.second != CurName) {
- S.Diag(New->getLocation(),
- diag::err_kernel_invalidates_sycl_unique_stable_name);
- S.Diag(Itr.first->getLocation(),
- diag::note_sycl_unique_stable_name_evaluated_here);
- // Update this so future diagnostics work correctly.
- Itr.second = CurName;
- }
- }
-
New->addAttr(Attr.clone(S.getASTContext()));
}
diff --git a/clang/test/CodeGenSYCL/unique_stable_name.cpp b/clang/test/CodeGenSYCL/unique_stable_name.cpp
index 380ddaeadc69c..462541a29fc2a 100644
--- a/clang/test/CodeGenSYCL/unique_stable_name.cpp
+++ b/clang/test/CodeGenSYCL/unique_stable_name.cpp
@@ -1,22 +1,22 @@
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -fsycl-is-device -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
-// CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE10000_E10000_\00"
+// CHECK: @[[LAMBDA_KERNEL3:[^\w]+]] = private unnamed_addr constant [[LAMBDA_K3_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ4mainEUlPZ4mainEUlvE_E_\00"
// CHECK: @[[INT1:[^\w]+]] = private unnamed_addr constant [[INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSi\00"
// CHECK: @[[STRING:[^\w]+]] = private unnamed_addr constant [[STRING_SIZE:\[[0-9]+ x i8\]]] c"_ZTSAppL_ZZ4mainE1jE_i\00",
// CHECK: @[[INT2:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
-// CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE_\00"
-// CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE0_\00"
-// CHECK: @[[MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE1_\00"
-// CHECK: @{{.*}} = private unnamed_addr constant [36 x i8] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE2_\00", align 1
-// CHECK: @{{.*}} = private unnamed_addr constant [36 x i8] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE3_\00", align 1
-// CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE4_\00"
-// CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE5_\00"
+// CHECK: @[[LAMBDA_X:[^\w]+]] = private unnamed_addr constant [[LAMBDA_X_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
+// CHECK: @[[MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE0_\00"
+// CHECK: @[[MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE1_\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE2_\00", align 1
+// CHECK: @{{.*}} = private unnamed_addr constant [32 x i8] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE3_\00", align 1
+// CHECK: @[[MACRO_MACRO_X:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE4_\00"
+// CHECK: @[[MACRO_MACRO_Y:[^\w]+]] = private unnamed_addr constant [[MACRO_MACRO_SIZE]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE5_\00"
// CHECK: @[[INT3:[^\w]+]] = private unnamed_addr constant [[INT_SIZE]] c"_ZTSi\00"
-// CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE10001_clEvEUlvE_\00"
+// CHECK: @[[LAMBDA:[^\w]+]] = private unnamed_addr constant [[LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZZ4mainENKUlvE0_clEvEUlvE_\00"
// CHECK: @[[LAMBDA_IN_DEP_INT:[^\w]+]] = private unnamed_addr constant [[DEP_INT_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIiEvvEUlvE_\00",
-// CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE10001_clEvEUlvE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_IN_DEP_X:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ28lambda_in_dependent_functionIZZ4mainENKUlvE0_clEvEUlvE_EvvEUlvE_\00",
// CHECK: @[[LAMBDA_NO_DEP:[^\w]+]] = private unnamed_addr constant [[NO_DEP_LAMBDA_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ13lambda_no_depIidEvT_T0_EUlidE_\00",
-// CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE10001_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00",
-// CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE10001_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_TWO_DEP:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA1_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUliE_ZZ4mainENKS0_clEvEUldE_EvvEUlvE_\00",
+// CHECK: @[[LAMBDA_TWO_DEP2:[^\w]+]] = private unnamed_addr constant [[DEP_LAMBDA2_SIZE:\[[0-9]+ x i8\]]] c"_ZTSZ14lambda_two_depIZZ4mainENKUlvE0_clEvEUldE_ZZ4mainENKS0_clEvEUliE_EvvEUlvE_\00",
extern "C" void puts(const char *) {}
diff --git a/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp b/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
index ecdc1d50abbee..7c7979f712f05 100644
--- a/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
+++ b/clang/test/CodeGenSYCL/unique_stable_name_windows_
diff .cpp
@@ -38,7 +38,7 @@ int main() {
// Make sure the following 3 are the same between the host and device compile.
// Note that these are NOT the same value as eachother, they
diff er by the
// signature.
- // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUlvE10000_\00"
- // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUliE10000_\00"
- // CHECK: private unnamed_addr constant [22 x i8] c"_ZTSZ4mainEUldE10000_\00"
+ // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUlvE_\00"
+ // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUliE_\00"
+ // CHECK: private unnamed_addr constant [17 x i8] c"_ZTSZ4mainEUldE_\00"
}
diff --git a/clang/test/SemaSYCL/unique_stable_name.cpp b/clang/test/SemaSYCL/unique_stable_name.cpp
index f86000fca4e23..2a0230d06137f 100644
--- a/clang/test/SemaSYCL/unique_stable_name.cpp
+++ b/clang/test/SemaSYCL/unique_stable_name.cpp
@@ -15,10 +15,6 @@ template <typename KernelName, typename KernelType>
template <typename Func>
void kernel1func(const Func &F1) {
constexpr const char *F1_output = __builtin_sycl_unique_stable_name(Func); // #USN_F1
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#kernel1func_call{{in instantiation of function template specialization}}
- // expected-note@#USN_F1{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel1>(F1); // #kernel1_call
}
@@ -38,10 +34,6 @@ void callkernel1() {
template <typename Func>
void kernel2func(const Func &F2) {
constexpr const char *F2_output = __builtin_sycl_unique_stable_name(Func); // #USN_F2
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#kernel2func_call{{in instantiation of function template specialization}}
- // expected-note@#USN_F2{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel2>([]() {});
}
@@ -93,40 +85,34 @@ int main() {
kernel_single_task<class kernel5>(
[=]() { l5(); }); // Used in the kernel, but not the kernel name itself
- // kernel6 - expect error
+ // kernel6 - expect no error
// Test that passing the lambda to the unique stable name builtin and then
- // using the same lambda in the naming of a kernel causes a diagnostic on the
- // kernel use due to the change in results to the stable name.
+ // using the same lambda in the naming of a kernel does not cause a diagnostic
+ // on the kernel use due to the change in results to the stable name.
auto l6 = []() { return 1; };
constexpr const char *l6_output =
__builtin_sycl_unique_stable_name(decltype(l6)); // #USN_l6
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#USN_l6{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel6>(l6); // Used in the kernel name after builtin
- // kernel7 - expect error
+ // kernel7 - expect no error
// Same as kernel11 (below) except make the lambda part of naming the kernel.
// Test that passing a lambda to the unique stable name builtin and then
- // passing a second lambda to the kernel throws an error because the first
- // lambda is included in the signature of the second lambda, hence it changes
- // the mangling of the kernel.
+ // passing a second lambda to the kernel does not throw an error because the
+ // first lambda is included in the signature of the second lambda, but does
+ // not change the mangling of the kernel.
auto l7 = []() { return 1; };
auto l8 = [](decltype(l7) *derp = nullptr) { return 2; };
constexpr const char *l7_output =
__builtin_sycl_unique_stable_name(decltype(l7)); // #USN_l7
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#USN_l7{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel7>(l8);
- // kernel8 and kernel9 - expect error
- // Tests that passing a lambda to the unique stable name builtin and passing it
- // to a kernel called with an if constexpr branch causes a diagnostic on the
- // kernel9 use due to the change in the results to the stable name. This happens
- // even though the use of kernel9 happens in the false branch of a constexpr if
- // because both the true and the false branches cause the instantiation of
- // kernel_single_task.
+ // kernel8 and kernel9 - expect no error
+ // Tests that passing a lambda to the unique stable name builtin and passing
+ // it to a kernel called with an if constexpr branch does not cause a
+ // diagnostic on the kernel9 as it does not change the result to the stable
+ // name. This is interesting even though the use of kernel9 happens in the
+ // false branch of a constexpr if because both the true and the false branches
+ // cause the instantiation of kernel_single_task.
auto l9 = []() { return 1; };
auto l10 = []() { return 2; };
constexpr const char *l10_output =
@@ -134,9 +120,6 @@ int main() {
if constexpr (1) {
kernel_single_task<class kernel8>(l9);
} else {
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#USN_l10{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel9>(l10);
}
@@ -151,26 +134,20 @@ int main() {
__builtin_sycl_unique_stable_name(decltype(l11));
kernel_single_task<class kernel11>(l12);
- // kernel12 - expect an error
+ // kernel12 - expect no error
// Test that passing a lambda to the unique stable name builtin and then
- // passing it to the kernel as a template template parameter causes a
+ // passing it to the kernel as a template template parameter does not cause a
// diagnostic on the kernel use due to template template parameter being
// involved in the mangling of the kernel name.
auto l13 = []() { return 1; };
constexpr const char *l13_output =
__builtin_sycl_unique_stable_name(decltype(l13)); // #USN_l13
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#USN_l13{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
kernel_single_task<class kernel12>(S<Tangerine, decltype(l13)>{});
- // kernel13 - expect an error
+ // kernel13 - expect no error
// Test that passing a lambda to the unique stable name builtin within a macro
- // and then calling the macro within the kernel causes an error on the kernel
- // and diagnoses in all the expected places despite the use of a macro.
- // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
- // expected-note@#USN_MACRO{{'__builtin_sycl_unique_stable_name' evaluated here}}
- // expected-note at +1{{in instantiation of function template specialization}}
+ // and then calling the macro within the kernel does not cause an error on the
+ // kernel.
kernel_single_task<class kernel13>(
[]() {
MACRO(); // #USN_MACRO
@@ -213,3 +190,15 @@ void use() {
// expected-note at +1{{in instantiation of}}
f2<St>();
}
+
+// A previous implementation resulted in this being an example of the
+// kernel-ordering and lexical lambda ordering issue.
+void out_of_order_use() {
+ auto x = [](){};
+ auto y = [](){};
+
+ kernel_single_task<decltype(y)>(y);
+ constexpr auto USN =__builtin_sycl_unique_stable_name(decltype(y));
+ (void)USN;
+ kernel_single_task<decltype(x)>(x);
+}
More information about the cfe-commits
mailing list