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

[SYCL] Unique stable name rebase #3835

Merged
merged 20 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bd97889
Revert old implementation sans tests
Apr 29, 2021
8347ee4
Reimplement __builtin_unique_stable_name-
Apr 23, 2021
6672484
Correct comment that referred to old name
May 27, 2021
47791c4
Update a bunch of library uses of unique-stable-name to have the corr…
May 27, 2021
8bdd49a
Fix the SYCL-Sema uses
May 27, 2021
eb0b1c3
Fix the sema-sycl tests, which just needed check values updated
May 27, 2021
a723f9a
update unique-stable-name codegen test
May 27, 2021
fa740a5
Fix most of the CodeGenSYCL tests, int_header_sycl2020_spec_const.cpp…
May 27, 2021
e4b4130
Replace 'magic static' with a member variable for SCYL kernel names
May 27, 2021
2c29e59
Add Wno-sycl-2020-compat to test so that it passes with no diagnostics
May 27, 2021
09a07c6
Update buffer-location-codegen test to match the new mangling
May 27, 2021
3a21d47
[SYCL] Instantiate sycl_kernel functions in host compilation
romanovvlad May 6, 2021
72738e0
Add workaround for library-host mode
May 6, 2021
5f82ac6
[SYCL] Use if constexpr instead of enable_if to avoid msvc bug
romanovvlad May 6, 2021
1ccdb17
Fix clang-format
romanovvlad May 6, 2021
255a450
Another clang-format ifx
Jun 1, 2021
45d489e
Disabling issues in 2 tests to hopefully make CI happy
May 6, 2021
8bcd424
[SYCL] Fix __builtin_sycl_unique_stable_name to work on windows/spir
Jun 2, 2021
6c947a9
Merge remote-tracking branch 'SYCL_public/sycl' into unique_stable_na…
Jun 2, 2021
47a130a
Update windows-diff test to force emit of unique-stable-name
Jun 2, 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
48 changes: 29 additions & 19 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,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 @@ -2404,29 +2404,39 @@ argument.
int *pb =__builtin_preserve_access_index(&v->c[3].b);
__builtin_preserve_access_index(v->j);

``__builtin_unique_stable_name``
--------------------------------
``__builtin_sycl_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.
``__builtin_sycl_unique_stable_name()`` is a builtin that takes a type and
produces a string literal containing a unique name for the type that is stable
across split compilations, mainly to support SYCL/Data Parallel C++ language.

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.
for lookup purposes, such as in the SYCL Integration Header.

The value of this builtin is computed entirely at compile time, so it can be
used in constant expressions. This value encodes lambda functions based on a
stable numbering order in which they appear in their local declaration contexts.
Once this builtin is evaluated in a constexpr context, it is erroneous to use
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 different 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
differentiator 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.

**Syntax**:

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.
.. code-block:: c

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.
// Computes a unique stable name for the given type.
constexpr const char * __builtin_sycl_unique_stable_name( type-id );

Multiprecision Arithmetic Builtins
----------------------------------
Expand Down Expand Up @@ -2622,7 +2632,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
28 changes: 28 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class DynTypedNode;
class DynTypedNodeList;
class Expr;
class GlobalDecl;
class ItaniumMangleContext;
class MangleContext;
class MangleNumberingContext;
class MaterializeTemporaryExpr;
Expand Down Expand Up @@ -2360,6 +2361,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// If \p T is null pointer, assume the target in ASTContext.
MangleContext *createMangleContext(const TargetInfo *T = nullptr);

/// Creates a device mangle context to correctly mangle lambdas in a mixed
/// architecture compile by setting the lambda mangling number source to the
/// DeviceLambdaManglingNumber. Currently this asserts that the TargetInfo
/// (from the AuxTargetInfo) is a an itanium target.
MangleContext *createDeviceMangleContext(const TargetInfo &T);

void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const;

Expand Down Expand Up @@ -3163,10 +3170,31 @@ 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.
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 SYCLUniqueStableNameExpr;
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(SYCLUniqueStableNameExpr *E);
ExprDependence computeDependence(PredefinedExpr *E);
ExprDependence computeDependence(CallExpr *E, llvm::ArrayRef<Expr *> PreArgs);
ExprDependence computeDependence(OffsetOfExpr *E);
Expand Down
127 changes: 60 additions & 67 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1948,17 +1948,13 @@ class StringLiteral final
/// [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr final
: public Expr,
private llvm::TrailingObjects<PredefinedExpr, Stmt *, Expr *,
TypeSourceInfo *> {
private llvm::TrailingObjects<PredefinedExpr, Stmt *> {
friend class ASTStmtReader;
friend TrailingObjects;

// PredefinedExpr is optionally followed by a single trailing
// "Stmt *" for the predefined identifier. It is present if and only if
// hasFunctionName() is true and is always a "StringLiteral *".
// It can also be followed by a Expr* in the case of a
// __builtin_unique_stable_name with an expression, or TypeSourceInfo * if
// __builtin_unique_stable_name with a type.

public:
enum IdentKind {
Expand All @@ -1971,18 +1967,12 @@ class PredefinedExpr final
PrettyFunction,
/// The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual,
UniqueStableNameType,
UniqueStableNameExpr,
PrettyFunctionNoVirtual
};

private:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL);
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
TypeSourceInfo *Info);
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
Expr *E);

explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);

Expand All @@ -1995,39 +1985,10 @@ class PredefinedExpr final
*getTrailingObjects<Stmt *>() = SL;
}

void setTypeSourceInfo(TypeSourceInfo *Info) {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
*getTrailingObjects<TypeSourceInfo *>() = Info;
}

void setExpr(Expr *E) {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"TypeSourceInfo only valid for UniqueStableName of n Expression.");
*getTrailingObjects<Expr *>() = E;
}

size_t numTrailingObjects(OverloadToken<Stmt *>) const {
return hasFunctionName();
}

size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
return getIdentKind() == UniqueStableNameType && !hasFunctionName();
}
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getIdentKind() == UniqueStableNameExpr && !hasFunctionName();
}

public:
/// Create a PredefinedExpr.
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK, StringLiteral *SL);
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK, StringLiteral *SL,
TypeSourceInfo *Info);
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK, StringLiteral *SL,
Expr *E);

/// Create an empty PredefinedExpr.
static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
Expand All @@ -2052,38 +2013,12 @@ class PredefinedExpr final
: nullptr;
}

TypeSourceInfo *getTypeSourceInfo() {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return *getTrailingObjects<TypeSourceInfo *>();
}

const TypeSourceInfo *getTypeSourceInfo() const {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return *getTrailingObjects<TypeSourceInfo *>();
}

Expr *getExpr() {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"TypeSourceInfo only valid for UniqueStableName of n Expression.");
return *getTrailingObjects<Expr *>();
}

const Expr *getExpr() const {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"TypeSourceInfo only valid for UniqueStableName of n Expression.");
return *getTrailingObjects<Expr *>();
}

static StringRef getIdentKindName(IdentKind IK);
StringRef getIdentKindName() const {
return getIdentKindName(getIdentKind());
}

static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
static std::string ComputeName(ASTContext &Context, IdentKind IK,
const QualType Ty);

SourceLocation getBeginLoc() const { return getLocation(); }
SourceLocation getEndLoc() const { return getLocation(); }
Expand All @@ -2104,6 +2039,64 @@ class PredefinedExpr final
}
};

// This represents a use of the __builtin_sycl_unique_stable_name, which takes a
// type-id, and at CodeGen time emits a unique string representation of the
// type in a way that permits us to properly encode information about the SYCL
// kernels.
class SYCLUniqueStableNameExpr final : public Expr {
friend class ASTStmtReader;
SourceLocation OpLoc, LParen, RParen;
TypeSourceInfo *TypeInfo;

SYCLUniqueStableNameExpr(EmptyShell Empty, QualType ResultTy);
SYCLUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen,
SourceLocation RParen, QualType ResultTy,
TypeSourceInfo *TSI);

void setTypeSourceInfo(TypeSourceInfo *Ty) { TypeInfo = Ty; }

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

public:
TypeSourceInfo *getTypeSourceInfo() { return TypeInfo; }

const TypeSourceInfo *getTypeSourceInfo() const { return TypeInfo; }

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

static SYCLUniqueStableNameExpr *CreateEmpty(const ASTContext &Ctx);

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() == SYCLUniqueStableNameExprClass;
}

// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}

const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}

// Convenience function to generate the name of the currently stored type.
std::string ComputeName(ASTContext &Context) const;

// Get the generated name of the type. Note that this only works after all
// kernels have been instantiated.
static std::string ComputeName(ASTContext &Context, QualType Ty);
};

/// 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
1 change: 1 addition & 0 deletions clang/include/clang/AST/JSONNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class JSONNodeDumper
void VisitBlockDecl(const BlockDecl *D);

void VisitDeclRefExpr(const DeclRefExpr *DRE);
void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
void VisitPredefinedExpr(const PredefinedExpr *PE);
void VisitUnaryOperator(const UnaryOperator *UO);
void VisitBinaryOperator(const BinaryOperator *BO);
Expand Down
19 changes: 8 additions & 11 deletions clang/include/clang/AST/Mangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,6 @@ class MangleContext {
virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;

virtual bool isDeviceMangleContext() const { return false; }
virtual void setDeviceMangleContext(bool) {}

virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) {
return false;
}
Expand Down Expand Up @@ -172,14 +169,11 @@ class MangleContext {
};

class ItaniumMangleContext : public MangleContext {
bool IsUniqueNameMangler = false;
public:
using DiscriminatorOverrideTy =
llvm::Optional<unsigned> (*)(ASTContext &, const NamedDecl *);
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Itanium) {}
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsUniqueNameMangler)
: MangleContext(C, D, MK_Itanium),
IsUniqueNameMangler(IsUniqueNameMangler) {}

virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
Expand All @@ -200,15 +194,18 @@ class ItaniumMangleContext : public MangleContext {

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

bool isUniqueNameMangler() { return IsUniqueNameMangler; }

// This has to live here, otherwise the CXXNameMangler won't have access to
// it.
virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 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,
bool IsUniqueNameMangler = false);
DiscriminatorOverrideTy Discriminator);
};

class MicrosoftMangleContext : public MangleContext {
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,9 @@ DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
DEF_TRAVERSE_STMT(ObjCAvailabilityCheckExpr, {})
DEF_TRAVERSE_STMT(ParenExpr, {})
DEF_TRAVERSE_STMT(ParenListExpr, {})
DEF_TRAVERSE_STMT(SYCLUniqueStableNameExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(PredefinedExpr, {})
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
Expand Down
Loading