diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 0af38472b0fec..e09d99fcab100 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1360,7 +1360,8 @@ bool SemaHLSL::handleRootSignatureElements( "Number of unbound elements must match the number of clauses"); bool HasAnySampler = false; bool HasAnyNonSampler = false; - uint32_t Offset = 0; + uint64_t Offset = 0; + bool IsPrevUnbound = false; for (const auto &[Clause, ClauseElem] : UnboundClauses) { SourceLocation Loc = ClauseElem->getLocation(); if (Clause->Type == llvm::dxil::ResourceClass::Sampler) @@ -1377,32 +1378,28 @@ bool SemaHLSL::handleRootSignatureElements( if (Clause->NumDescriptors == 0) return true; - if (Clause->Offset != - llvm::hlsl::rootsig::DescriptorTableOffsetAppend) { - // Manually specified the offset + bool IsAppending = + Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend; + if (!IsAppending) Offset = Clause->Offset; - } uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( Offset, Clause->NumDescriptors); - if (!llvm::hlsl::rootsig::verifyBoundOffset(Offset)) { - // Trying to append onto unbound offset + if (IsPrevUnbound && IsAppending) Diag(Loc, diag::err_hlsl_appending_onto_unbound); - } else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) { - // Upper bound overflows maximum offset + else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound)) Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound; - } - Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded - ? uint32_t(RangeBound) - : uint32_t(RangeBound + 1); + // Update offset to be 1 past this range's bound + Offset = RangeBound + 1; + IsPrevUnbound = Clause->NumDescriptors == + llvm::hlsl::rootsig::NumDescriptorsUnbounded; // Compute the register bounds and track resource binding uint32_t LowerBound(Clause->Reg.Number); - uint32_t UpperBound = Clause->NumDescriptors == ~0u - ? ~0u - : LowerBound + Clause->NumDescriptors - 1; + uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound( + LowerBound, Clause->NumDescriptors); BindingChecker.trackBinding( Table->Visibility, diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl index 2d025d0e6e5ce..cb2569f380b2c 100644 --- a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl +++ b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl @@ -141,4 +141,12 @@ void append_offset_overflow_signature() {} // expected-error@+1 {{descriptor range offset overflows [4294967292, 4294967296]}} [RootSignature("DescriptorTable(CBV(b0, offset = 4294967292, numDescriptors = 5))")] -void offset_() {} +void offset_overflow() {} + +// expected-error@+1 {{descriptor range offset overflows [4294967295, 4294967296]}} +[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1, numDescriptors = 2))")] +void appended_offset_overflow() {} + +// expected-error@+1 {{descriptor range offset overflows [4294967296, 4294967296]}} +[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1), CBV(b2))")] +void multiple_appended_offset_overflow() {} diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl index 10e7215eccf6e..37bb4f173aac4 100644 --- a/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl +++ b/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl @@ -25,3 +25,6 @@ void valid_root_signature_6() {} [RootSignature("DescriptorTable(CBV(b0, offset = 4294967292), CBV(b1, numDescriptors = 3))")] void valid_root_signature_7() {} + +[RootSignature("DescriptorTable(CBV(b0, offset = 4294967294), CBV(b1))")] +void valid_root_signature_8() {} diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index ea96094b18300..49c5967aebd3e 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -38,9 +38,8 @@ LLVM_ABI bool verifyMipLODBias(float MipLODBias); LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyLOD(float LOD); -LLVM_ABI bool verifyBoundOffset(uint32_t Offset); LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset); -LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size); +LLVM_ABI uint64_t computeRangeBound(uint64_t Offset, uint32_t Size); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 0970977b5064f..c2c3bf6d1b8dc 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -125,20 +125,16 @@ bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } -bool verifyBoundOffset(uint32_t Offset) { - return Offset != NumDescriptorsUnbounded; -} - bool verifyNoOverflowedOffset(uint64_t Offset) { return Offset <= std::numeric_limits::max(); } -uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) { +uint64_t computeRangeBound(uint64_t Offset, uint32_t Size) { assert(0 < Size && "Must be a non-empty range"); if (Size == NumDescriptorsUnbounded) return NumDescriptorsUnbounded; - return uint64_t(Offset) + uint64_t(Size) - 1; + return Offset + uint64_t(Size) - 1; } } // namespace rootsig