Skip to content

Commit 5eaa14f

Browse files
author
Erich Keane
authored
[SYCL] Implement __builtin_sycl_unique_id to support spec-constants (#3890)
This works similar to the unique-stable-name implementation, except it instead takes a DeclRefExpr to a VarDecl (with Global Storage!), and produces the mangled name of the variable. For variables without external linkage, it prepends it with the unique identifier passed on the command line from the driver.
1 parent 0666f52 commit 5eaa14f

39 files changed

+788
-82
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,27 @@ their usual pattern without any special treatment.
24522452
// Computes a unique stable name for the given type.
24532453
constexpr const char * __builtin_sycl_unique_stable_name( type-id );
24542454
2455+
``__builtin_sycl_unique_stable_id``
2456+
----------------------------------
2457+
2458+
Like ``__builtin_sycl_unique_stable_name``, this builtin generates a unique and
2459+
stable name as a string literal to support sharing it across split compliations.
2460+
2461+
However, this builtin takes the name of a variable with global storage and
2462+
provides the name for that. In the case of names with internal linkage, it
2463+
prepends an optional value if provided by ``-fsycl-unique-prefix`` on the command
2464+
line, which the driver will do for SYCL invocations.
2465+
2466+
This builtin produces a string that can be demangled, except when its argument has
2467+
internal linkage.
2468+
2469+
**Syntax**:
2470+
2471+
.. code-block:: c++
2472+
2473+
// Computes a unique stable name for a given variable.
2474+
constexpr bool __builtin_sycl_unique_stable_id( expr );
2475+
24552476
``__builtin_sycl_mark_kernel_name``
24562477
-----------------------------------
24572478

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,8 +3175,9 @@ OPT_LIST(V)
31753175
unsigned GetSYCLKernelNamingIndex(const NamedDecl *RD);
31763176
/// A SourceLocation to store whether we have evaluated a kernel name already,
31773177
/// and where it happened. If so, we need to diagnose an illegal use of the
3178-
/// builtin.
3179-
llvm::MapVector<const SYCLUniqueStableNameExpr *, std::string>
3178+
/// builtin. This should only contain SYCLUniqueStableNameExprs and
3179+
/// SYCLUniqueStableIdExprs.
3180+
llvm::MapVector<const Expr *, std::string>
31803181
SYCLUniqueStableNameEvaluatedValues;
31813182

31823183
private:

clang/include/clang/AST/ComputeDependence.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class MaterializeTemporaryExpr;
7878
class CXXFoldExpr;
7979
class TypeTraitExpr;
8080
class ConceptSpecializationExpr;
81+
class SYCLUniqueStableIdExpr;
8182
class SYCLUniqueStableNameExpr;
8283
class PredefinedExpr;
8384
class CallExpr;
@@ -171,6 +172,7 @@ ExprDependence computeDependence(ConceptSpecializationExpr *E,
171172
bool ValueDependent);
172173

173174
ExprDependence computeDependence(SYCLUniqueStableNameExpr *E);
175+
ExprDependence computeDependence(SYCLUniqueStableIdExpr *E);
174176
ExprDependence computeDependence(PredefinedExpr *E);
175177
ExprDependence computeDependence(CallExpr *E, llvm::ArrayRef<Expr *> PreArgs);
176178
ExprDependence computeDependence(OffsetOfExpr *E);

clang/include/clang/AST/Expr.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,58 @@ class SYCLUniqueStableNameExpr final : public Expr {
20972097
static std::string ComputeName(ASTContext &Context, QualType Ty);
20982098
};
20992099

2100+
class SYCLUniqueStableIdExpr final : public Expr {
2101+
friend class ASTStmtReader;
2102+
SourceLocation OpLoc, LParen, RParen;
2103+
// A statement instead of an expression because otherwise implementing
2104+
// 'children' is awkward.
2105+
Stmt *DRE = nullptr;
2106+
2107+
SYCLUniqueStableIdExpr(EmptyShell Empty, QualType ResultTy);
2108+
SYCLUniqueStableIdExpr(SourceLocation OpLoc, SourceLocation LParen,
2109+
SourceLocation RParen, QualType ResultTy, Expr *E);
2110+
2111+
void setExpr(Expr *E) { DRE = E; }
2112+
2113+
void setLocation(SourceLocation L) { OpLoc = L; }
2114+
void setLParenLocation(SourceLocation L) { LParen = L; }
2115+
void setRParenLocation(SourceLocation L) { RParen = L; }
2116+
2117+
public:
2118+
Expr *getExpr() { return cast<Expr>(DRE); }
2119+
const Expr *getExpr() const { return cast<Expr>(DRE); }
2120+
2121+
static SYCLUniqueStableIdExpr *Create(const ASTContext &Ctx,
2122+
SourceLocation OpLoc,
2123+
SourceLocation LParen,
2124+
SourceLocation RParen, Expr *E);
2125+
2126+
static SYCLUniqueStableIdExpr *CreateEmpty(const ASTContext &Ctx);
2127+
2128+
SourceLocation getBeginLoc() const { return getLocation(); }
2129+
SourceLocation getEndLoc() const { return RParen; }
2130+
SourceLocation getLocation() const { return OpLoc; }
2131+
SourceLocation getLParenLocation() const { return LParen; }
2132+
SourceLocation getRParenLocation() const { return RParen; }
2133+
2134+
static bool classof(const Stmt *T) {
2135+
return T->getStmtClass() == SYCLUniqueStableIdExprClass;
2136+
}
2137+
2138+
// Iterators
2139+
child_range children() { return child_range(&DRE, &DRE + 1); }
2140+
const_child_range children() const {
2141+
return const_child_range(&DRE, &DRE + 1);
2142+
}
2143+
2144+
// Convenience function to generate the name of the currently stored type.
2145+
std::string ComputeName(ASTContext &Context) const;
2146+
2147+
// Get the generated name of the type. Note that this only works after all
2148+
// kernels have been instantiated.
2149+
static std::string ComputeName(ASTContext &Context, const VarDecl *VD);
2150+
};
2151+
21002152
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
21012153
/// AST node is only formed if full location information is requested.
21022154
class ParenExpr : public Expr {

clang/include/clang/AST/JSONNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ class JSONNodeDumper
264264

265265
void VisitDeclRefExpr(const DeclRefExpr *DRE);
266266
void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
267+
void VisitSYCLUniqueStableIdExpr(const SYCLUniqueStableIdExpr *E);
267268
void VisitPredefinedExpr(const PredefinedExpr *PE);
268269
void VisitUnaryOperator(const UnaryOperator *UO);
269270
void VisitBinaryOperator(const BinaryOperator *BO);

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,7 @@ DEF_TRAVERSE_STMT(ParenListExpr, {})
26792679
DEF_TRAVERSE_STMT(SYCLUniqueStableNameExpr, {
26802680
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
26812681
})
2682+
DEF_TRAVERSE_STMT(SYCLUniqueStableIdExpr, {})
26822683
DEF_TRAVERSE_STMT(PredefinedExpr, {})
26832684
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
26842685
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ class TextNodeDumper
250250
void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
251251
void VisitDeclRefExpr(const DeclRefExpr *Node);
252252
void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *Node);
253+
void VisitSYCLUniqueStableIdExpr(const SYCLUniqueStableIdExpr *Node);
253254
void VisitPredefinedExpr(const PredefinedExpr *Node);
254255
void VisitCharacterLiteral(const CharacterLiteral *Node);
255256
void VisitIntegerLiteral(const IntegerLiteral *Node);

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6411,9 +6411,13 @@ def warn_gnu_null_ptr_arith : Warning<
64116411
InGroup<NullPointerArithmetic>, DefaultIgnore;
64126412
def err_kernel_invalidates_sycl_unique_stable_name
64136413
: Error<"kernel %select{naming|instantiation}0 changes the result of an "
6414-
"evaluated '__builtin_sycl_unique_stable_name'">;
6414+
"evaluated '__builtin_sycl_unique_stable_%select{name|id}1'">;
64156415
def note_sycl_unique_stable_name_evaluated_here
6416-
: Note<"'__builtin_sycl_unique_stable_name' evaluated here">;
6416+
: Note<"'__builtin_sycl_unique_stable_%select{name|id}0' evaluated here">;
6417+
def err_unique_stable_id_expected_var : Error<"expected variable name">;
6418+
def err_unique_stable_id_global_storage
6419+
: Error<"argument passed to '__builtin_sycl_unique_stable_id' must have "
6420+
"global storage">;
64176421

64186422
def warn_floatingpoint_eq : Warning<
64196423
"comparing floating point with == or != is unsafe">,

clang/include/clang/Basic/StmtNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def CoreturnStmt : StmtNode<Stmt>;
5858
def Expr : StmtNode<ValueStmt, 1>;
5959
def PredefinedExpr : StmtNode<Expr>;
6060
def SYCLUniqueStableNameExpr : StmtNode<Expr>;
61+
def SYCLUniqueStableIdExpr : StmtNode<Expr>;
6162
def DeclRefExpr : StmtNode<Expr>;
6263
def IntegerLiteral : StmtNode<Expr>;
6364
def FixedPointLiteral : StmtNode<Expr>;

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ ALIAS("__char32_t" , char32_t , KEYCXX)
709709
KEYWORD(__builtin_bit_cast , KEYALL)
710710
KEYWORD(__builtin_available , KEYALL)
711711
KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL)
712+
KEYWORD(__builtin_sycl_unique_stable_id , KEYSYCL)
712713

713714
TYPE_TRAIT_1(__builtin_sycl_mark_kernel_name, SYCLMarkKernelName, KEYSYCL)
714715

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,7 @@ class Parser : public CodeCompletionHandler {
18021802
ExprResult ParseUnaryExprOrTypeTraitExpression();
18031803
ExprResult ParseBuiltinPrimaryExpression();
18041804
ExprResult ParseSYCLUniqueStableNameExpression();
1805+
ExprResult ParseSYCLUniqueStableIdExpression();
18051806

18061807
ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
18071808
bool &isCastExpr,

clang/include/clang/Sema/Sema.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5449,6 +5449,13 @@ class Sema final {
54495449
SourceLocation RParen,
54505450
ParsedType ParsedTy);
54515451

5452+
ExprResult BuildSYCLUniqueStableIdExpr(SourceLocation OpLoc,
5453+
SourceLocation LParen,
5454+
SourceLocation RParen, Expr *E);
5455+
ExprResult ActOnSYCLUniqueStableIdExpr(SourceLocation OpLoc,
5456+
SourceLocation LParen,
5457+
SourceLocation RParen, Expr *E);
5458+
54525459
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
54535460

54545461
ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,8 @@ enum StmtCode {
19751975
EXPR_SYCL_BUILTIN_NUM_BASES,
19761976
EXPR_SYCL_BUILTIN_BASE_TYPE,
19771977
EXPR_SYCL_UNIQUE_STABLE_NAME,
1978+
// SYCLUniqueStableIdExpr
1979+
EXPR_SYCL_UNIQUE_STABLE_ID,
19781980
};
19791981

19801982
/// The kinds of designators that can occur in a

clang/lib/AST/ComputeDependence.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,10 @@ ExprDependence clang::computeDependence(SYCLUniqueStableNameExpr *E) {
560560
return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence());
561561
}
562562

563+
ExprDependence clang::computeDependence(SYCLUniqueStableIdExpr *E) {
564+
return E->getExpr()->getDependence();
565+
}
566+
563567
ExprDependence clang::computeDependence(PredefinedExpr *E) {
564568
return toExprDependence(E->getType()->getDependence()) &
565569
~ExprDependence::UnexpandedPack;

clang/lib/AST/Expr.cpp

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -539,26 +539,27 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context) const {
539539
getTypeSourceInfo()->getType());
540540
}
541541

542+
static llvm::Optional<unsigned> SYCLMangleCallback(ASTContext &Ctx,
543+
const NamedDecl *ND) {
544+
// This replaces the 'lambda number' in the mangling with a unique number
545+
// based on its order in the declaration. To provide some level of visual
546+
// notability (actual uniqueness from normal lambdas isn't necessary, as
547+
// these are used differently), we add 10,000 to the number.
548+
// For example:
549+
// _ZTSZ3foovEUlvE10005_
550+
// Demangles to: typeinfo name for foo()::'lambda10005'()
551+
// Note that the mangler subtracts 2, since with normal lambdas the lambda
552+
// mangling number '0' is an anonymous struct mangle, and '1' is omitted.
553+
// So 10,002 results in the first number being 10,000.
554+
if (Ctx.IsSYCLKernelNamingDecl(ND))
555+
return 10'002 + Ctx.GetSYCLKernelNamingIndex(ND);
556+
return llvm::None;
557+
}
558+
542559
std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
543560
QualType Ty) {
544-
auto MangleCallback = [](ASTContext &Ctx,
545-
const NamedDecl *ND) -> llvm::Optional<unsigned> {
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);
558-
return llvm::None;
559-
};
560561
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
561-
Context, Context.getDiagnostics(), MangleCallback)};
562+
Context, Context.getDiagnostics(), SYCLMangleCallback)};
562563

563564
std::string Buffer;
564565
Buffer.reserve(128);
@@ -568,6 +569,60 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
568569
return Out.str();
569570
}
570571

572+
SYCLUniqueStableIdExpr::SYCLUniqueStableIdExpr(EmptyShell Empty,
573+
QualType ResultTy)
574+
: Expr(SYCLUniqueStableIdExprClass, ResultTy, VK_RValue, OK_Ordinary) {}
575+
576+
SYCLUniqueStableIdExpr::SYCLUniqueStableIdExpr(SourceLocation OpLoc,
577+
SourceLocation LParen,
578+
SourceLocation RParen,
579+
QualType ResultTy, Expr *E)
580+
: Expr(SYCLUniqueStableIdExprClass, ResultTy, VK_RValue, OK_Ordinary),
581+
OpLoc(OpLoc), LParen(LParen), RParen(RParen), DRE(E) {
582+
setDependence(computeDependence(this));
583+
}
584+
585+
SYCLUniqueStableIdExpr *SYCLUniqueStableIdExpr::Create(const ASTContext &Ctx,
586+
SourceLocation OpLoc,
587+
SourceLocation LParen,
588+
SourceLocation RParen,
589+
Expr *E) {
590+
QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
591+
return new (Ctx) SYCLUniqueStableIdExpr(OpLoc, LParen, RParen, ResultTy, E);
592+
}
593+
594+
SYCLUniqueStableIdExpr *
595+
SYCLUniqueStableIdExpr::CreateEmpty(const ASTContext &Ctx) {
596+
QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
597+
return new (Ctx) SYCLUniqueStableIdExpr(EmptyShell(), ResultTy);
598+
}
599+
600+
std::string SYCLUniqueStableIdExpr::ComputeName(ASTContext &Context) const {
601+
assert(!isInstantiationDependent() &&
602+
"Can't compute name of uninstantiated value");
603+
604+
auto *DR = cast<DeclRefExpr>(getExpr()->IgnoreUnlessSpelledInSource());
605+
auto *VD = cast<VarDecl>(DR->getDecl());
606+
607+
return ComputeName(Context, VD);
608+
}
609+
610+
std::string SYCLUniqueStableIdExpr::ComputeName(ASTContext &Context,
611+
const VarDecl *VD) {
612+
std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
613+
Context, Context.getDiagnostics(), SYCLMangleCallback)};
614+
615+
std::string Buffer;
616+
Buffer.reserve(128);
617+
llvm::raw_string_ostream Out(Buffer);
618+
Ctx->mangleName(GlobalDecl{VD}, Out);
619+
620+
if (VD->isExternallyVisible())
621+
return Out.str();
622+
623+
return Context.getLangOpts().SYCLUniquePrefix + "___" + Out.str();
624+
}
625+
571626
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
572627
StringLiteral *SL)
573628
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
@@ -3450,6 +3505,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
34503505
case SYCLBuiltinNumBasesExprClass:
34513506
case SYCLBuiltinBaseTypeExprClass:
34523507
case SYCLUniqueStableNameExprClass:
3508+
case SYCLUniqueStableIdExprClass:
34533509
// These never have a side-effect.
34543510
return false;
34553511

clang/lib/AST/ExprClassification.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
438438
case Expr::CoyieldExprClass:
439439
return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
440440
case Expr::SYCLUniqueStableNameExprClass:
441+
case Expr::SYCLUniqueStableIdExprClass:
441442
return Cl::CL_PRValue;
442443
break;
443444
}

clang/lib/AST/ExprConstant.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8689,6 +8689,26 @@ class PointerExprEvaluator
86898689
return true;
86908690
}
86918691

8692+
bool VisitSYCLUniqueStableIdExpr(const SYCLUniqueStableIdExpr *E) {
8693+
std::string ResultStr = E->ComputeName(Info.Ctx);
8694+
8695+
Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
8696+
8697+
QualType CharTy = Info.Ctx.CharTy.withConst();
8698+
APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
8699+
ResultStr.size() + 1);
8700+
QualType ArrayTy = Info.Ctx.getConstantArrayType(CharTy, Size, nullptr,
8701+
ArrayType::Normal, 0);
8702+
8703+
StringLiteral *SL =
8704+
StringLiteral::Create(Info.Ctx, ResultStr, StringLiteral::Ascii,
8705+
/*Pascal*/ false, ArrayTy, E->getLocation());
8706+
8707+
evaluateLValue(SL, Result);
8708+
Result.addArray(Info, E, cast<ConstantArrayType>(ArrayTy));
8709+
return true;
8710+
}
8711+
86928712
// FIXME: Missing: @protocol, @selector
86938713
};
86948714
} // end anonymous namespace
@@ -15190,6 +15210,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
1519015210
case Expr::SYCLBuiltinFieldTypeExprClass:
1519115211
case Expr::SYCLBuiltinBaseTypeExprClass:
1519215212
case Expr::SYCLUniqueStableNameExprClass:
15213+
case Expr::SYCLUniqueStableIdExprClass:
1519315214
return ICEDiag(IK_NotICE, E->getBeginLoc());
1519415215

1519515216
case Expr::InitListExprClass: {

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5056,6 +5056,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
50565056
Out << "E";
50575057
break;
50585058
}
5059+
case Expr::SYCLUniqueStableIdExprClass: {
5060+
const auto *USID = cast<SYCLUniqueStableIdExpr>(E);
5061+
NotPrimaryExpr();
5062+
5063+
Out << "cl31__builtin_sycl_unique_stable_id";
5064+
mangleExpression(USID->getExpr());
5065+
Out << "E";
5066+
break;
5067+
}
50595068
}
50605069

50615070
if (AsTemplateArg && !IsPrimaryExpr)

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,9 @@ void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
11701170
createQualType(E->getTypeSourceInfo()->getType()));
11711171
}
11721172

1173+
void JSONNodeDumper::VisitSYCLUniqueStableIdExpr(
1174+
const SYCLUniqueStableIdExpr *E) {}
1175+
11731176
void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
11741177
JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
11751178
}

0 commit comments

Comments
 (0)