Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
8c2e149
Add infrastructure for where to run the 'mark' stage of the mangler
Apr 23, 2021
e6b6534
Add lang extension documentation
Apr 23, 2021
f3dffdd
Add builtin as keyword + add parsing code... won't link until we
Apr 23, 2021
5a2780b
Started by trying to implement the 'Build' functions, which requried an
Apr 23, 2021
8f637d8
Add ItaniumMangleContext infrastructure, still need to have it modify…
Apr 23, 2021
355ecc4
Revert unwanted changes from LangExtensions, fix issues aaron mentioned
Apr 26, 2021
acd6f9d
ACTUALLY fix the things aaron suggested
Apr 26, 2021
ba8491a
Implement Codegen for this, not including the modified mangled name
Apr 26, 2021
7358177
Move codegen time name computation into the type so that is accessibl…
Apr 26, 2021
2975b68
TemplateInstantiator doesn't need special handling, remove it so that…
Apr 26, 2021
17339c1
Require a complete type
Apr 26, 2021
0affc56
Add kernel naming structure and at least the beginning of where the C…
Apr 26, 2021
7bc6b92
Remove a pair of TODOs, I couldn't get to the mangling attempt, and t…
Apr 27, 2021
c55e53e
A little work trying to get mangling right, apparently our 'kernel la…
Apr 27, 2021
e74bc41
Add some level of mangling to the lambdas
Apr 28, 2021
bcd0493
Change the callback behavior to include 2 callbacks.
Apr 28, 2021
5c5f66e
Fix things aaron noticed
Apr 29, 2021
7e7552d
Remove some TODOs, implement a numbering mechanism that provides uniq…
Apr 29, 2021
55bb855
Move this expression to CXCursor_UnexposedExpr
Apr 29, 2021
4ad8f83
Move calc name function to a static function so it can be used in the…
Apr 29, 2021
43e51b7
Fix spelling issue, plus fix out of line decl
Apr 29, 2021
ef6ba73
Stop assuming that kernel callees are lambdas/functors, function poin…
Apr 30, 2021
3bb78fe
Change the way we do our codegen-
Apr 30, 2021
f934e00
Re-apply the placeholder-expr crash fix.
Apr 30, 2021
099df82
Correct the codegen behavior ot correctly generate a global of the co…
Apr 30, 2021
1df6b08
clang-format fixes
Apr 30, 2021
0fbaef5
Make ComputeName a const member
May 4, 2021
4718a96
Implement constexpr for builtin-stable-name
May 4, 2021
48e3a92
A less-invasive version of the constexpr checking, to see if CI would…
May 4, 2021
c9295c2
Remove 'must be complete' restriction in case that allows us to work
May 4, 2021
0779772
Clang--format fixes
May 6, 2021
89c7b70
Change operating type from TagDecl to CXXRecordDecl.
May 10, 2021
8d8db2a
Fix diagnostics on subsequent kernels re-identifying the same change.
May 10, 2021
0ff40f9
Add tests
schittir May 4, 2021
4c53337
Add more tests
schittir May 6, 2021
3e06737
Edit builtin documentation
schittir May 11, 2021
81b49f8
Edit documentation per review comments
schittir May 11, 2021
9993946
Fix typos per Aaron's review
schittir May 12, 2021
6c01690
Update doc with Aaron's feedback on non-lambda types
schittir May 13, 2021
e2ae208
Changing text per Aaron's suggestion
schittir May 13, 2021
be023e8
Add SemaSYCL tests
schittir May 13, 2021
9ebbc6c
Add more tests
schittir May 14, 2021
9b0b1be
Add single quotes around builtin name in diagnostics
May 14, 2021
71c0cc7
Implement mangling of this so that we correctly handle the trailing r…
May 14, 2021
a13ec99
Add back spurrious whitespace, remove unnecessary cast to void
May 14, 2021
c73731b
Merge remote-tracking branch 'origin/unique_stable_name_reimpl' into …
schittir May 14, 2021
6840213
Edit parsing test per review comments
schittir May 14, 2021
a8867d4
Changing test case now that mangling for trailing types is implemented
schittir May 14, 2021
375e87d
Fix minor issues because lit test failed
schittir May 14, 2021
764a4b0
Add another test case per Aaron's suggestion and fix ifconstexpr case
schittir May 15, 2021
0ec2d07
Group cases that trigger errors in a separate section
schittir May 15, 2021
8ddd3a9
Add number markers to diagnostics
schittir May 18, 2021
821dbb6
Correct lambda mangling numbering, which should make this deterministic.
May 18, 2021
c636401
Merge remote-tracking branch 'origin/unique_stable_name_reimpl' into …
schittir May 18, 2021
52862e8
Adding kernelSingleTask bookmark and cleaning up some comments
schittir May 18, 2021
874d44f
Minor change - add space
schittir May 18, 2021
68ec935
Make sure we diagnose ALL builtin changes, so that we dont' get weird…
May 18, 2021
e5ac8fc
Merge remote-tracking branch 'origin/unique_stable_name_reimpl' into …
schittir May 18, 2021
96bb440
Add more CodeGen tests including TODO and FIXMEs, and address review …
schittir May 19, 2021
a08a5ac
Add SemaSYCL test cases and address review comments
schittir May 19, 2021
195218a
Fix null-terminated strings, make sure buffer is being flushed
May 19, 2021
bdffe7e
Add bookmarks to notes
schittir May 19, 2021
b2584b2
Merge remote-tracking branch 'origin/unique_stable_name_reimpl' into …
schittir May 19, 2021
53a414b
Move CHECK strings around per Erich's review
schittir May 19, 2021
41ffe76
Add two cases per Aaron's suggestion
schittir May 19, 2021
4fa5e27
Update SemaSYCL test comments
schittir May 19, 2021
5b0018e
Moved CHECK lines per new comments
schittir May 20, 2021
ad7eadb
Update comments and diagnostics in SemaSYCL test
schittir May 20, 2021
bf909b0
Make sure we filter the list of decls for the purpose of the number b…
May 20, 2021
10643c8
Merge remote-tracking branch 'origin/unique_stable_name_reimpl' into …
schittir May 20, 2021
07c5fbd
Add and move around CHECK lines per Erich's comments
schittir May 21, 2021
8e56614
Minor change to address review comment
schittir May 24, 2021
5bc1061
Reorganize SemaSYCL test and change diagnostic messages accordingly
schittir May 25, 2021
3e19ec4
Minor edits and fixing typos
schittir May 25, 2021
e2edc31
Change comments per Aaron's review and minor fixes
schittir May 25, 2021
5003b2b
Minor change - number the kernel calls and lambdas in (mostly) textua…
schittir May 25, 2021
dbada48
Address the remaining review comments
schittir May 25, 2021
8fd77bd
Change comments per review - catching the remaining things
schittir May 25, 2021
4be1a00
Unique stable name tests
May 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ correctly in any circumstances. It can be used if:
metaprogramming algorithms to be able to specify/detect types generically.

- the generated kernel binary does not contain indirect calls because they
are eliminated using compiler optimizations e.g. devirtualization.
are eliminated using compiler optimizations e.g. devirtualization.

- the selected target supports the function pointer like functionality e.g.
most CPU targets.
Expand Down Expand Up @@ -2311,6 +2311,30 @@ argument.
int *pb =__builtin_preserve_access_index(&v->c[3].b);
__builtin_preserve_access_index(v->j);

``__builtin_unique_stable_name``
------------------------

``__builtin_unique_stable_name()`` is a builtin that takes a type or expression and
produces a string literal containing a unique name for the type (or type of the
expression) that is stable across split compilations.

In cases where the split compilation needs to share a unique token for a type
across the boundary (such as in an offloading situation), this name can be used
for lookup purposes.

This builtin is superior to RTTI for this purpose for two reasons. First, this
value is computed entirely at compile time, so it can be used in constant
expressions. Second, this value encodes lambda functions based on line-number
rather than the order in which it appears in a function. This is valuable
because it is stable in cases where an unrelated lambda is introduced
conditionally in the same function.

The current implementation of this builtin uses a slightly modified Itanium
Mangler to produce the unique name. The lambda ordinal is replaced with one or
more line/column pairs in the format ``LINE->COL``, separated with a ``~``

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erichkeane - Just noticed that this is the description for the old mangling format. Could you please update it?
Commenting here in case it escaped your attention too.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd forgotten about that, thanks. I'm doing a bunch of other stuff on this patch as well right now, but it would probably be a good learning opportunity for you to write this up so we can review/fill in the gaps. Please submit a PR when you get a chance. Tests are more important obviously, but this needs to happen next week as well.

character. Typically, only one pair will be included, however in the case of
macro expansions the entire macro expansion stack is expressed.

Multiprecision Arithmetic Builtins
----------------------------------

Expand Down Expand Up @@ -2505,7 +2529,7 @@ Guaranteed inlined copy
``__builtin_memcpy_inline`` has been designed as a building block for efficient
``memcpy`` implementations. It is identical to ``__builtin_memcpy`` but also
guarantees not to call any external functions. See LLVM IR `llvm.memcpy.inline
<https://llvm.org/docs/LangRef.html#llvm-memcpy-inline-intrinsic>`_ intrinsic
<https://llvm.org/docs/LangRef.html#llvm-memcpy-inline-intrinsic>`_ intrinsic
for more information.

This is useful to implement a custom version of ``memcpy``, implement a
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/ComputeDependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class MaterializeTemporaryExpr;
class CXXFoldExpr;
class TypeTraitExpr;
class ConceptSpecializationExpr;
class UniqueStableNameExpr;
class PredefinedExpr;
class CallExpr;
class OffsetOfExpr;
Expand Down Expand Up @@ -165,6 +166,7 @@ ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);

ExprDependence computeDependence(UniqueStableNameExpr *E);
ExprDependence computeDependence(PredefinedExpr *E);
ExprDependence computeDependence(CallExpr *E, llvm::ArrayRef<Expr *> PreArgs);
ExprDependence computeDependence(OffsetOfExpr *E);
Expand Down
106 changes: 106 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,112 @@ class PredefinedExpr final
}
};

// This represents a use of the __builtin_unique_stable_name, which takes either
// a type-id or an expression, and at CodeGen time emits a unique string
// representation of the type (or type of the expression) in a way that permits
// us to properly encode information about the SYCL Kernels.
class UniqueStableNameExpr final
: public Expr,
private llvm::TrailingObjects<UniqueStableNameExpr, Stmt *,
TypeSourceInfo *> {
friend class ASTStmtReader;
friend TrailingObjects;
SourceLocation OpLoc, LParen, RParen;
// Note: We store a Stmt* instead of the Expr* so that we can implement
// 'children'.
enum class ParamKind { Type, Expr };
ParamKind Kind;

UniqueStableNameExpr(EmptyShell Empty, QualType ResultTy, bool IsExpr);
UniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen,
SourceLocation RParen, QualType ResultTy,
TypeSourceInfo *TSI);
UniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen,
SourceLocation RParen, QualType ResultTy, Expr *E);

size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
return Kind == ParamKind::Type ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<Stmt *>) const {
return Kind == ParamKind::Expr ? 1 : 0;
}
void setTypeSourceInfo(TypeSourceInfo *Ty) {
assert(Kind == ParamKind::Type &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
*getTrailingObjects<TypeSourceInfo *>() = Ty;
}
void setExpr(Expr *E) {
assert(Kind == ParamKind::Expr &&
"Expr only valid for UniqueStableName of an Expr");
assert(E->isInstantiationDependent() &&
"Expr type only valid if the expr is dependent");
*getTrailingObjects<Stmt *>() = E;
}

void setLocation(SourceLocation L) { OpLoc = L; }
void setLParenLocation(SourceLocation L) { LParen = L; }
void setRParenLocation(SourceLocation L) { RParen = L; }

public:
TypeSourceInfo *getTypeSourceInfo() {
assert(Kind == ParamKind::Type &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return *getTrailingObjects<TypeSourceInfo *>();
}

const TypeSourceInfo *getTypeSourceInfo() const {
assert(Kind == ParamKind::Type &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return *getTrailingObjects<TypeSourceInfo *>();
}

Expr *getExpr() {
assert(Kind == ParamKind::Expr &&
"Expr only valid for UniqueStableName of an Expr");
return static_cast<Expr *>(*getTrailingObjects<Stmt *>());
}

const Expr *getExpr() const {
assert(Kind == ParamKind::Expr &&
"Expr only valid for UniqueStableName of an Expr");
return static_cast<Expr *>(*getTrailingObjects<Stmt *>());
}

bool isExpr() const { return Kind == ParamKind::Expr; }

bool isTypeSourceInfo() const { return Kind == ParamKind::Type; }

static UniqueStableNameExpr *
Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen,
SourceLocation RParen, TypeSourceInfo *TSI);

static UniqueStableNameExpr *Create(const ASTContext &Ctx,
SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen, Expr *E);
static UniqueStableNameExpr *CreateEmpty(const ASTContext &Ctx, bool IsExpr);

SourceLocation getBeginLoc() const { return getLocation(); }
SourceLocation getEndLoc() const { return RParen; }
SourceLocation getLocation() const { return OpLoc; }
SourceLocation getLParenLocation() const { return LParen; }
SourceLocation getRParenLocation() const { return RParen; }

static bool classof(const Stmt *T) {
return T->getStmtClass() == UniqueStableNameExprClass;
}

// Iterators
child_range children() {
return child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + isExpr());
}
const_child_range children() const {
return const_child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + isExpr());
}
};

/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/AST/Mangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class MangleContext {

class ItaniumMangleContext : public MangleContext {
public:
// TODO: ERICH: this is obviously not going to be sufficient, type will change
// during dev.
using KernelMangleCallbackTy = void (*)();
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Itanium) {}

Expand All @@ -195,12 +198,21 @@ class ItaniumMangleContext : public MangleContext {

virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;

// This seemingly has to live here, otherwise the CXXNameMangler won't have
// access to it.
virtual KernelMangleCallbackTy getKernelMangleCallback() = 0;

static bool classof(const MangleContext *C) {
return C->getKind() == MK_Itanium;
}

static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags,
KernelMangleCallbackTy Callback);

private:
};

class MicrosoftMangleContext : public MangleContext {
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2636,6 +2636,12 @@ DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
DEF_TRAVERSE_STMT(ObjCAvailabilityCheckExpr, {})
DEF_TRAVERSE_STMT(ParenExpr, {})
DEF_TRAVERSE_STMT(ParenListExpr, {})
DEF_TRAVERSE_STMT(UniqueStableNameExpr, {
if (S->isExpr())
TRY_TO(TraverseStmt(S->getExpr()));
else
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(PredefinedExpr, {})
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def CoreturnStmt : StmtNode<Stmt>;
// Expressions
def Expr : StmtNode<ValueStmt, 1>;
def PredefinedExpr : StmtNode<Expr>;
def UniqueStableNameExpr : StmtNode<Expr>;
def DeclRefExpr : StmtNode<Expr>;
def IntegerLiteral : StmtNode<Expr>;
def FixedPointLiteral : StmtNode<Expr>;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ ALIAS("__char16_t" , char16_t , KEYCXX)
ALIAS("__char32_t" , char32_t , KEYCXX)
KEYWORD(__builtin_bit_cast , KEYALL)
KEYWORD(__builtin_available , KEYALL)
KEYWORD(__builtin_unique_stable_name, KEYALL)

// Clang-specific keywords enabled only in testing.
TESTING_KEYWORD(__unknown_anytype , KEYALL)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,7 @@ class Parser : public CodeCompletionHandler {
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseUnaryExprOrTypeTraitExpression();
ExprResult ParseBuiltinPrimaryExpression();
ExprResult ParseUniqueStableNameExpression();

ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
bool &isCastExpr,
Expand Down
19 changes: 19 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,10 @@ 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 {
Expand Down Expand Up @@ -5176,6 +5180,21 @@ class Sema final {
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);

ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI);
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen, Expr *E);
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
ParsedType ParsedTy);
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen, Expr *Operand);

bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);

ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,9 @@ enum StmtCode {

// FixedPointLiteral
EXPR_FIXEDPOINT_LITERAL,

// UniqueStableNameExpr
EXPR_UNIQUESTABLENAME,
};

/// The kinds of designators that can occur in a
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,12 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) {
return D;
}

ExprDependence clang::computeDependence(UniqueStableNameExpr *E) {
if (E->isExpr())
return E->getExpr()->getDependence();
return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence());
}

ExprDependence clang::computeDependence(PredefinedExpr *E) {
return toExprDependence(E->getType()->getDependence()) &
~ExprDependence::UnexpandedPack;
Expand Down
63 changes: 63 additions & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,68 @@ SourceLocation DeclRefExpr::getEndLoc() const {
return getNameInfo().getEndLoc();
}

UniqueStableNameExpr::UniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
QualType ResultTy,
TypeSourceInfo *TSI)
: Expr(UniqueStableNameExprClass, ResultTy, VK_LValue, OK_Ordinary),
OpLoc(OpLoc), LParen(LParen), RParen(RParen), Kind(ParamKind::Type) {
setTypeSourceInfo(TSI);
// Fixme: Do we have to do anything to make this work?
setDependence(computeDependence(this));
}

UniqueStableNameExpr::UniqueStableNameExpr(EmptyShell Empty, QualType ResultTy,
bool IsExpr)
: Expr(UniqueStableNameExprClass, ResultTy, VK_LValue, OK_Ordinary) {
Kind = IsExpr ? ParamKind::Expr : ParamKind::Expr;
}

UniqueStableNameExpr::UniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
QualType ResultTy, Expr *E)
: Expr(UniqueStableNameExprClass, ResultTy, VK_LValue, OK_Ordinary),
OpLoc(OpLoc), LParen(LParen), RParen(RParen), Kind(ParamKind::Expr) {
setExpr(E);
setDependence(computeDependence(this));
}

UniqueStableNameExpr *UniqueStableNameExpr::Create(const ASTContext &Ctx,
SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
Expr *E) {
assert(E->isInstantiationDependent() &&
"Expr type only valid if the expr is dependent");
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, TypeSourceInfo *>(1, 0),
alignof(UniqueStableNameExpr));

QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
return new (Mem) UniqueStableNameExpr(OpLoc, LParen, RParen, ResultTy, E);
}

UniqueStableNameExpr *UniqueStableNameExpr::Create(const ASTContext &Ctx,
SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI) {
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *, TypeSourceInfo *>(1, 0),
alignof(UniqueStableNameExpr));
QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
return new (Mem) UniqueStableNameExpr(OpLoc, LParen, RParen, ResultTy, TSI);
}

UniqueStableNameExpr *UniqueStableNameExpr::CreateEmpty(const ASTContext &Ctx,
bool IsExpr) {
void *Mem =
Ctx.Allocate(totalSizeToAlloc<Stmt *, TypeSourceInfo *>(IsExpr, !IsExpr),
alignof(UniqueStableNameExpr));
QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
return new (Mem) UniqueStableNameExpr(EmptyShell(), ResultTy, IsExpr);
}

PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
Expand Down Expand Up @@ -3308,6 +3370,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case SourceLocExprClass:
case ConceptSpecializationExprClass:
case RequiresExprClass:
case UniqueStableNameExprClass:
// These never have a side-effect.
return false;

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CoawaitExprClass:
case Expr::CoyieldExprClass:
return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
case Expr::UniqueStableNameExprClass:
// TODO: ERICH! Figure out how to handle this.
break;
}

llvm_unreachable("unhandled expression kind in classification");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15154,6 +15154,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CoawaitExprClass:
case Expr::DependentCoawaitExprClass:
case Expr::CoyieldExprClass:
case Expr::UniqueStableNameExprClass:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is correct, but we should have some constexpr tests to make sure this works in constant expression evaluations. e.g., it would probably be useful to be able to write static_assert(std::string(__builtin_unique_stable_name(whatever)) == "foo");

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that static assert actually wouldn't work for 2 reasons: 1- its a std::string, which isn't constexpr yet :) But more importantly, #2, the value of __builtin_unique_stable_name isn't calculable until we are 'after' constexpr evaluation. Basically, we have to see every template instantiation (and thus the entire TU evaluated) before we can actually 'know' the name. Otherwise lambda numbers are going to be 'off'.

The previous version didn't need the knowledge of the entire TU (that is, of every lambda required to name a kernel) to calculate it, so it worked as a constant expression.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://en.cppreference.com/w/cpp/string/basic_string/basic_string sure make it seem like it is constexpr since C++20 (see signature llvm#5)

However, the point about having to do this after constant evaluation time is interesting. I'll have to think on that a bit, but IIRC, there were some comments in the review that made me think constexpr was expected to work (so we may need a pass to make sure those comments get corrected).

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh, neat! Didn't realize they'd gotten to string for 20, much industrious LEWG/LWG!

Not sure what comments you mean, but we'll have to discuss it at that point I think. Thinking further, I hope the lack of constexpr doesn't break some of our use cases.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@romanovvlad : Can you comment on this? Do we need constexpr evaluation for this builtin?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erichkeane
Do not see why it would be necessary from the functional point of view.
On the other hand this can change the pattern which SpecConstants pass should recognize.
@vmaksimo Could you please tell if it's OK for the pass?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not see why it would be necessary from the functional point of view.

I also can't think of a point where at DPC++ level constexpr matters here

On the other hand this can change the pattern which SpecConstants pass should recognize.

I'm not exactly sure here - I assume that it would be the same string literal as it is now, which will be located in a global variable and references through some load/stores/geps/addrspacecasts.
It is hard to say without an LLVM IR example

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constexprness means you couldn't use the builtin in a constexpr function, and you couldn't use the result of it as a template. We were just making sure that is OK.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g., the static_assert example I gave above would fail to compile (rather than perform the check and then potentially fail). That was about the only useful case I could think of, and it seems reasonable to not support it until someone needs it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schittir -- the static_assert example would be a good one to add to the new test cases as well.

return ICEDiag(IK_NotICE, E->getBeginLoc());

case Expr::InitListExprClass: {
Expand Down
Loading