Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique stable name reimpl #307

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 ``~``
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
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
15 changes: 15 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -5176,6 +5176,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:
return ICEDiag(IK_NotICE, E->getBeginLoc());

case Expr::InitListExprClass: {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4069,6 +4069,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
case Expr::CXXInheritedCtorInitExprClass:
case Expr::UniqueStableNameExprClass:
llvm_unreachable("unexpected statement kind");

case Expr::ConstantExprClass:
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,16 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
OS << "]";
}

void StmtPrinter::VisitUniqueStableNameExpr(UniqueStableNameExpr *Node) {
// FIXME: Is this the correct thing?
OS << "__builtin_unique_stable_name(";
if (Node->isExpr())
PrintExpr(Node->getExpr());
else
Node->getTypeSourceInfo()->getType().print(OS, Policy);
OS << ")";
}

void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}
Expand Down
Loading