Skip to content

Commit

Permalink
Revert "[HLSL] Add implicit resource element type concepts to AST" (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
bob80905 authored Nov 15, 2024
1 parent 47889cd commit c1f6cb7
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 250 deletions.
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

0 comments on commit c1f6cb7

Please sign in to comment.