diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276..71a86f035b855 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -326,6 +326,10 @@ struct TemplateParameterListBuilder { BuiltinTypeDeclBuilder &finalizeTemplateArgs() { if (Params.empty()) return Builder; + + ConceptSpecializationExpr *CSE = + CD ? constructConceptSpecializationExpr(S, CD) : nullptr; + auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(), SourceLocation(), Params, SourceLocation(), nullptr); @@ -472,6 +476,186 @@ 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; +} + +BinaryOperator *getSizeOfLEQ16Expr(clang::ASTContext &context, + SourceLocation NameLoc, + TemplateTypeParmDecl *T) { + // Obtain the QualType for 'unsigned long' + clang::QualType unsignedLongType = context.UnsignedLongTy; + + // Create a QualType that points to this TemplateTypeParmDecl + clang::QualType TType = context.getTypeDeclType(T); + + // Create a TypeSourceInfo for the template type parameter 'T' + clang::TypeSourceInfo *TTypeSourceInfo = + context.getTrivialTypeSourceInfo(TType, NameLoc); + + clang::UnaryExprOrTypeTraitExpr *sizeOfExpr = new (context) + clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo, + unsignedLongType, NameLoc, NameLoc); + + // Create an IntegerLiteral for the value '16' with size type + clang::QualType sizeType = context.getSizeType(); + llvm::APInt sizeValue = llvm::APInt(context.getTypeSize(sizeType), 16); + clang::IntegerLiteral *sizeLiteral = new (context) + clang::IntegerLiteral(context, sizeValue, sizeType, NameLoc); + + clang::QualType BoolTy = context.BoolTy; + + clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create( + context, sizeOfExpr, // Left-hand side expression + sizeLiteral, // Right-hand side expression + clang::BO_LE, // Binary operator kind (<=) + BoolTy, // Result type (bool) + clang::VK_LValue, // Value kind + clang::OK_Ordinary, // Object kind + NameLoc, // Source location of operator + FPOptionsOverride()); + + return binaryOperator; +} + +Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc, + TemplateTypeParmDecl *T) { + clang::ASTContext &context = S.getASTContext(); + + // first get the "sizeof(T) <= 16" expression, as a binary operator + BinaryOperator *sizeOfLEQ16 = getSizeOfLEQ16Expr(context, NameLoc, T); + // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin + // and return a binary operator that evaluates the builtin on the given + // template type parameter 'T' + return sizeOfLEQ16; +} + +ConceptDecl *getTypedBufferConceptDecl(Sema &S) { + DeclContext *DC = S.CurContext; + clang::ASTContext &context = S.getASTContext(); + SourceLocation DeclLoc = SourceLocation(); + + IdentifierInfo &IsValidLineVectorII = + context.Idents.get("is_valid_line_vector"); + IdentifierInfo &ElementTypeII = context.Idents.get("element_type"); + clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create( + context, context.getTranslationUnitDecl(), 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 + clang::TemplateParameterList *ConceptParams = + clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc, {T}, + DeclLoc, nullptr); + + DeclarationName DeclName = DeclarationName(&IsValidLineVectorII); + Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T); + + // Create a ConceptDecl + clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create( + context, context.getTranslationUnitDecl(), DeclLoc, DeclName, + ConceptParams, ConstraintExpr); + + // Attach the template parameter list to the ConceptDecl + conceptDecl->setTemplateParameters(ConceptParams); + + // Add the concept declaration to the Translation Unit Decl + context.getTranslationUnitDecl()->addDecl(conceptDecl); + + return conceptDecl; +} + void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") diff --git a/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl index 5a13ca7735f99..8dbab44024d34 100644 --- a/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl @@ -12,7 +12,7 @@ // instantiated specialization. // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit AppendStructuredBuffer -// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class AppendStructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -26,7 +26,7 @@ AppendStructuredBuffer Buffer; #endif // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit AppendStructuredBuffer -// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class AppendStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl index b75f3fcb959cf..f27941b539b6a 100644 --- a/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl @@ -12,7 +12,7 @@ // instantiated specialization. // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit ConsumeStructuredBuffer -// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class ConsumeStructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -26,7 +26,7 @@ ConsumeStructuredBuffer Buffer; #endif // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit ConsumeStructuredBuffer -// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class ConsumeStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl index 4a1e1d7570e5e..5058eab40b1ae 100644 --- a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl @@ -12,7 +12,7 @@ // instantiated specialization. // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWStructuredBuffer -// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWStructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -26,7 +26,7 @@ RWStructuredBuffer Buffer; #endif // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWStructuredBuffer -// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl index f334e1bb6db3f..bd05432a09e01 100644 --- a/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl @@ -12,7 +12,7 @@ // instantiated specialization. // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RasterizerOrderedStructuredBuffer -// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RasterizerOrderedStructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -26,7 +26,7 @@ RasterizerOrderedStructuredBuffer Buffer; #endif // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RasterizerOrderedStructuredBuffer -// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RasterizerOrderedStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final