Skip to content

Revert "[HLSL] Add implicit resource element type concepts to AST" #116305

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

Merged
merged 1 commit into from
Nov 15, 2024
Merged
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
217 changes: 12 additions & 205 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,8 @@ struct BuiltinTypeDeclBuilder {
}

TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
BuiltinTypeDeclBuilder &
addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S,
ArrayRef<StringRef> Names);
};

struct TemplateParameterListBuilder {
Expand All @@ -313,129 +312,30 @@ struct TemplateParameterListBuilder {
S.Context, Builder.Record->getDeclContext(), SourceLocation(),
SourceLocation(), /* TemplateDepth */ 0, Position,
&S.Context.Idents.get(Name, tok::TokenKind::identifier),
/* Typename */ true,
/* ParameterPack */ false,
/* HasTypeConstraint*/ false);
/* Typename */ false,
/* ParameterPack */ false);
if (!DefaultValue.isNull())
Decl->setDefaultArgument(
S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
SourceLocation()));

Params.emplace_back(Decl);
return *this;
}

/*
The concept specialization expression (CSE) constructed in
constructConceptSpecializationExpr is constructed so that it
matches the CSE that is constructed when parsing the below C++ code:

template<typename T>
concept is_typed_resource_element_compatible = sizeof(T) <= 16;

template<typename element_type> requires
is_typed_resource_element_compatible<element_type>
struct RWBuffer {
element_type Val;
};

int fn() {
RWBuffer<int> Buf;
}

When dumping the AST and filtering for "RWBuffer", the resulting AST
structure is what we're trying to construct below, specifically the
CSE portion.
*/
ConceptSpecializationExpr *
constructConceptSpecializationExpr(Sema &S, ConceptDecl *CD) {
ASTContext &Context = S.getASTContext();
SourceLocation Loc = Builder.Record->getBeginLoc();
DeclarationNameInfo DNI(CD->getDeclName(), Loc);
NestedNameSpecifierLoc NNSLoc;
DeclContext *DC = Builder.Record->getDeclContext();
TemplateArgumentListInfo TALI(Loc, Loc);

// Assume that the concept decl has just one template parameter
// This parameter should have been added when CD was constructed
// in getTypedBufferConceptDecl
assert(CD->getTemplateParameters()->size() == 1 &&
"unexpected concept decl parameter count");
TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
CD->getTemplateParameters()->getParam(0));

// this TemplateTypeParmDecl is the template for the resource, and is
// used to construct a template argumentthat will be used
// to construct the ImplicitConceptSpecializationDecl
TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
Context, // AST context
Builder.Record->getDeclContext(), // DeclContext
SourceLocation(), SourceLocation(),
/*depth=*/0, // Depth in the template parameter list
/*position=*/0, // Position in the template parameter list
/*id=*/nullptr, // Identifier for 'T'
/*Typename=*/true, // Indicates this is a 'typename' or 'class'
/*ParameterPack=*/false, // Not a parameter pack
/*HasTypeConstraint=*/false // Has no type constraint
);

T->setDeclContext(DC);

QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);

// this is the 2nd template argument node, on which
// the concept constraint is actually being applied: 'element_type'
TemplateArgument ConceptTA = TemplateArgument(ConceptTType);

QualType CSETType = Context.getTypeDeclType(T);

// this is the 1st template argument node, which represents
// the abstract type that a concept would refer to: 'T'
TemplateArgument CSETA = TemplateArgument(CSETType);

ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
ImplicitConceptSpecializationDecl::Create(
Context, Builder.Record->getDeclContext(), Loc, {CSETA});

// Constraint satisfaction is used to construct the
// ConceptSpecailizationExpr, and represents the 2nd Template Argument,
// located at the bottom of the sample AST above.
const ConstraintSatisfaction CS(CD, {ConceptTA});
TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
ConceptTA, QualType(), SourceLocation());

TALI.addArgument(TAL);
const ASTTemplateArgumentListInfo *ATALI =
ASTTemplateArgumentListInfo::Create(Context, TALI);

// In the concept reference, ATALI is what adds the extra
// TemplateArgument node underneath CSE
ConceptReference *CR =
ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);

ConceptSpecializationExpr *CSE =
ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);

return CSE;
}

BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
if (Params.empty())
return Builder;
ConceptSpecializationExpr *CSE =
CD ? constructConceptSpecializationExpr(S, CD) : nullptr;

auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
SourceLocation(), Params,
SourceLocation(), CSE);
SourceLocation(), nullptr);
Builder.Template = ClassTemplateDecl::Create(
S.Context, Builder.Record->getDeclContext(), SourceLocation(),
DeclarationName(Builder.Record->getIdentifier()), ParamList,
Builder.Record);

Builder.Record->setDescribedClassTemplate(Builder.Template);
Builder.Template->setImplicit(true);
Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());

// NOTE: setPreviousDecl before addDecl so new decl replace old decl when
// make visible.
Builder.Template->setPreviousDecl(Builder.PrevTemplate);
Expand All @@ -455,13 +355,13 @@ BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
return TemplateParameterListBuilder(S, *this);
}

BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
BuiltinTypeDeclBuilder &
BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
ArrayRef<StringRef> Names) {
TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
for (StringRef Name : Names)
Builder.addTypeParameter(Name);

return Builder.finalizeTemplateArgs(CD);
return Builder.finalizeTemplateArgs();
}

HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
Expand Down Expand Up @@ -572,103 +472,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
.addDefaultHandleConstructor(S);
}

BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
SourceLocation NameLoc,
TemplateTypeParmDecl *T) {
// Obtain the QualType for 'unsigned long'
QualType UnsignedLongType = Context.UnsignedLongTy;

// Create a QualType that points to this TemplateTypeParmDecl
QualType TType = Context.getTypeDeclType(T);

// Create a TypeSourceInfo for the template type parameter 'T'
TypeSourceInfo *TTypeSourceInfo =
Context.getTrivialTypeSourceInfo(TType, NameLoc);

UnaryExprOrTypeTraitExpr *sizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
UETT_SizeOf, TTypeSourceInfo, UnsignedLongType, NameLoc, NameLoc);

// Create an IntegerLiteral for the value '16' with size type
QualType SizeType = Context.getSizeType();
llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
IntegerLiteral *SizeLiteral =
new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);

QualType BoolTy = Context.BoolTy;

BinaryOperator *binaryOperator =
BinaryOperator::Create(Context, sizeOfExpr, // Left-hand side expression
SizeLiteral, // Right-hand side expression
BO_LE, // Binary operator kind (<=)
BoolTy, // Result type (bool)
VK_LValue, // Value kind
OK_Ordinary, // Object kind
NameLoc, // Source location of operator
FPOptionsOverride());

return binaryOperator;
}

Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
TemplateTypeParmDecl *T) {
ASTContext &Context = S.getASTContext();

// first get the "sizeof(T) <= 16" expression, as a binary operator
BinaryOperator *SizeOfLEQ16 = constructSizeOfLEQ16Expr(Context, NameLoc, T);
// TODO: add the 'builtin_hlsl_is_typed_resource_element_compatible' builtin
// and return a binary operator that evaluates the builtin on the given
// template type parameter 'T'.
// Defined in issue https://github.com/llvm/llvm-project/issues/113223
return SizeOfLEQ16;
}

ConceptDecl *constructTypedBufferConceptDecl(Sema &S, NamespaceDecl *NSD) {
ASTContext &Context = S.getASTContext();
DeclContext *DC = NSD->getDeclContext();
SourceLocation DeclLoc = SourceLocation();

IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
Context, NSD->getDeclContext(), DeclLoc, DeclLoc,
/*depth=*/0,
/*position=*/0,
/*id=*/&ElementTypeII,
/*Typename=*/true,
/*ParameterPack=*/false);

T->setDeclContext(DC);
T->setReferenced();

// Create and Attach Template Parameter List to ConceptDecl
TemplateParameterList *ConceptParams = TemplateParameterList::Create(
Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);

DeclarationName DeclName = DeclarationName(
&Context.Idents.get("__is_typed_resource_element_compatible"));
Expr *ConstraintExpr = constructTypedBufferConstraintExpr(S, DeclLoc, T);

// Create a ConceptDecl
ConceptDecl *CD =
ConceptDecl::Create(Context, NSD->getDeclContext(), DeclLoc, DeclName,
ConceptParams, ConstraintExpr);

// Attach the template parameter list to the ConceptDecl
CD->setTemplateParameters(ConceptParams);

// Add the concept declaration to the Translation Unit Decl
NSD->getDeclContext()->addDecl(CD);

return CD;
}

void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
CXXRecordDecl *Decl;
ConceptDecl *TypedBufferConcept =
constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace);

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
.addSimpleTemplateParams(*SemaPtr, {"element_type"},
TypedBufferConcept)
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
.Record;

onCompletion(Decl, [this](CXXRecordDecl *Decl) {
Expand Down
20 changes: 2 additions & 18 deletions clang/test/AST/HLSL/RWBuffer-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@
// instantiated specialization.

// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
// EMPTY-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_typed_resource_element_compatible'
// EMPTY-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
// EMPTY-NEXT: TemplateArgument type 'type-parameter-0-0'
// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
// EMPTY-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class RWBuffer
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final

Expand All @@ -33,15 +25,7 @@ RWBuffer<float> Buffer;
#endif

// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
// CHECK-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_typed_resource_element_compatible'
// CHECK-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
// CHECK-NEXT: TemplateArgument type 'type-parameter-0-0'
// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
// CHECK-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition

// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// instantiated specialization.

// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class StructuredBuffer
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final

Expand All @@ -26,7 +26,7 @@ StructuredBuffer<float> Buffer;
#endif

// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class StructuredBuffer definition

// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
Expand Down

This file was deleted.

15 changes: 2 additions & 13 deletions clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,13 @@ typedef vector<float, 3> float3;
RWBuffer<float3> Buffer;

// expected-error@+2 {{class template 'RWBuffer' requires template arguments}}
// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
RWBuffer BufferErr1;

// expected-error@+2 {{too few template arguments for class template 'RWBuffer'}}
// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
RWBuffer<> BufferErr2;

struct threeDoubles {
double a;
double b;
double c;
};

// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
// expected-note@*:* {{because 'threeDoubles' does not satisfy '__is_typed_resource_element_compatible'}}
// expected-note@*:* {{because 'sizeof(threeDoubles) <= 16UL' (24 <= 16) evaluated to false}}
RWBuffer<threeDoubles> BufferErr3;

[numthreads(1,1,1)]
void main() {
(void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer<vector<float, 3>>'}}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ typedef vector<float, 3> float3;
StructuredBuffer<float3> Buffer;

// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}}
// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
StructuredBuffer BufferErr1;

// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}}
// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
StructuredBuffer<> BufferErr2;

[numthreads(1,1,1)]
Expand Down
Loading