[clang] [HLSL][TableGen] Add `__hlsl_resource_t` to known built-in function types (PR #163465)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 19 12:08:43 PST 2025
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/163465
>From 99831c12ece1b67295d8ddf522d114863dbddf92 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 14 Oct 2025 15:24:34 -0700
Subject: [PATCH 1/6] [HLSL] Add __hlsl_resource_t to types recognized by clang
TableGen for built-in functions
---
clang/include/clang/Basic/Builtins.td | 12 ++---
clang/lib/AST/ASTContext.cpp | 3 ++
clang/lib/Sema/SemaHLSL.cpp | 39 +++-------------
clang/lib/Sema/SemaOverload.cpp | 27 ++++++++----
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 12 ++---
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 44 +++++++++----------
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 12 ++---
.../buffer_update_counter-errors.hlsl | 4 +-
clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 1 +
9 files changed, 70 insertions(+), 84 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 792e2e07ec594..8d8886ee8be3c 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4930,25 +4930,25 @@ def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> {
def HLSLResourceUninitializedHandle : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_uninitializedhandle"];
let Attributes = [NoThrow];
- let Prototype = "void(...)";
+ let Prototype = "__hlsl_resource_t(__hlsl_resource_t)";
}
def HLSLResourceHandleFromBinding : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_handlefrombinding"];
let Attributes = [NoThrow];
- let Prototype = "void(...)";
+ let Prototype = "__hlsl_resource_t(__hlsl_resource_t, uint32_t, uint32_t, int32_t, uint32_t, char const*)";
}
def HLSLResourceHandleFromImplicitBinding : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_handlefromimplicitbinding"];
let Attributes = [NoThrow];
- let Prototype = "void(...)";
+ let Prototype = "__hlsl_resource_t(__hlsl_resource_t, uint32_t, uint32_t, int32_t, uint32_t, char const*)";
}
def HLSLResourceCounterHandleFromImplicitBinding : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_counterhandlefromimplicitbinding"];
- let Attributes = [NoThrow, CustomTypeChecking];
- let Prototype = "void(...)";
+ let Attributes = [NoThrow];
+ let Prototype = "__hlsl_resource_t(__hlsl_resource_t, uint32_t, uint32_t)";
}
def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
@@ -5176,7 +5176,7 @@ def HLSLRadians : LangBuiltin<"HLSL_LANG"> {
def HLSLBufferUpdateCounter : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_buffer_update_counter"];
let Attributes = [NoThrow];
- let Prototype = "uint32_t(...)";
+ let Prototype = "uint32_t(__hlsl_resource_t, int)";
}
def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a8b41ba18fa01..ace93a7b40311 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12603,6 +12603,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
case 'm':
Type = Context.MFloat8Ty;
break;
+ case 'r':
+ Type = Context.HLSLResourceTy;
+ break;
}
// If there are modifiers and if we're allowed to parse them, go for it.
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 72b2ac99ec53c..41495570e9fe9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2947,54 +2947,29 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
}
case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
- if (SemaRef.checkArgCount(TheCall, 1) ||
- CheckResourceHandle(&SemaRef, TheCall, 0))
- return true;
+ assert(TheCall->getNumArgs() == 1 && "expected 1 arg");
// use the type of the handle (arg0) as a return type
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
- ASTContext &AST = SemaRef.getASTContext();
- if (SemaRef.checkArgCount(TheCall, 6) ||
- CheckResourceHandle(&SemaRef, TheCall, 0) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
- AST.getPointerType(AST.CharTy.withConst())))
- return true;
+ assert(TheCall->getNumArgs() == 6 && "expected 6 args");
// use the type of the handle (arg0) as a return type
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
- ASTContext &AST = SemaRef.getASTContext();
- if (SemaRef.checkArgCount(TheCall, 6) ||
- CheckResourceHandle(&SemaRef, TheCall, 0) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
- AST.getPointerType(AST.CharTy.withConst())))
- return true;
+ assert(TheCall->getNumArgs() == 6 && "expected 6 args");
// use the type of the handle (arg0) as a return type
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {
+ assert(TheCall->getNumArgs() == 3 && "expected 3 args");
ASTContext &AST = SemaRef.getASTContext();
- if (SemaRef.checkArgCount(TheCall, 3) ||
- CheckResourceHandle(&SemaRef, TheCall, 0) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy))
- return true;
-
QualType MainHandleTy = TheCall->getArg(0)->getType();
auto *MainResType = MainHandleTy->getAs<HLSLAttributedResourceType>();
auto MainAttrs = MainResType->getAttrs();
@@ -3302,14 +3277,12 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
}
case Builtin::BI__builtin_hlsl_buffer_update_counter: {
+ assert(TheCall->getNumArgs() == 2 && "expected 2 args");
auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {
return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&
ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());
};
- if (SemaRef.checkArgCount(TheCall, 2) ||
- CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
- SemaRef.getASTContext().IntTy))
+ if (CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy))
return true;
Expr *OffsetExpr = TheCall->getArg(1);
std::optional<llvm::APSInt> Offset =
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8339bb19a1edc..4b59cd3c4f4ce 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1825,15 +1825,24 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
return ICS;
}
- if (S.getLangOpts().HLSL && ToType->isHLSLAttributedResourceType() &&
- FromType->isHLSLAttributedResourceType()) {
- auto *ToResType = cast<HLSLAttributedResourceType>(ToType);
- auto *FromResType = cast<HLSLAttributedResourceType>(FromType);
- if (S.Context.hasSameUnqualifiedType(ToResType->getWrappedType(),
- FromResType->getWrappedType()) &&
- S.Context.hasSameUnqualifiedType(ToResType->getContainedType(),
- FromResType->getContainedType()) &&
- ToResType->getAttrs() == FromResType->getAttrs()) {
+ const Type *FromTy = FromType->getUnqualifiedDesugaredType();
+ if (S.getLangOpts().HLSL && FromTy->isHLSLAttributedResourceType()) {
+ bool CanConvert = false;
+ const Type *ToTy = ToType->getUnqualifiedDesugaredType();
+ if (ToTy->isHLSLAttributedResourceType()) {
+ auto *ToResType = cast<HLSLAttributedResourceType>(ToTy);
+ auto *FromResType = cast<HLSLAttributedResourceType>(FromTy);
+ if (S.Context.hasSameUnqualifiedType(ToResType->getWrappedType(),
+ FromResType->getWrappedType()) &&
+ S.Context.hasSameUnqualifiedType(ToResType->getContainedType(),
+ FromResType->getContainedType()) &&
+ ToResType->getAttrs() == FromResType->getAttrs())
+ CanConvert = true;
+ }
+ else if (ToTy->isHLSLResourceType()) {
+ CanConvert = true;
+ }
+ if (CanConvert) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 43d8ddee6ccad..cf128c43481e6 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -50,8 +50,8 @@ RESOURCE Buffer;
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
-// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle' '__hlsl_resource_t (__hlsl_resource_t) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
@@ -97,8 +97,8 @@ RESOURCE Buffer;
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
@@ -127,8 +127,8 @@ RESOURCE Buffer;
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index e72207e10132c..1761754f5c076 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -97,8 +97,8 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
-// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle' '__hlsl_resource_t (__hlsl_resource_t) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
@@ -154,8 +154,8 @@ RESOURCE<float> Buffer;
// CHECK-BINDING-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-BINDING-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-BINDING-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-BINDING-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-BINDING-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
@@ -182,8 +182,8 @@ RESOURCE<float> Buffer;
// CHECK-BINDING-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-BINDING-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-BINDING-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-BINDING-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-BINDING-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-BINDING-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
@@ -209,8 +209,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
@@ -222,8 +222,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__counter_handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_counterhandlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_counterhandlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int) noexcept'
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'counterOrderId' 'unsigned int'
@@ -246,8 +246,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
@@ -259,8 +259,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__counter_handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_counterhandlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-COUNTER-HANDLE-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_counterhandlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int) noexcept'
// CHECK-COUNTER-HANDLE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-COUNTER-HANDLE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'counterOrderId' 'unsigned int'
@@ -332,8 +332,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-NEXT: CompoundStmt
// CHECK-COUNTER-NEXT: ReturnStmt
// CHECK-COUNTER-NEXT: CallExpr {{.*}} 'unsigned int'
-// CHECK-COUNTER-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-COUNTER-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept'
+// CHECK-COUNTER-NEXT: ImplicitCastExpr {{.*}} 'unsigned int (*)(__hlsl_resource_t, int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (__hlsl_resource_t, int) noexcept'
// CHECK-COUNTER-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-COUNTER-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-COUNTER-SAME{LITERAL}: [[hlsl::raw_buffer]]
@@ -348,8 +348,8 @@ RESOURCE<float> Buffer;
// CHECK-COUNTER-NEXT: CompoundStmt
// CHECK-COUNTER-NEXT: ReturnStmt
// CHECK-COUNTER-NEXT: CallExpr {{.*}} 'unsigned int'
-// CHECK-COUNTER-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-COUNTER-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept'
+// CHECK-COUNTER-NEXT: ImplicitCastExpr {{.*}} 'unsigned int (*)(__hlsl_resource_t, int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-COUNTER-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (__hlsl_resource_t, int) noexcept'
// CHECK-COUNTER-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-COUNTER-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-COUNTER-SAME{LITERAL}: [[hlsl::raw_buffer]]
@@ -374,8 +374,8 @@ RESOURCE<float> Buffer;
// CHECK-APPEND-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle
// CHECK-APPEND-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-APPEND-NEXT: CallExpr {{.*}} 'unsigned int'
-// CHECK-APPEND-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-APPEND-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept'
+// CHECK-APPEND-NEXT: ImplicitCastExpr {{.*}} 'unsigned int (*)(__hlsl_resource_t, int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-APPEND-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (__hlsl_resource_t, int) noexcept'
// CHECK-APPEND-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-APPEND-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-APPEND-SAME{LITERAL}: [[hlsl::raw_buffer]]
@@ -399,8 +399,8 @@ RESOURCE<float> Buffer;
// CHECK-CONSUME-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle
// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-CONSUME-NEXT: CallExpr {{.*}} 'unsigned int'
-// CHECK-CONSUME-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-CONSUME-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept'
+// CHECK-CONSUME-NEXT: ImplicitCastExpr {{.*}} 'unsigned int (*)(__hlsl_resource_t, int) noexcept' <BuiltinFnToFnPtr>
+// CHECK-CONSUME-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (__hlsl_resource_t, int) noexcept'
// CHECK-CONSUME-NEXT: MemberExpr {{.*}} '__hlsl_resource_t
// CHECK-CONSUME-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-CONSUME-SAME{LITERAL}: [[hlsl::raw_buffer]]
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 5182ce194cfb0..2f623a7301741 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -72,8 +72,8 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t
-// CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle' '__hlsl_resource_t (__hlsl_resource_t) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: AlwaysInlineAttr
@@ -119,8 +119,8 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int'
@@ -147,8 +147,8 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t (*)(__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' '__hlsl_resource_t (__hlsl_resource_t, unsigned int, unsigned int, int, unsigned int, const char *) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 'unsigned int'
diff --git a/clang/test/SemaHLSL/BuiltIns/buffer_update_counter-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/buffer_update_counter-errors.hlsl
index 4aa3ac183d3b1..faac8f07b240a 100644
--- a/clang/test/SemaHLSL/BuiltIns/buffer_update_counter-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/buffer_update_counter-errors.hlsl
@@ -16,7 +16,7 @@ void test_args(int x, bool b) {
// expected-error at +1 {{too many arguments to function call, expected 2, have 3}}
__builtin_hlsl_buffer_update_counter(x, x, x);
- // expected-error at +1 {{used type 'int' where __hlsl_resource_t is required}}
+ // expected-error at +1 {{cannot initialize a parameter of type '__hlsl_resource_t' with an lvalue of type 'int'}}
__builtin_hlsl_buffer_update_counter(x, x);
bad_handle_not_raw_t bad1;
@@ -37,7 +37,7 @@ void test_args(int x, bool b) {
// expected-error at +1 {{argument 1 must be constant integer 1 or -1}}
__builtin_hlsl_buffer_update_counter(res, x);
- // expected-error at +1 {{passing 'const char *' to parameter of incompatible type 'int'}}
+ // expected-error at +1 {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char[2]'}}
__builtin_hlsl_buffer_update_counter(res, "1");
// expected-error at +1 {{argument 1 must be constant integer 1 or -1}}
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 352765acf5338..165203b772a6c 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -330,6 +330,7 @@ class PrototypeParser {
.Case("__builtin_va_list", "a")
.Case("__float128", "LLd")
.Case("__fp16", "h")
+ .Case("__hlsl_resource_t", "r")
.Case("__int128_t", "LLLi")
.Case("_Float16", "x")
.Case("__bf16", "y")
>From 568bb70bfc7f9cce523ad6cb9a10ecf2e5c77ccb Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 31 Oct 2025 11:30:17 -0700
Subject: [PATCH 2/6] Change GetDimensions to use __hlsl_resource_t in the
builtin signature
---
clang/include/clang/Basic/Builtins.td | 4 ++--
clang/lib/Sema/SemaHLSL.cpp | 18 ------------------
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 4 ++--
clang/test/AST/HLSL/StructuredBuffers-AST.hlsl | 8 ++++----
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 4 ++--
5 files changed, 10 insertions(+), 28 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index dc562321e090b..e13c1d004797a 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4967,13 +4967,13 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
def HLSLResourceGetDimensionsX : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_getdimensions_x"];
let Attributes = [NoThrow];
- let Prototype = "void(...)";
+ let Prototype = "void(__hlsl_resource_t, uint32_t&)";
}
def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_resource_getstride"];
let Attributes = [NoThrow];
- let Prototype = "void(...)";
+ let Prototype = "void(__hlsl_resource_t, uint32_t&)";
}
def HLSLAll : LangBuiltin<"HLSL_LANG"> {
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f8038a0fb6226..5fb6b398db4d2 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3045,24 +3045,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(CounterHandleTy);
break;
}
- case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
- ASTContext &AST = SemaRef.getASTContext();
- if (SemaRef.checkArgCount(TheCall, 2) ||
- CheckResourceHandle(&SemaRef, TheCall, 0) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckModifiableLValue(&SemaRef, TheCall, 1))
- return true;
- break;
- }
- case Builtin::BI__builtin_hlsl_resource_getstride: {
- ASTContext &AST = SemaRef.getASTContext();
- if (SemaRef.checkArgCount(TheCall, 2) ||
- CheckResourceHandle(&SemaRef, TheCall, 0) ||
- CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
- CheckModifiableLValue(&SemaRef, TheCall, 1))
- return true;
- break;
- }
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 458ad6f7484bc..2713cc19ea2be 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -149,8 +149,8 @@ RESOURCE Buffer;
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(__hlsl_resource_t, unsigned int &) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (__hlsl_resource_t, unsigned int &) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index bb1f6aa70fae4..538eb5256f8d5 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -417,14 +417,14 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(__hlsl_resource_t, unsigned int &) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (__hlsl_resource_t, unsigned int &) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'numStructs' 'unsigned int &__restrict'
// CHECK-NEXT: CallExpr {{.*}} 'void'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getstride' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(__hlsl_resource_t, unsigned int &) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getstride' 'void (__hlsl_resource_t, unsigned int &) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'stride' 'unsigned int &__restrict'
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 1f2caeb03794d..4b66faa79662a 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -221,8 +221,8 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
-// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(__hlsl_resource_t, unsigned int &) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (__hlsl_resource_t, unsigned int &) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
>From 8621c01a003d83220f766fc968e7164467be6f49 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 31 Oct 2025 11:40:45 -0700
Subject: [PATCH 3/6] clang-format & add comments
---
clang/lib/Sema/SemaOverload.cpp | 49 ++++++++++++++++++---------------
1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 8d498d1c62c97..c12f92dfdab66 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1825,29 +1825,34 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
return ICS;
}
- const Type *FromTy = FromType->getUnqualifiedDesugaredType();
- if (S.getLangOpts().HLSL && FromTy->isHLSLAttributedResourceType()) {
- bool CanConvert = false;
- const Type *ToTy = ToType->getUnqualifiedDesugaredType();
- if (ToTy->isHLSLAttributedResourceType()) {
- auto *ToResType = cast<HLSLAttributedResourceType>(ToTy);
- auto *FromResType = cast<HLSLAttributedResourceType>(FromTy);
- if (S.Context.hasSameUnqualifiedType(ToResType->getWrappedType(),
- FromResType->getWrappedType()) &&
- S.Context.hasSameUnqualifiedType(ToResType->getContainedType(),
- FromResType->getContainedType()) &&
- ToResType->getAttrs() == FromResType->getAttrs())
+ if (S.getLangOpts().HLSL) {
+ // Handle conversion of the HLSL resource types.
+ const Type *FromTy = FromType->getUnqualifiedDesugaredType();
+ if (FromTy->isHLSLAttributedResourceType()) {
+ // Attributed resource types can convert to other attributed
+ // resource types with the same attributes and contained types,
+ // or to __hlsl_resource_t without any attributes.
+ bool CanConvert = false;
+ const Type *ToTy = ToType->getUnqualifiedDesugaredType();
+ if (ToTy->isHLSLAttributedResourceType()) {
+ auto *ToResType = cast<HLSLAttributedResourceType>(ToTy);
+ auto *FromResType = cast<HLSLAttributedResourceType>(FromTy);
+ if (S.Context.hasSameUnqualifiedType(ToResType->getWrappedType(),
+ FromResType->getWrappedType()) &&
+ S.Context.hasSameUnqualifiedType(ToResType->getContainedType(),
+ FromResType->getContainedType()) &&
+ ToResType->getAttrs() == FromResType->getAttrs())
+ CanConvert = true;
+ } else if (ToTy->isHLSLResourceType()) {
CanConvert = true;
- }
- else if (ToTy->isHLSLResourceType()) {
- CanConvert = true;
- }
- if (CanConvert) {
- ICS.setStandard();
- ICS.Standard.setAsIdentityConversion();
- ICS.Standard.setFromType(FromType);
- ICS.Standard.setAllToTypes(ToType);
- return ICS;
+ }
+ if (CanConvert) {
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.setFromType(FromType);
+ ICS.Standard.setAllToTypes(ToType);
+ return ICS;
+ }
}
}
>From bc12044c1e60845158672d8ee3ed48869231f52d Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 6 Nov 2025 12:37:29 -0800
Subject: [PATCH 4/6] [HLSL] Add internal linkage attribute to resources
HLSL resources should not be externally visible from the module.
We made sure of this by marking them `static` as soon as they were declared.
However, this prevents us fixing issue #166458 because there is no way
to know if a resource has been explicitly marked `static`
by the user, and can therefore be assigned to.
This change is moves from making all resources `static` to adding Clang internal
linkage attribute to all non-static resource declarations as a global scope.
Existing tests verify that there is no change in how the resource globals are
emitted: `internal global`.
---
clang/lib/Sema/SemaHLSL.cpp | 13 ++++++++-----
clang/test/AST/HLSL/cbuffer.hlsl | 2 +-
clang/test/AST/HLSL/private.hlsl | 2 +-
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5fb6b398db4d2..68802813f74e5 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3802,12 +3802,15 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
if (VD->getType()->isHLSLIntangibleType())
collectResourceBindingsOnVarDecl(VD);
- if (isResourceRecordTypeOrArrayOf(VD) ||
- VD->hasAttr<HLSLVkConstantIdAttr>()) {
- // Make the variable for resources static. The global externally visible
- // storage is accessed through the handle, which is a member. The variable
- // itself is not externally visible.
+ if (VD->hasAttr<HLSLVkConstantIdAttr>())
VD->setStorageClass(StorageClass::SC_Static);
+
+ if (isResourceRecordTypeOrArrayOf(VD) &&
+ VD->getStorageClass() != SC_Static) {
+ // Add internal linkage attribute to non-static resource variables. The
+ // global externally visible storage is accessed through the handle, which
+ // is a member. The variable itself is not externally visible.
+ VD->addAttr(InternalLinkageAttr::CreateImplicit(getASTContext()));
}
// process explicit bindings
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index f3c6636232798..b0b5b989e36c2 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -153,7 +153,7 @@ cbuffer CB {
static float SV;
// CHECK: VarDecl {{.*}} s7 'EmptyStruct' callinit
EmptyStruct s7;
- // CHECK: VarDecl {{.*}} Buf 'RWBuffer<float>':'hlsl::RWBuffer<float>' static callinit
+ // CHECK: VarDecl {{.*}} Buf 'RWBuffer<float>':'hlsl::RWBuffer<float>' callinit
RWBuffer<float> Buf;
// CHECK: VarDecl {{.*}} ea 'EmptyArrayTypedef':'float[10][0]'
EmptyArrayTypedef ea;
diff --git a/clang/test/AST/HLSL/private.hlsl b/clang/test/AST/HLSL/private.hlsl
index e00afb8f5cbd8..ba7380ec3cfda 100644
--- a/clang/test/AST/HLSL/private.hlsl
+++ b/clang/test/AST/HLSL/private.hlsl
@@ -3,7 +3,7 @@
// CHECK: VarDecl {{.*}} global_scalar 'hlsl_private int' static cinit
static int global_scalar = 0;
-// CHECK: VarDecl {{.*}} global_buffer 'RWBuffer<float>':'hlsl::RWBuffer<float>' static callinit
+// CHECK: VarDecl {{.*}} global_buffer 'RWBuffer<float>':'hlsl::RWBuffer<float>' callinit
RWBuffer<float> global_buffer;
class A {
>From c10e6f3fd7c43bc7335a3e51aaf39ae1cba8835f Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 18 Nov 2025 13:42:15 -0800
Subject: [PATCH 5/6] Update shortcut to "Qr"
---
clang/lib/AST/ASTContext.cpp | 7 ++++---
clang/utils/TableGen/ClangBuiltinsEmitter.cpp | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 07ee39e5d474f..b929b0fc1aa8e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12540,6 +12540,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
Type = Context.AMDGPUTextureTy;
break;
}
+ case 'r': {
+ Type = Context.HLSLResourceTy;
+ break;
+ }
default:
llvm_unreachable("Unexpected target builtin type");
}
@@ -12615,9 +12619,6 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
case 'm':
Type = Context.MFloat8Ty;
break;
- case 'r':
- Type = Context.HLSLResourceTy;
- break;
}
// If there are modifiers and if we're allowed to parse them, go for it.
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 165203b772a6c..9b6dd37c7a4a9 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -330,7 +330,7 @@ class PrototypeParser {
.Case("__builtin_va_list", "a")
.Case("__float128", "LLd")
.Case("__fp16", "h")
- .Case("__hlsl_resource_t", "r")
+ .Case("__hlsl_resource_t", "Qr")
.Case("__int128_t", "LLLi")
.Case("_Float16", "x")
.Case("__bf16", "y")
>From 04578d36d692a4817befda4ff798d9e4446063a0 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 19 Nov 2025 12:08:17 -0800
Subject: [PATCH 6/6] code review feedback - update comments
---
clang/lib/Sema/SemaHLSL.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e585b9c0b2fe3..c834f7736eacf 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3048,21 +3048,21 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
assert(TheCall->getNumArgs() == 1 && "expected 1 arg");
- // use the type of the handle (arg0) as a return type
+ // Update return type to be the attributed resource type from arg0.
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
assert(TheCall->getNumArgs() == 6 && "expected 6 args");
- // use the type of the handle (arg0) as a return type
+ // Update return type to be the attributed resource type from arg0.
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
}
case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
assert(TheCall->getNumArgs() == 6 && "expected 6 args");
- // use the type of the handle (arg0) as a return type
+ // Update return type to be the attributed resource type from arg0.
QualType ResourceTy = TheCall->getArg(0)->getType();
TheCall->setType(ResourceTy);
break;
@@ -3078,6 +3078,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
QualType CounterHandleTy = AST.getHLSLAttributedResourceType(
MainResType->getWrappedType(), MainResType->getContainedType(),
MainAttrs);
+ // Update return type to be the attributed resource type from arg0
+ // with added IsCounter flag.
TheCall->setType(CounterHandleTy);
break;
}
More information about the cfe-commits
mailing list