Skip to content

Commit 27c632e

Browse files
author
Erich Keane
authored
[SYCL] Change unique-stable-name to just use the lambda's mangled name. (#4457)
Currently, whether a lambda is used in a kernel is used to determine the result of `__builtin_sycl_unique_stable_name`.This leads to a sitaution where using a lambda in a kernel that is lexically higher than an existing kernel will change the result of the builtin, causing a build failure. This patch replaces this with JUST the lambda's itanium-mangled name. This has the limitation in that it is not stable/unique in light of certain macro-expansions that differ between device and host, however wording is being put into the SYCL standard to make those cases UB. This DOES have one bit of fallout, which is to make sure that the name on a Windows host does NOT have its lambda mangling 'number', which we are doing by storing the value in the Device Lamba Mangling Number (previously done for CUDA only for similar reasons!). Additionally, this patch removes the 'mark_kernel_name' builtin, as this results in it being a no-op.
1 parent 3c7971d commit 27c632e

26 files changed

+148
-426
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,12 +2521,9 @@ it in an instantiation which changes its value.
25212521
In order to produce the unique name, the current implementation of the bultin
25222522
uses Itanium mangling even if the host compilation uses a different name
25232523
mangling scheme at runtime. The mangler marks all the lambdas required to name
2524-
the SYCL kernel and emits a stable local ordering of the respective lambdas,
2525-
starting from ``10000``. The initial value of ``10000`` serves as an obvious
2526-
differentiator from ordinary lambda mangling numbers but does not serve any
2527-
other purpose and may change in the future. The resulting pattern is
2528-
demanglable. When non-lambda types are passed to the builtin, the mangler emits
2529-
their usual pattern without any special treatment.
2524+
the SYCL kernel and emits a stable local ordering of the respective lambdas.
2525+
The resulting pattern is demanglable. When non-lambda types are passed to the
2526+
builtin, the mangler emits their usual pattern without any special treatment.
25302527
25312528
**Syntax**:
25322529
@@ -2556,30 +2553,6 @@ internal linkage.
25562553
// Computes a unique stable name for a given variable.
25572554
constexpr bool __builtin_sycl_unique_stable_id( expr );
25582555
2559-
``__builtin_sycl_mark_kernel_name``
2560-
-----------------------------------
2561-
2562-
``__builtin_sycl_mark_kernel_name`` is a builtin that can be used with
2563-
``__builtin_sycl_unique_stable_name`` to make sure a kernel is properly 'marked'
2564-
as a kernel without having to instantiate a sycl_kernel function. Typically,
2565-
``__builtin_sycl_unique_stable_name`` can only be called in a constant expression
2566-
context after any kernels that would change the output have been instantiated.
2567-
This is necessary, as changing the answer to the constant expression after
2568-
evaluation isn't permitted. However, in some cases it can be useful to query the
2569-
result of ``__builtin_unique_stable_name`` after we know that the name is a kernel
2570-
name, but before we are able to instantiate the kernel itself (such as when trying
2571-
to decide between two signatures at compile time). In these cases,
2572-
``__builtin_sycl_mark_kernel_name`` can be used to mark the type as a kernel name,
2573-
ensuring that ``__builtin_unique_stable_name`` gives the correct result despite the
2574-
kernel not yet being instantiated.
2575-
2576-
**Syntax**:
2577-
2578-
.. code-block:: c++
2579-
2580-
// Marks a type as the name of a sycl kernel.
2581-
constexpr bool __builtin_sycl_mark_kernel_name( type-id );
2582-
25832556
Multiprecision Arithmetic Builtins
25842557
----------------------------------
25852558

clang/include/clang/AST/ASTContext.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,32 +3238,10 @@ OPT_LIST(V)
32383238

32393239
StringRef getCUIDHash() const;
32403240

3241-
void AddSYCLKernelNamingDecl(const CXXRecordDecl *RD);
3242-
bool IsSYCLKernelNamingDecl(const NamedDecl *RD) const;
3243-
unsigned GetSYCLKernelNamingIndex(const NamedDecl *RD);
3244-
/// A SourceLocation to store whether we have evaluated a kernel name already,
3245-
/// and where it happened. If so, we need to diagnose an illegal use of the
3246-
/// builtin. This should only contain SYCLUniqueStableNameExprs and
3247-
/// SYCLUniqueStableIdExprs.
3248-
llvm::MapVector<const Expr *, std::string>
3249-
SYCLUniqueStableNameEvaluatedValues;
3250-
32513241
private:
32523242
/// All OMPTraitInfo objects live in this collection, one per
32533243
/// `pragma omp [begin] declare variant` directive.
32543244
SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector;
3255-
3256-
/// A list of the (right now just lambda decls) declarations required to
3257-
/// name all the SYCL kernels in the translation unit, so that we can get the
3258-
/// correct kernel name, as well as implement
3259-
/// __builtin_sycl_unique_stable_name.
3260-
llvm::DenseMap<const DeclContext *,
3261-
llvm::SmallPtrSet<const CXXRecordDecl *, 4>>
3262-
SYCLKernelNamingTypes;
3263-
std::unique_ptr<ItaniumMangleContext> SYCLKernelFilterContext;
3264-
void FilterSYCLKernelNamingDecls(
3265-
const CXXRecordDecl *RD,
3266-
llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls);
32673245
};
32683246

32693247
/// Insertion operator for diagnostics.

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6452,11 +6452,6 @@ def warn_gnu_null_ptr_arith : Warning<
64526452
def warn_pointer_sub_null_ptr : Warning<
64536453
"performing pointer subtraction with a null pointer %select{has|may have}0 undefined behavior">,
64546454
InGroup<NullPointerSubtraction>, DefaultIgnore;
6455-
def err_kernel_invalidates_sycl_unique_stable_name
6456-
: Error<"kernel %select{naming|instantiation}0 changes the result of an "
6457-
"evaluated '__builtin_sycl_unique_stable_%select{name|id}1'">;
6458-
def note_sycl_unique_stable_name_evaluated_here
6459-
: Note<"'__builtin_sycl_unique_stable_%select{name|id}0' evaluated here">;
64606455
def err_unique_stable_id_expected_var : Error<"expected variable name">;
64616456
def err_unique_stable_id_global_storage
64626457
: Error<"argument passed to '__builtin_sycl_unique_stable_id' must have "

clang/include/clang/Basic/TokenKinds.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,6 @@ KEYWORD(__builtin_available , KEYALL)
711711
KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL)
712712
KEYWORD(__builtin_sycl_unique_stable_id , KEYSYCL)
713713

714-
TYPE_TRAIT_1(__builtin_sycl_mark_kernel_name, SYCLMarkKernelName, KEYSYCL)
715-
716714
// Clang-specific keywords enabled only in testing.
717715
TESTING_KEYWORD(__unknown_anytype , KEYALL)
718716

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,15 +1094,6 @@ class Sema final {
10941094
OpaqueParser = P;
10951095
}
10961096

1097-
// Marks a type as a SYCL Kernel without necessarily adding it. Additionally,
1098-
// it diagnoses if this causes any of the evaluated
1099-
// __builtin_sycl_unique_stable_name values to change.
1100-
void MarkSYCLKernel(SourceLocation NewLoc, QualType Ty, bool IsInstantiation);
1101-
// Does the work necessary to deal with a SYCL kernel lambda. At the moment,
1102-
// this just marks the list of lambdas required to name the kernel. It does
1103-
// this by dispatching to MarkSYCLKernel, so it also does the diagnostics.
1104-
void AddSYCLKernelLambda(const FunctionDecl *FD);
1105-
11061097
class DelayedDiagnostics;
11071098

11081099
class DelayedDiagnosticsState {

clang/lib/AST/ASTContext.cpp

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11817,86 +11817,3 @@ StringRef ASTContext::getCUIDHash() const {
1181711817
CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
1181811818
return CUIDHash;
1181911819
}
11820-
11821-
// Get the closest named parent, so we can order the sycl naming decls somewhere
11822-
// that mangling is meaningful.
11823-
static const DeclContext *GetNamedParent(const CXXRecordDecl *RD) {
11824-
const DeclContext *DC = RD->getDeclContext();
11825-
11826-
while (!isa<NamedDecl, TranslationUnitDecl>(DC))
11827-
DC = DC->getParent();
11828-
return DC;
11829-
}
11830-
11831-
void ASTContext::AddSYCLKernelNamingDecl(const CXXRecordDecl *RD) {
11832-
assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
11833-
RD = RD->getCanonicalDecl();
11834-
const DeclContext *DC = GetNamedParent(RD);
11835-
11836-
assert(RD->getLocation().isValid() &&
11837-
"Invalid location on kernel naming decl");
11838-
11839-
(void)SYCLKernelNamingTypes[DC].insert(RD);
11840-
}
11841-
11842-
bool ASTContext::IsSYCLKernelNamingDecl(const NamedDecl *ND) const {
11843-
assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
11844-
const auto *RD = dyn_cast<CXXRecordDecl>(ND);
11845-
if (!RD)
11846-
return false;
11847-
RD = RD->getCanonicalDecl();
11848-
const DeclContext *DC = GetNamedParent(RD);
11849-
11850-
auto Itr = SYCLKernelNamingTypes.find(DC);
11851-
11852-
if (Itr == SYCLKernelNamingTypes.end())
11853-
return false;
11854-
11855-
return Itr->getSecond().count(RD);
11856-
}
11857-
11858-
// Filters the Decls list to those that share the lambda mangling with the
11859-
// passed RD.
11860-
void ASTContext::FilterSYCLKernelNamingDecls(
11861-
const CXXRecordDecl *RD,
11862-
llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls) {
11863-
11864-
if (!SYCLKernelFilterContext)
11865-
SYCLKernelFilterContext.reset(
11866-
ItaniumMangleContext::create(*this, getDiagnostics()));
11867-
11868-
llvm::SmallString<128> LambdaSig;
11869-
llvm::raw_svector_ostream Out(LambdaSig);
11870-
SYCLKernelFilterContext->mangleLambdaSig(RD, Out);
11871-
11872-
llvm::erase_if(Decls, [this, &LambdaSig](const CXXRecordDecl *LocalRD) {
11873-
llvm::SmallString<128> LocalLambdaSig;
11874-
llvm::raw_svector_ostream LocalOut(LocalLambdaSig);
11875-
SYCLKernelFilterContext->mangleLambdaSig(LocalRD, LocalOut);
11876-
return LambdaSig != LocalLambdaSig;
11877-
});
11878-
}
11879-
11880-
unsigned ASTContext::GetSYCLKernelNamingIndex(const NamedDecl *ND) {
11881-
assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
11882-
assert(IsSYCLKernelNamingDecl(ND) &&
11883-
"Lambda not involved in mangling asked for a naming index?");
11884-
11885-
const CXXRecordDecl *RD = cast<CXXRecordDecl>(ND)->getCanonicalDecl();
11886-
const DeclContext *DC = GetNamedParent(RD);
11887-
11888-
auto Itr = SYCLKernelNamingTypes.find(DC);
11889-
assert(Itr != SYCLKernelNamingTypes.end() && "Not a valid DeclContext?");
11890-
11891-
const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &Set = Itr->getSecond();
11892-
11893-
llvm::SmallVector<const CXXRecordDecl *> Decls{Set.begin(), Set.end()};
11894-
11895-
FilterSYCLKernelNamingDecls(RD, Decls);
11896-
11897-
llvm::sort(Decls, [](const CXXRecordDecl *LHS, const CXXRecordDecl *RHS) {
11898-
return LHS->getLambdaManglingNumber() < RHS->getLambdaManglingNumber();
11899-
});
11900-
11901-
return llvm::find(Decls, RD) - Decls.begin();
11902-
}

clang/lib/AST/Expr.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -541,27 +541,17 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context) const {
541541
getTypeSourceInfo()->getType());
542542
}
543543

544-
static llvm::Optional<unsigned> SYCLMangleCallback(ASTContext &Ctx,
545-
const NamedDecl *ND) {
546-
// This replaces the 'lambda number' in the mangling with a unique number
547-
// based on its order in the declaration. To provide some level of visual
548-
// notability (actual uniqueness from normal lambdas isn't necessary, as
549-
// these are used differently), we add 10,000 to the number.
550-
// For example:
551-
// _ZTSZ3foovEUlvE10005_
552-
// Demangles to: typeinfo name for foo()::'lambda10005'()
553-
// Note that the mangler subtracts 2, since with normal lambdas the lambda
554-
// mangling number '0' is an anonymous struct mangle, and '1' is omitted.
555-
// So 10,002 results in the first number being 10,000.
556-
if (Ctx.IsSYCLKernelNamingDecl(ND))
557-
return 10'002 + Ctx.GetSYCLKernelNamingIndex(ND);
544+
static llvm::Optional<unsigned>
545+
UniqueStableNameDiscriminator(ASTContext &, const NamedDecl *ND) {
546+
if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
547+
return RD->getDeviceLambdaManglingNumber();
558548
return llvm::None;
559549
}
560550

561551
std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
562552
QualType Ty) {
563553
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
564-
Context, Context.getDiagnostics(), SYCLMangleCallback)};
554+
Context, Context.getDiagnostics(), UniqueStableNameDiscriminator)};
565555

566556
std::string Buffer;
567557
Buffer.reserve(128);
@@ -612,7 +602,7 @@ std::string SYCLUniqueStableIdExpr::ComputeName(ASTContext &Context) const {
612602
std::string SYCLUniqueStableIdExpr::ComputeName(ASTContext &Context,
613603
const VarDecl *VD) {
614604
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
615-
Context, Context.getDiagnostics(), SYCLMangleCallback)};
605+
Context, Context.getDiagnostics(), UniqueStableNameDiscriminator)};
616606

617607
std::string Buffer;
618608
Buffer.reserve(128);

clang/lib/AST/ExprConstant.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8674,8 +8674,6 @@ class PointerExprEvaluator
86748674
bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E) {
86758675
std::string ResultStr = E->ComputeName(Info.Ctx);
86768676

8677-
Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
8678-
86798677
QualType CharTy = Info.Ctx.CharTy.withConst();
86808678
APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
86818679
ResultStr.size() + 1);
@@ -8694,8 +8692,6 @@ class PointerExprEvaluator
86948692
bool VisitSYCLUniqueStableIdExpr(const SYCLUniqueStableIdExpr *E) {
86958693
std::string ResultStr = E->ComputeName(Info.Ctx);
86968694

8697-
Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
8698-
86998695
QualType CharTy = Info.Ctx.CharTy.withConst();
87008696
APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
87018697
ResultStr.size() + 1);

clang/lib/AST/ItaniumCXXABI.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,37 @@ class ItaniumNumberingContext : public MangleNumberingContext {
181181
}
182182
};
183183

184+
// A version of this for SYCL that makes sure that 'device' mangling context
185+
// matches the lambda mangling number, so that __builtin_sycl_unique_stable_name
186+
// can be consistently generated between a MS and Itanium host by just referring
187+
// to the device mangling number.
188+
class ItaniumSYCLNumberingContext : public ItaniumNumberingContext {
189+
llvm::DenseMap<const CXXMethodDecl *, unsigned> ManglingNumbers;
190+
using ManglingItr = decltype(ManglingNumbers)::iterator;
191+
192+
public:
193+
ItaniumSYCLNumberingContext(ItaniumMangleContext *Mangler)
194+
: ItaniumNumberingContext(Mangler) {}
195+
196+
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
197+
unsigned Number = ItaniumNumberingContext::getManglingNumber(CallOperator);
198+
std::pair<ManglingItr, bool> emplace_result =
199+
ManglingNumbers.try_emplace(CallOperator, Number);
200+
(void)emplace_result;
201+
assert(emplace_result.second && "Lambda number set multiple times?");
202+
return Number;
203+
}
204+
205+
using ItaniumNumberingContext::getManglingNumber;
206+
207+
unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
208+
ManglingItr Itr = ManglingNumbers.find(CallOperator);
209+
assert(Itr != ManglingNumbers.end() && "Lambda not yet mangled?");
210+
211+
return Itr->second;
212+
}
213+
};
214+
184215
class ItaniumCXXABI : public CXXABI {
185216
private:
186217
std::unique_ptr<MangleContext> Mangler;
@@ -249,6 +280,9 @@ class ItaniumCXXABI : public CXXABI {
249280

250281
std::unique_ptr<MangleNumberingContext>
251282
createMangleNumberingContext() const override {
283+
if (Context.getLangOpts().isSYCL())
284+
return std::make_unique<ItaniumSYCLNumberingContext>(
285+
cast<ItaniumMangleContext>(Mangler.get()));
252286
return std::make_unique<ItaniumNumberingContext>(
253287
cast<ItaniumMangleContext>(Mangler.get()));
254288
}

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,9 +1518,16 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
15181518
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
15191519
// # Parameter types or 'v' for 'void'.
15201520
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
1521-
if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
1522-
Context.getDiscriminatorOverride()(
1523-
Context.getASTContext(), Record))) {
1521+
llvm::Optional<unsigned> DeviceNumber =
1522+
Context.getDiscriminatorOverride()(Context.getASTContext(), Record);
1523+
1524+
// If we have a device-number via the discriminator, use that to mangle
1525+
// the lambda, otherwise use the typical lambda-mangling-number. In either
1526+
// case, a '0' should be mangled as a normal unnamed class instead of as a
1527+
// lambda.
1528+
if (Record->isLambda() &&
1529+
((DeviceNumber && *DeviceNumber > 0) ||
1530+
(!DeviceNumber && Record->getLambdaManglingNumber() > 0))) {
15241531
assert(!AdditionalAbiTags &&
15251532
"Lambda type cannot have additional abi tags");
15261533
mangleLambda(Record);
@@ -1960,8 +1967,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
19601967
// mangling number for this lambda.
19611968
llvm::Optional<unsigned> DeviceNumber =
19621969
Context.getDiscriminatorOverride()(Context.getASTContext(), Lambda);
1963-
unsigned Number = DeviceNumber.hasValue() ? *DeviceNumber
1964-
: Lambda->getLambdaManglingNumber();
1970+
unsigned Number =
1971+
DeviceNumber ? *DeviceNumber : Lambda->getLambdaManglingNumber();
19651972

19661973
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
19671974
if (Number > 1)

clang/lib/AST/MicrosoftCXXABI.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ class MSHIPNumberingContext : public MicrosoftNumberingContext {
7878
}
7979
};
8080

81+
class MSSYCLNumberingContext : public MicrosoftNumberingContext {
82+
std::unique_ptr<MangleNumberingContext> DeviceCtx;
83+
84+
public:
85+
MSSYCLNumberingContext(MangleContext *DeviceMangler) {
86+
DeviceCtx = createItaniumNumberingContext(DeviceMangler);
87+
}
88+
89+
unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override {
90+
return DeviceCtx->getManglingNumber(CallOperator);
91+
}
92+
};
93+
8194
class MicrosoftCXXABI : public CXXABI {
8295
ASTContext &Context;
8396
llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
@@ -99,6 +112,9 @@ class MicrosoftCXXABI : public CXXABI {
99112
"Unexpected combination of C++ ABIs.");
100113
DeviceMangler.reset(
101114
Context.createMangleContext(Context.getAuxTargetInfo()));
115+
} else if (Context.getLangOpts().isSYCL()) {
116+
DeviceMangler.reset(
117+
ItaniumMangleContext::create(Context, Context.getDiagnostics()));
102118
}
103119
}
104120

@@ -162,6 +178,9 @@ class MicrosoftCXXABI : public CXXABI {
162178
if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) {
163179
assert(DeviceMangler && "Missing device mangler");
164180
return std::make_unique<MSHIPNumberingContext>(DeviceMangler.get());
181+
} else if (Context.getLangOpts().isSYCL()) {
182+
assert(DeviceMangler && "Missing device mangler");
183+
return std::make_unique<MSSYCLNumberingContext>(DeviceMangler.get());
165184
}
166185
return std::make_unique<MicrosoftNumberingContext>();
167186
}

clang/lib/Parse/ParseExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,6 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
893893
/// [Clang] unary-type-trait:
894894
/// '__is_aggregate'
895895
/// '__trivially_copyable'
896-
/// '__builtin_sycl_mark_kernel_name'
897896
///
898897
/// binary-type-trait:
899898
/// [GNU] '__is_base_of'

0 commit comments

Comments
 (0)