https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/161929
>From e50918910a0ce590228c6ecacd4ff2a578da6f58 Mon Sep 17 00:00:00 2001 From: Helena Kotas <[email protected]> Date: Fri, 3 Oct 2025 17:33:19 -0700 Subject: [PATCH 1/4] [HLSL] GetDimensions methods for buffer resources Adds GetDimensions methods on all supported buffer resources. --- clang/include/clang/Basic/Builtins.td | 12 +++ clang/lib/CodeGen/CGHLSLBuiltins.cpp | 61 ++++++++++++++ clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 81 ++++++++++++++++++- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 + clang/lib/Sema/HLSLExternalSemaSource.cpp | 11 +++ clang/lib/Sema/SemaHLSL.cpp | 18 +++++ .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 14 ++++ .../test/AST/HLSL/StructuredBuffers-AST.hlsl | 22 +++++ clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 14 ++++ .../resources/ByteAddressBuffers-methods.hlsl | 47 +++++++++++ .../StructuredBuffers-methods-lib.hlsl | 53 +++++++++++- .../StructuredBuffers-methods-ps.hlsl | 37 +++++++++ .../resources/TypedBuffers-methods.hlsl | 34 ++++++++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 4 + 14 files changed, 406 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 468121f7d20ab..0b1587be51217 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4951,6 +4951,18 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> { let Prototype = "uint32_t(uint32_t)"; } +def HLSLResourceGetDimensions : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_buffer_getdimensions"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + +def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_buffer_getstride"]; + let Attributes = [NoThrow]; + let Prototype = "void(...)"; +} + def HLSLAll : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_all"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 6c0fc8d7f07be..373153e01c128 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -160,6 +160,58 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { return LastInst; } +static Value *emitDXILGetDimensions(CodeGenFunction *CGF, Value *Handle, + Value *MipLevel, LValue *OutArg0, + LValue *OutArg1 = nullptr, + LValue *OutArg2 = nullptr, + LValue *OutArg3 = nullptr) { + assert(OutArg0 && "first output argument is required"); + + llvm::Type *I32 = CGF->Int32Ty; + StructType *RetTy = llvm::StructType::get(I32, I32, I32, I32); + + CallInst *CI = CGF->Builder.CreateIntrinsic( + RetTy, llvm::Intrinsic::dx_resource_getdimensions, + ArrayRef<Value *>{Handle, MipLevel}); + + Value *LastInst = nullptr; + unsigned OutArgIndex = 0; + for (LValue *OutArg : {OutArg0, OutArg1, OutArg2, OutArg3}) { + if (OutArg) { + Value *OutArgVal = CGF->Builder.CreateExtractValue(CI, OutArgIndex); + LastInst = CGF->Builder.CreateStore(OutArgVal, OutArg->getAddress()); + } + ++OutArgIndex; + } + assert(LastInst && "no output argument stored?"); + return LastInst; +} + +static Value *emitBufferGetDimensions(CodeGenFunction *CGF, Value *Handle, + LValue &Dim) { + // Generate the call to get the buffer dimension. + switch (CGF->CGM.getTarget().getTriple().getArch()) { + case llvm::Triple::dxil: + return emitDXILGetDimensions(CGF, Handle, PoisonValue::get(CGF->Int32Ty), + &Dim); + break; + case llvm::Triple::spirv: + llvm_unreachable("SPIR-V GetDimensions codegen not implemented yet."); + default: + llvm_unreachable("GetDimensions not supported by target architecture"); + } +} + +static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr, + LValue &Stride) { + // Figure out the stride of the buffer elements from the handle type. + auto *HandleTy = + cast<HLSLAttributedResourceType>(HandleExpr->getType().getTypePtr()); + QualType ElementTy = HandleTy->getContainedType(); + Value *StrideValue = CGF->getTypeSize(ElementTy); + return CGF->Builder.CreateStore(StrideValue, Stride.getAddress()); +} + // Return dot product intrinsic that corresponds to the QT scalar type static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) { if (QT->isFloatingType()) @@ -359,6 +411,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(), ArrayRef<Value *>{IndexOp}); } + case Builtin::BI__builtin_hlsl_buffer_getdimensions: { + Value *Handle = EmitScalarExpr(E->getArg(0)); + LValue Dim = EmitLValue(E->getArg(1)); + return emitBufferGetDimensions(this, Handle, Dim); + } + case Builtin::BI__builtin_hlsl_buffer_getstride: { + LValue Stride = EmitLValue(E->getArg(1)); + return emitBufferStride(this, E->getArg(0), Stride); + } case Builtin::BI__builtin_hlsl_all: { Value *Op0 = EmitScalarExpr(E->getArg(0)); return Builder.CreateIntrinsic( diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 3c20ccd799b2d..d6d6b31aa2d9d 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -57,6 +57,29 @@ CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) { return CD; return nullptr; } + +ParameterABI +convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) { + assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in && + "HLSL 'in' parameters modifier cannot be converted to ParameterABI"); + switch (Modifier) { + case HLSLParamModifierAttr::Spelling::Keyword_out: + return ParameterABI::HLSLOut; + case HLSLParamModifierAttr::Spelling::Keyword_inout: + return ParameterABI::HLSLInOut; + default: + llvm_unreachable("Invalid HLSL parameter modifier"); + } +} + +QualType getInoutParameterType(ASTContext &AST, QualType Ty) { + assert(!Ty->isReferenceType() && + "Pointer and reference types cannot be inout or out parameters"); + Ty = AST.getLValueReferenceType(Ty); + Ty.addRestrict(); + return Ty; +} + } // namespace // Builder for template arguments of builtin types. Used internally @@ -421,13 +444,32 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty, void BuiltinTypeMethodBuilder::createDecl() { assert(Method == nullptr && "Method or constructor is already created"); - // create method or constructor type + // create function prototype ASTContext &AST = DeclBuilder.SemaRef.getASTContext(); SmallVector<QualType> ParamTypes; - for (Param &MP : Params) - ParamTypes.emplace_back(MP.Ty); + SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size()); + uint32_t ArgIndex = 0; + bool IsTemplate = DeclBuilder.Template != nullptr; + bool UseParamExtInfo = false; + for (Param &MP : Params) { + QualType Ty = MP.Ty; + if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) { + UseParamExtInfo = true; + ParamExtInfos[ArgIndex].withABI( + convertParamModifierToParamABI(MP.Modifier)); + // Only update types on inout and out parameters for non-templated + // methods. Templated types will have their inout/out parameters + // converted to references during template instantiation. + if (!IsTemplate) + Ty = getInoutParameterType(AST, Ty); + } + ParamTypes.emplace_back(Ty); + ++ArgIndex; + } FunctionProtoType::ExtProtoInfo ExtInfo; + if (UseParamExtInfo) + ExtInfo.ExtParameterInfos = ParamExtInfos.data(); if (IsConst) ExtInfo.TypeQuals.addConst(); @@ -459,6 +501,7 @@ void BuiltinTypeMethodBuilder::createDecl() { AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None, nullptr); if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) { + Parm->setType(getInoutParameterType(AST, Parm->getType())); auto *Mod = HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier); Parm->addAttr(Mod); @@ -1127,5 +1170,37 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() { .finalize(); } +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() { + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + ASTContext &AST = SemaRef.getASTContext(); + QualType UIntTy = AST.UnsignedIntTy; + + QualType HandleTy = getResourceHandleField()->getType(); + auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr()); + + // Structured buffers except {RW}ByteAddressBuffer have overload + // GetDimensions(out uint numStructs, out uint stride). + if (AttrResTy->getAttrs().RawBuffer && + AttrResTy->getContainedType() != AST.Char8Ty) { + return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) + .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out) + .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out) + .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(), + PH::Handle, PH::_0) + .callBuiltin("__builtin_hlsl_buffer_getstride", QualType(), PH::Handle, + PH::_1) + .finalize(); + } + + // Typed buffers and {RW}ByteAddressBuffer have overload + // GetDimensions(out uint dim). + return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) + .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out) + .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(), + PH::Handle, PH::_0) + .finalize(); +} + } // namespace hlsl } // namespace clang diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index a981602a50461..920a2f07a16ad 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -95,6 +95,8 @@ class BuiltinTypeDeclBuilder { BuiltinTypeDeclBuilder &addAppendMethod(); BuiltinTypeDeclBuilder &addConsumeMethod(); + BuiltinTypeDeclBuilder &addGetDimensionsMethodForBuffer(); + private: BuiltinTypeDeclBuilder &addResourceMember(StringRef MemberName, ResourceClass RC, bool IsROV, diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cc43e9474ea79..ce69e4987d6cd 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -380,6 +380,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { /*RawBuffer=*/false, /*HasCounter=*/false) .addArraySubscriptOperators() .addLoadMethods() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -392,6 +393,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { /*RawBuffer=*/false, /*HasCounter=*/false) .addArraySubscriptOperators() .addLoadMethods() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -404,6 +406,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { /*RawBuffer=*/false, /*HasCounter=*/false) .addArraySubscriptOperators() .addLoadMethods() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -415,6 +418,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { /*RawBuffer=*/true, /*HasCounter=*/false) .addArraySubscriptOperators() .addLoadMethods() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -428,6 +432,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .addLoadMethods() .addIncrementCounterMethod() .addDecrementCounterMethod() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -439,6 +444,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false, /*RawBuffer=*/true, /*HasCounter=*/true) .addAppendMethod() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -450,6 +456,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false, /*RawBuffer=*/true, /*HasCounter=*/true) .addConsumeMethod() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -464,6 +471,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .addLoadMethods() .addIncrementCounterMethod() .addDecrementCounterMethod() + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); @@ -472,6 +480,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false, /*RawBuffer=*/true, /*HasCounter=*/false) + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer") @@ -479,6 +488,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false, /*RawBuffer=*/true, /*HasCounter=*/false) + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, @@ -487,6 +497,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true, /*RawBuffer=*/true, /*HasCounter=*/false) + .addGetDimensionsMethodForBuffer() .completeDefinition(); }); } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index fa30c66b62684..e3281c493da50 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2978,6 +2978,24 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall->setType(ResourceTy); break; } + case Builtin::BI__builtin_hlsl_buffer_getdimensions: { + 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_buffer_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 43d8ddee6ccad..a2058b29401c0 100644 --- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl @@ -142,5 +142,19 @@ RESOURCE Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline +// GetDimensions method + +// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int &__restrict)' +// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict' +// 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_buffer_getdimensions' 'void (...) 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' +// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline + // CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const char8_t &(unsigned int) const' // CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'char8_t &(unsigned int)' diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl index 6779abb10bec4..e5f4b22fe2a10 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -334,6 +334,28 @@ RESOURCE<float> Buffer; // CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this // CHECK-CONSUME-NEXT: IntegerLiteral {{.*}} 'int' -1 +// GetDimensions method + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} numStructs 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} stride 'unsigned int &__restrict' +// 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_buffer_getdimensions' 'void (...) 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_buffer_getstride' 'void (...) 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' +// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline + // CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition // CHECK: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType {{.*}} 'float' diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl index 5182ce194cfb0..07f04001a58ae 100644 --- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl @@ -214,6 +214,20 @@ RESOURCE<float> Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline +// GetDimensions method + +// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict' +// 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_buffer_getdimensions' 'void (...) 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' +// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline + // CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition // CHECK: TemplateArgument type 'float' diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl new file mode 100644 index 0000000000000..f089c0cdf0ca3 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL +// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV + +// NOTE: SPIRV codegen for resource methods is not yet implemented + +ByteAddressBuffer Buf : register(t0); +RWByteAddressBuffer RWBuf : register(u0); + +// DXIL: %"class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) } +// DXIL: %"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) } + +// DXIL: @Buf = internal global %"class.hlsl::ByteAddressBuffer" poison +// DXIL: @RWBuf = internal global %"class.hlsl::RWByteAddressBuffer" poison + +export uint TestGetDimensions() { + uint dim1, dim2; + Buf.GetDimensions(dim1); + RWBuf.GetDimensions(dim2); + return dim1 + dim2; +} + +// CHECK: define {{.*}} @TestGetDimensions()() +// CHECK: call void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr{{.*}} %dim1) +// CHECK: call void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr{{.*}} @RWBuf, ptr{{.*}} %dim2) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim) +// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]] +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim) +// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]] +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] +// CHECK-NEXT: ret void + +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0), i32) +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0), i32) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index a506c2b50b1dc..c3bb147ad4a53 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -82,7 +82,7 @@ export float TestLoad() { return RWSB1.Load(1) + SB1.Load(2); } -// CHECK: define noundef nofpclass(nan inf) float @TestLoad()() +// CHECK: define {{.*}} float @TestLoad()() // CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1) // CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @SB1, i32 noundef 2) // CHECK: add @@ -104,9 +104,60 @@ export float TestLoad() { // CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]], align 4 // CHECK-NEXT: ret float %[[VAL]] +export uint TestGetDimensions() { + uint dim1, dim2, dim3, stride1, stride2, stride3; + SB1.GetDimensions(dim1, stride1); + RWSB2.GetDimensions(dim2, stride2); + CSB.GetDimensions(dim3, stride3); + return dim1 + dim2 + dim3 + stride1 + stride2 + stride3; +} +// CHECK: define noundef i32 @TestGetDimensions()() +// CHECK: call void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) +// CHECK: call void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: call void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}} %dim3, ptr {{.*}} %stride3) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] +// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr +// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] +// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr +// CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]] +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] +// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr +// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] +// CHECK-NEXT: ret void + // DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) // DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i8) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) // DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i8) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32) + +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32) +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i32) +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index af312f9a815b8..413f402f87c97 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -65,7 +65,44 @@ export float TestLoad() { // CHECK-NEXT: %[[VAL:.*]] = load <2 x i32>, ptr %[[BUFPTR]] // CHECK-NEXT: ret <2 x i32> %[[VAL]] +export uint TestGetDimensions() { + uint dim1, dim2, stride1, stride2; + ROSB1.GetDimensions(dim1, stride1); + ROSB2.GetDimensions(dim2, stride2); + return dim1 + dim2 + stride1 + stride2; +} +// CHECK: define noundef i32 @TestGetDimensions()() +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[AAA:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[AAA]], ptr %[[NUMSTRUCTS_PTR]] +// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr +// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] +// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr +// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] +// CHECK-NEXT: ret void + // DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8) // DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i8) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32) + +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32) diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl index b153bda167a35..b23c8360d244c 100644 --- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl @@ -38,5 +38,39 @@ export float TestLoad() { // CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]] // CHECK-NEXT: ret <4 x i32> %[[VEC]] +export uint TestGetDimensions() { + uint dim1, dim2; + Buf.GetDimensions(dim1); + RWBuf.GetDimensions(dim2); + return dim1 + dim2; +} + +// CHECK: @TestGetDimensions()() +// CHECK: call void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}} %dim1) +// CHECK: call void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}} %dim2) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim) +// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]] +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim) +// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]] +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr +// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 poison) +// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] +// CHECK-NEXT: ret void + // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32) + +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) +// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32) diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 570d6bc35cbd0..38cd3f3e07a87 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -77,6 +77,10 @@ def int_dx_resource_updatecounter : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; +def int_dx_resource_getdimensions + : DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty], + [IntrReadMem]>; + // Cast between target extension handle types and dxil-style opaque handles def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; >From 2fd9c3a7a5e46fce4a740de3b9aba03ce122f975 Mon Sep 17 00:00:00 2001 From: Helena Kotas <[email protected]> Date: Wed, 8 Oct 2025 22:41:36 -0700 Subject: [PATCH 2/4] Change to buffer-specific LLVM intrinsic --- clang/lib/CodeGen/CGHLSLBuiltins.cpp | 48 ++----------------- clang/lib/CodeGen/CGHLSLRuntime.h | 2 + .../resources/ByteAddressBuffers-methods.hlsl | 10 ++-- .../StructuredBuffers-methods-lib.hlsl | 15 +++--- .../StructuredBuffers-methods-ps.hlsl | 12 ++--- .../resources/TypedBuffers-methods.hlsl | 10 ++-- llvm/include/llvm/IR/IntrinsicsDirectX.td | 5 +- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 3 ++ 8 files changed, 31 insertions(+), 74 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 373153e01c128..85d554d2ef158 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -160,48 +160,6 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { return LastInst; } -static Value *emitDXILGetDimensions(CodeGenFunction *CGF, Value *Handle, - Value *MipLevel, LValue *OutArg0, - LValue *OutArg1 = nullptr, - LValue *OutArg2 = nullptr, - LValue *OutArg3 = nullptr) { - assert(OutArg0 && "first output argument is required"); - - llvm::Type *I32 = CGF->Int32Ty; - StructType *RetTy = llvm::StructType::get(I32, I32, I32, I32); - - CallInst *CI = CGF->Builder.CreateIntrinsic( - RetTy, llvm::Intrinsic::dx_resource_getdimensions, - ArrayRef<Value *>{Handle, MipLevel}); - - Value *LastInst = nullptr; - unsigned OutArgIndex = 0; - for (LValue *OutArg : {OutArg0, OutArg1, OutArg2, OutArg3}) { - if (OutArg) { - Value *OutArgVal = CGF->Builder.CreateExtractValue(CI, OutArgIndex); - LastInst = CGF->Builder.CreateStore(OutArgVal, OutArg->getAddress()); - } - ++OutArgIndex; - } - assert(LastInst && "no output argument stored?"); - return LastInst; -} - -static Value *emitBufferGetDimensions(CodeGenFunction *CGF, Value *Handle, - LValue &Dim) { - // Generate the call to get the buffer dimension. - switch (CGF->CGM.getTarget().getTriple().getArch()) { - case llvm::Triple::dxil: - return emitDXILGetDimensions(CGF, Handle, PoisonValue::get(CGF->Int32Ty), - &Dim); - break; - case llvm::Triple::spirv: - llvm_unreachable("SPIR-V GetDimensions codegen not implemented yet."); - default: - llvm_unreachable("GetDimensions not supported by target architecture"); - } -} - static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr, LValue &Stride) { // Figure out the stride of the buffer elements from the handle type. @@ -414,7 +372,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, case Builtin::BI__builtin_hlsl_buffer_getdimensions: { Value *Handle = EmitScalarExpr(E->getArg(0)); LValue Dim = EmitLValue(E->getArg(1)); - return emitBufferGetDimensions(this, Handle, Dim); + llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext()); + Value *DimValue = Builder.CreateIntrinsic( + RetTy, CGM.getHLSLRuntime().getGetDimensionsBufferIntrinsic(), + ArrayRef<Value *>{Handle}); + return Builder.CreateStore(DimValue, Dim.getAddress()); } case Builtin::BI__builtin_hlsl_buffer_getstride: { LValue Stride = EmitLValue(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 7c6c2850fd4d4..5fd87d0b9a53c 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -135,6 +135,8 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) + GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsBuffer, + resource_getdimensions_buffer) //===----------------------------------------------------------------------===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl index f089c0cdf0ca3..4e4d882057d48 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl @@ -29,8 +29,7 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void @@ -38,10 +37,9 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0), i32) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0)) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index c3bb147ad4a53..6197cc5cd0a19 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -122,8 +122,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] @@ -133,8 +132,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]] @@ -144,8 +142,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] @@ -158,6 +155,6 @@ export uint TestGetDimensions() { // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0)) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index 413f402f87c97..652446ba805da 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -81,9 +81,8 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[AAA:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 -// CHECK-NEXT: store i32 %[[AAA]], ptr %[[NUMSTRUCTS_PTR]] +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]]) +// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] // CHECK-NEXT: ret void @@ -92,8 +91,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] @@ -104,5 +102,5 @@ export uint TestGetDimensions() { // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1)) diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl index b23c8360d244c..d3f7e19583906 100644 --- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl @@ -55,8 +55,7 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void @@ -64,13 +63,12 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 poison) -// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0 +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) -// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0)) diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 38cd3f3e07a87..855f2e522ba6b 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -77,9 +77,8 @@ def int_dx_resource_updatecounter : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; -def int_dx_resource_getdimensions - : DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty], - [IntrReadMem]>; +def int_dx_resource_getdimensions_buffer + : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>; // Cast between target extension handle types and dxil-style opaque handles def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 823c491e1bfee..c1476a0142c86 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -159,6 +159,9 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty] : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; + def int_spv_resource_getdimensions_buffer + : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>; + def int_spv_resource_getpointer : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty], [IntrNoMem]>; >From 135a858b473ce823de26271de896bff7fcec403a Mon Sep 17 00:00:00 2001 From: Helena Kotas <[email protected]> Date: Thu, 9 Oct 2025 14:04:40 -0700 Subject: [PATCH 3/4] Update builtins and intrinsic to *resource_getdimensions_x and *_resource_getstride --- clang/include/clang/Basic/Builtins.td | 6 +++--- clang/lib/CodeGen/CGHLSLBuiltins.cpp | 6 +++--- clang/lib/CodeGen/CGHLSLRuntime.h | 3 +-- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 ++++---- clang/lib/Sema/SemaHLSL.cpp | 4 ++-- clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +- clang/test/AST/HLSL/StructuredBuffers-AST.hlsl | 4 ++-- clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 2 +- .../resources/ByteAddressBuffers-methods.hlsl | 8 ++++---- .../resources/StructuredBuffers-methods-lib.hlsl | 12 ++++++------ .../resources/StructuredBuffers-methods-ps.hlsl | 8 ++++---- .../CodeGenHLSL/resources/TypedBuffers-methods.hlsl | 8 ++++---- llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +- 14 files changed, 37 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 0b1587be51217..90e549eda1aa2 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4951,14 +4951,14 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> { let Prototype = "uint32_t(uint32_t)"; } -def HLSLResourceGetDimensions : LangBuiltin<"HLSL_LANG"> { - let Spellings = ["__builtin_hlsl_buffer_getdimensions"]; +def HLSLResourceGetDimensionsX : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_x"]; let Attributes = [NoThrow]; let Prototype = "void(...)"; } def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> { - let Spellings = ["__builtin_hlsl_buffer_getstride"]; + let Spellings = ["__builtin_hlsl_resource_getstride"]; let Attributes = [NoThrow]; let Prototype = "void(...)"; } diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 85d554d2ef158..11c6231704ebb 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -369,16 +369,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(), ArrayRef<Value *>{IndexOp}); } - case Builtin::BI__builtin_hlsl_buffer_getdimensions: { + case Builtin::BI__builtin_hlsl_resource_getdimensions_x: { Value *Handle = EmitScalarExpr(E->getArg(0)); LValue Dim = EmitLValue(E->getArg(1)); llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext()); Value *DimValue = Builder.CreateIntrinsic( - RetTy, CGM.getHLSLRuntime().getGetDimensionsBufferIntrinsic(), + RetTy, CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(), ArrayRef<Value *>{Handle}); return Builder.CreateStore(DimValue, Dim.getAddress()); } - case Builtin::BI__builtin_hlsl_buffer_getstride: { + case Builtin::BI__builtin_hlsl_resource_getstride: { LValue Stride = EmitLValue(E->getArg(1)); return emitBufferStride(this, E->getArg(0), Stride); } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 5fd87d0b9a53c..103b4a98f6c26 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -135,8 +135,7 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) - GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsBuffer, - resource_getdimensions_buffer) + GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x) //===----------------------------------------------------------------------===// // End of reserved area for HLSL intrinsic getters. diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index d6d6b31aa2d9d..38edba36633d4 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1186,10 +1186,10 @@ BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() { return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out) .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out) - .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(), + .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(), PH::Handle, PH::_0) - .callBuiltin("__builtin_hlsl_buffer_getstride", QualType(), PH::Handle, - PH::_1) + .callBuiltin("__builtin_hlsl_resource_getstride", QualType(), + PH::Handle, PH::_1) .finalize(); } @@ -1197,7 +1197,7 @@ BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() { // GetDimensions(out uint dim). return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out) - .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(), + .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(), PH::Handle, PH::_0) .finalize(); } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e3281c493da50..4c0981d78ab65 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2978,7 +2978,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { TheCall->setType(ResourceTy); break; } - case Builtin::BI__builtin_hlsl_buffer_getdimensions: { + case Builtin::BI__builtin_hlsl_resource_getdimensions_x: { ASTContext &AST = SemaRef.getASTContext(); if (SemaRef.checkArgCount(TheCall, 2) || CheckResourceHandle(&SemaRef, TheCall, 0) || @@ -2987,7 +2987,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } - case Builtin::BI__builtin_hlsl_buffer_getstride: { + case Builtin::BI__builtin_hlsl_resource_getstride: { ASTContext &AST = SemaRef.getASTContext(); if (SemaRef.checkArgCount(TheCall, 2) || CheckResourceHandle(&SemaRef, TheCall, 0) || diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl index a2058b29401c0..9ecd6dbb6456f 100644 --- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl @@ -150,7 +150,7 @@ RESOURCE Buffer; // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr> -// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) 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 e5f4b22fe2a10..7cfb4126824c0 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -344,13 +344,13 @@ RESOURCE<float> Buffer; // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr> -// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) 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_buffer_getstride' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getstride' 'void (...) 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 07f04001a58ae..44a866397f68b 100644 --- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl @@ -222,7 +222,7 @@ RESOURCE<float> Buffer; // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr> -// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) 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' diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl index 4e4d882057d48..2b235da4ba6c7 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl @@ -29,7 +29,7 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void @@ -37,9 +37,9 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0)) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0)) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index 6197cc5cd0a19..a98d2bbdca6f4 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -122,7 +122,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] @@ -132,7 +132,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]] @@ -142,7 +142,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] @@ -155,6 +155,6 @@ export uint TestGetDimensions() { // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0)) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0)) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0)) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index 652446ba805da..dfc7ddb41731d 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -81,7 +81,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]]) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] @@ -91,7 +91,7 @@ export uint TestGetDimensions() { // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle // CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr -// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]]) +// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] @@ -102,5 +102,5 @@ export uint TestGetDimensions() { // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1)) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1)) diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl index d3f7e19583906..3df904ba8421c 100644 --- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl @@ -55,7 +55,7 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void @@ -63,12 +63,12 @@ export uint TestGetDimensions() { // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]] // CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr -// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]]) +// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]]) // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) // DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0)) -// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0)) +// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0)) diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 855f2e522ba6b..3b7077c52db21 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -77,7 +77,7 @@ def int_dx_resource_updatecounter : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; -def int_dx_resource_getdimensions_buffer +def int_dx_resource_getdimensions_x : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>; // Cast between target extension handle types and dxil-style opaque handles diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index c1476a0142c86..7b27b46668ea9 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -159,7 +159,7 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty] : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty], [IntrInaccessibleMemOrArgMemOnly]>; - def int_spv_resource_getdimensions_buffer + def int_spv_resource_getdimensions_x : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>; def int_spv_resource_getpointer >From c8f1da3860789367312112a65d7620ca8be1962d Mon Sep 17 00:00:00 2001 From: Helena Kotas <[email protected]> Date: Thu, 16 Oct 2025 10:42:28 -0700 Subject: [PATCH 4/4] Update code that creates a method with out parameters after #163648 fix --- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 ++++++++----------- .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +- .../test/AST/HLSL/StructuredBuffers-AST.hlsl | 2 +- clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 2 +- .../resources/ByteAddressBuffers-methods.hlsl | 4 ++-- .../StructuredBuffers-methods-lib.hlsl | 6 ++--- .../StructuredBuffers-methods-ps.hlsl | 4 ++-- .../resources/TypedBuffers-methods.hlsl | 4 ++-- 8 files changed, 22 insertions(+), 25 deletions(-) diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 38edba36633d4..9722ee2f6de07 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -449,21 +449,19 @@ void BuiltinTypeMethodBuilder::createDecl() { SmallVector<QualType> ParamTypes; SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size()); uint32_t ArgIndex = 0; - bool IsTemplate = DeclBuilder.Template != nullptr; + + // Create function prototype. bool UseParamExtInfo = false; for (Param &MP : Params) { - QualType Ty = MP.Ty; if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) { UseParamExtInfo = true; - ParamExtInfos[ArgIndex].withABI( - convertParamModifierToParamABI(MP.Modifier)); - // Only update types on inout and out parameters for non-templated - // methods. Templated types will have their inout/out parameters - // converted to references during template instantiation. - if (!IsTemplate) - Ty = getInoutParameterType(AST, Ty); + FunctionType::ExtParameterInfo &PI = ParamExtInfos[ArgIndex]; + ParamExtInfos[ArgIndex] = + PI.withABI(convertParamModifierToParamABI(MP.Modifier)); + if (!MP.Ty->isDependentType()) + MP.Ty = getInoutParameterType(AST, MP.Ty); } - ParamTypes.emplace_back(Ty); + ParamTypes.emplace_back(MP.Ty); ++ArgIndex; } @@ -475,7 +473,7 @@ void BuiltinTypeMethodBuilder::createDecl() { QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo); - // create method or constructor decl + // Create method or constructor declaration. auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation()); DeclarationNameInfo NameInfo = DeclarationNameInfo(Name, SourceLocation()); if (IsCtor) @@ -488,7 +486,7 @@ void BuiltinTypeMethodBuilder::createDecl() { AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, SC, false, false, ConstexprSpecKind::Unspecified, SourceLocation()); - // create params & set them to the function prototype + // Create params & set them to the method/constructor and function prototype. SmallVector<ParmVarDecl *> ParmDecls; unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth(); auto FnProtoLoc = @@ -501,7 +499,6 @@ void BuiltinTypeMethodBuilder::createDecl() { AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None, nullptr); if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) { - Parm->setType(getInoutParameterType(AST, Parm->getType())); auto *Mod = HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier); Parm->addAttr(Mod); diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl index 9ecd6dbb6456f..61d5e5ab44c97 100644 --- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl @@ -144,7 +144,7 @@ RESOURCE Buffer; // GetDimensions method -// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int &__restrict)' +// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int)' // CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} out // CHECK-NEXT: CompoundStmt diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl index 7cfb4126824c0..0a83c22c4cd22 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -336,7 +336,7 @@ RESOURCE<float> Buffer; // GetDimensions method -// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, unsigned int)' +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int, out unsigned int)' // CHECK-NEXT: ParmVarDecl {{.*}} numStructs 'unsigned int &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} out // CHECK-NEXT: ParmVarDecl {{.*}} stride 'unsigned int &__restrict' diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl index 44a866397f68b..14e274d3855ed 100644 --- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl @@ -216,7 +216,7 @@ RESOURCE<float> Buffer; // GetDimensions method -// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int)' +// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int)' // CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} out // CHECK-NEXT: CompoundStmt diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl index 2b235da4ba6c7..9dd02287620e7 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl @@ -20,8 +20,8 @@ export uint TestGetDimensions() { } // CHECK: define {{.*}} @TestGetDimensions()() -// CHECK: call void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr{{.*}} %dim1) -// CHECK: call void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr{{.*}} @RWBuf, ptr{{.*}} %dim2) +// CHECK: call void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr{{.*}}) +// CHECK: call void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr{{.*}} @RWBuf, ptr{{.*}}) // CHECK: add // CHECK: ret diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index a98d2bbdca6f4..4a35cbc3d7dc5 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -112,9 +112,9 @@ export uint TestGetDimensions() { return dim1 + dim2 + dim3 + stride1 + stride2 + stride3; } // CHECK: define noundef i32 @TestGetDimensions()() -// CHECK: call void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) -// CHECK: call void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) -// CHECK: call void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}} %dim3, ptr {{.*}} %stride3) +// CHECK: call void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}}, ptr {{.*}}) // CHECK: add // CHECK: ret diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index dfc7ddb41731d..96bd143e3dd72 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -72,8 +72,8 @@ export uint TestGetDimensions() { return dim1 + dim2 + stride1 + stride2; } // CHECK: define noundef i32 @TestGetDimensions()() -// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) -// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}}, ptr {{.*}}) // CHECK: add // CHECK: ret diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl index 3df904ba8421c..fdc1ef08b7c2c 100644 --- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl @@ -46,8 +46,8 @@ export uint TestGetDimensions() { } // CHECK: @TestGetDimensions()() -// CHECK: call void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}} %dim1) -// CHECK: call void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}} %dim2) +// CHECK: call void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}}) +// CHECK: call void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}}) // CHECK: add // CHECK: ret _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
