From 8ba74ceb7e7dd2e9d6ed0503b37c31ed9d253190 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Fri, 3 Oct 2025 12:14:28 -0700 Subject: [PATCH 1/7] [HLSL][NFC] Refactor method tests for structured buffers Refactoring structured buffer tests to make it clearer that - the test functions call the buffer methods - the buffer methods are defined after each test function - show what the buffer methods bodies look like - use buffers with different element types, not just `float` - use `llvm-cxxfilt` tool to de-mangle names --- .../StructuredBuffers-methods-lib.hlsl | 116 +++++++++++++----- .../StructuredBuffers-methods-ps.hlsl | 74 ++++++++--- 2 files changed, 136 insertions(+), 54 deletions(-) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index 43ddd2e768ea0..a506c2b50b1dc 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -1,64 +1,112 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV +// 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,SPV // NOTE: SPIRV codegen for resource methods is not yet implemented StructuredBuffer SB1 : register(t0); RWStructuredBuffer RWSB1 : register(u0); -RWStructuredBuffer RWSB2 : register(u1); +RWStructuredBuffer RWSB2 : register(u1); AppendStructuredBuffer ASB : register(u2); -ConsumeStructuredBuffer CSB : register(u3); +ConsumeStructuredBuffer CSB : register(u3); -// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) } -// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } -// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } -// CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } +// DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) } +// DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } +// DXIL: %"class.hlsl::RWStructuredBuffer.0" = type { target("dx.RawBuffer", <4 x i32>, 1, 0), target("dx.RawBuffer", <4 x i32>, 1, 0) } +// DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } +// DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", double, 1, 0), target("dx.RawBuffer", double, 1, 0) } export int TestIncrementCounter() { return RWSB1.IncrementCounter(); } -// CHECK: define noundef i32 @_Z20TestIncrementCounterv() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) -// CHECK-DXIL: ret i32 %[[INDEX]] +// CHECK: define noundef i32 @TestIncrementCounter()() +// CHECK: call noundef i32 @hlsl::RWStructuredBuffer::IncrementCounter()(ptr {{.*}} @RWSB1) +// CHECK: ret + +// CHECK: define {{.*}} noundef i32 @hlsl::RWStructuredBuffer::IncrementCounter()(ptr {{.*}} %this) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle, align 4 +// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i8 1) +// CHECK-NEXT: ret i32 %[[COUNTER]] + export int TestDecrementCounter() { return RWSB2.DecrementCounter(); } +// CHECK: define {{.*}} i32 @TestDecrementCounter()() +// CHECK: call noundef i32 @hlsl::RWStructuredBuffer::DecrementCounter()(ptr {{.*}} @RWSB2) +// CHECK: ret -// CHECK: define noundef i32 @_Z20TestDecrementCounterv() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) -// CHECK-DXIL: ret i32 %[[INDEX]] +// CHECK: define {{.*}} noundef i32 @hlsl::RWStructuredBuffer::DecrementCounter()(ptr {{.*}} %this) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle, align 4 +// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i8 -1) +// CHECK-NEXT: ret i32 %[[COUNTER]] export void TestAppend(float value) { ASB.Append(value); } -// CHECK: define void @_Z10TestAppendf(float noundef nofpclass(nan inf) %value) -// CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %value.addr, align 4 -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) -// CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %[[INDEX]]) -// CHECK-DXIL: store float %[[VALUE]], ptr %[[RESPTR]], align 4 +// CHECK: define void @TestAppend(float)(float {{.*}} %value) +// CHECK: call void @hlsl::AppendStructuredBuffer::Append(float)(ptr {{.*}} @ASB, float noundef nofpclass(nan inf) %0) +// CHECK: ret void + +// CHECK: define {{.*}} void @hlsl::AppendStructuredBuffer::Append(float)(ptr {{.*}} %this, float noundef nofpclass(nan inf) %value) +// CHECK: %[[VALUE:.*]] = load float, ptr %value.addr +// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle, align 4 +// CHECK-NEXT: %__handle2 = getelementptr inbounds nuw %"class.hlsl::AppendStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE2:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle2, align 4 +// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE2]], i8 1) +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i32 %[[COUNTER]]) +// CHECK-NEXT: store float %[[VALUE]], ptr %[[PTR]], align 4 +// CHECK-NEXT: ret void -export float TestConsume() { +export double TestConsume() { return CSB.Consume(); } - -// CHECK: define noundef nofpclass(nan inf) float @_Z11TestConsumev() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %1, i8 -1) -// CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %0, i32 %[[INDEX]]) -// CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %[[RESPTR]], align 4 -// CHECK-DXIL: ret float %[[VALUE]] +// CHECK: define {{.*}} double @TestConsume()() +// CHECK: call {{.*}} double @hlsl::ConsumeStructuredBuffer::Consume()(ptr {{.*}} @CSB) +// CHECK: ret double + +// CHECK: define {{.*}} double @hlsl::ConsumeStructuredBuffer::Consume()(ptr {{.*}} %this) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle, align 4 +// CHECK-NEXT: %__handle2 = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE2:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle2, align 4 +// DXIL-NEXT: %[[COUNTER:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE2]], i8 -1) +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 %[[COUNTER]]) +// CHECK-NEXT: %[[VAL:.*]] = load double, ptr %[[PTR]], align 8 +// CHECK-NEXT: ret double %[[VAL]] export float TestLoad() { return RWSB1.Load(1) + SB1.Load(2); } -// CHECK: define noundef nofpclass(nan inf) float @_Z8TestLoadv() -// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %{{[0-9]+}}) -// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]] -// CHECK: %[[PTR2:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %{{[0-9]+}}, i32 %{{[0-9]+}}) -// CHECK: %[[VALUE2:.*]] = load float, ptr %[[PTR2]] +// CHECK: define noundef nofpclass(nan inf) float @TestLoad()() +// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1) +// CHECK: call {{.*}} float @hlsl::StructuredBuffer::Load(unsigned int)(ptr {{.*}} @SB1, i32 noundef 2) +// CHECK: add +// CHECK: ret float + +// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle, align 4 +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr, align 4 +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]], align 4 +// CHECK-NEXT: ret float %[[VAL]] + +// CHECK: define {{.*}} float @hlsl::StructuredBuffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle, align 4 +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr, align 4 +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]], align 4 +// CHECK-NEXT: ret float %[[VAL]] -// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) -// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) -// CHECK: 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.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) diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index 9e08a6d0d7ae0..af312f9a815b8 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -1,37 +1,71 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-pixel -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -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-pixel -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPV // NOTE: SPIRV codegen for resource methods is not yet implemented -RWStructuredBuffer RWSB1, RWSB2; -RasterizerOrderedStructuredBuffer ROSB1, ROSB2; +RasterizerOrderedStructuredBuffer ROSB1; +RasterizerOrderedStructuredBuffer ROSB2; -// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), target("dx.RawBuffer", float, 1, 0) } +// %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1), target("dx.RawBuffer", float, 1, 1) } +// %"class.hlsl::RasterizerOrderedStructuredBuffer.0" = type { target("dx.RawBuffer", <2 x i32>, 1, 1), target("dx.RawBuffer", <2 x i32>, 1, 1) } + +// CHECK: @ROSB1 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison +// CHECK: @ROSB2 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer.0" poison export void TestIncrementCounter() { -// CHECK: define void @_Z20TestIncrementCounterv() -// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) -// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 1) - RWSB1.IncrementCounter(); ROSB1.IncrementCounter(); } +// CHECK: define void @TestIncrementCounter()() +// CHECK: call noundef i32 @hlsl::RasterizerOrderedStructuredBuffer::IncrementCounter()(ptr {{.*}} @ROSB1) +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} i32 @hlsl::RasterizerOrderedStructuredBuffer::IncrementCounter()(ptr {{.*}} %this) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle +// DXIL-NEXT: %[[VAL:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i8 1) +// CHECK-NEXT: ret i32 %[[VAL]] + export void TestDecrementCounter() { -// CHECK: define void @_Z20TestDecrementCounterv() -// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) -// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 -1) - RWSB2.DecrementCounter(); ROSB2.DecrementCounter(); } +// CHECK: define void @TestDecrementCounter()() +// CHECK: call noundef i32 @hlsl::RasterizerOrderedStructuredBuffer::DecrementCounter()(ptr {{.*}} @ROSB2) +// CHECK-NEXT: ret void + +// CHECK: define {{.*}} i32 @hlsl::RasterizerOrderedStructuredBuffer::DecrementCounter()(ptr {{.*}} %this) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle +// DXIL-NEXT: %[[VAL:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i8 -1) +// CHECK-NEXT: ret i32 %[[VAL]] + export float TestLoad() { - return ROSB1.Load(10); + return ROSB1.Load(10).x + ROSB2.Load(20).x; } -// CHECK: define noundef nofpclass(nan inf) float @_Z8TestLoadv() -// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i32 %{{[0-9]+}}) -// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]] +// CHECK: define {{.*}} float @TestLoad()() +// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer::Load(unsigned int)(ptr {{.*}} @ROSB1, i32 noundef 10) +// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer::Load(unsigned int)(ptr {{.*}} @ROSB2, i32 noundef 20) +// CHECK: ret + +// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer::Load(unsigned int)(ptr {{.*}} %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr {{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr +// DXIL-NEXT: %[[BUFPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[BUFPTR]] +// CHECK-NEXT: ret float %[[VAL]] + +// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer::Load(unsigned int)(ptr {{.*}} %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr {{.*}}, i32 0, i32 0 +// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr +// DXIL-NEXT: %[[BUFPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VAL:.*]] = load <2 x i32>, ptr %[[BUFPTR]] +// CHECK-NEXT: ret <2 x i32> %[[VAL]] -// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) -// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8) -// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) +// 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) From d42f931879a1a563a2204abc5604b509f798cc46 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Fri, 3 Oct 2025 14:06:38 -0700 Subject: [PATCH 2/7] [HLSL][NFC] Add test coverage for Buffer Test coverage for `Buffer` resource class was not sufficient. All of the typed buffer tests were using RWBuffer. This change adds `Buffer` tests cases to several existing `RWBuffer-*.test` files and renames them to `TypedBuffer-*.test`. Also adds new `TypedBuffers-methods.tests`. --- .../resources/RWBuffer-elementtype.hlsl | 70 -------------- .../resources/RWBuffer-subscript.hlsl | 26 ----- ...tor.hlsl => TypedBuffers-constructor.hlsl} | 36 +++---- .../resources/TypedBuffers-elementtype.hlsl | 94 +++++++++++++++++++ .../resources/TypedBuffers-subscript.hlsl | 26 +++++ .../resources/TypesBuffers-methods.hlsl | 42 +++++++++ 6 files changed, 180 insertions(+), 114 deletions(-) delete mode 100644 clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl delete mode 100644 clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl rename clang/test/CodeGenHLSL/resources/{RWBuffer-constructor.hlsl => TypedBuffers-constructor.hlsl} (77%) create mode 100644 clang/test/CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl create mode 100644 clang/test/CodeGenHLSL/resources/TypedBuffers-subscript.hlsl create mode 100644 clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl deleted file mode 100644 index f48521b0f1764..0000000000000 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-elementtype.hlsl +++ /dev/null @@ -1,70 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL -// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPIRV - -// DXIL: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", i16, 1, 0, 1) } -// DXIL: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", i16, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", i32, 1, 0, 1) } -// DXIL: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i64, 1, 0, 1) } -// DXIL: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", half, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.6" = type { target("dx.TypedBuffer", float, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.7" = type { target("dx.TypedBuffer", double, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 1) } -// DXIL: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0) } -// DXIL: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <4 x i32>, 1, 0, 1) } - -// SPIRV: %"class.hlsl::RWBuffer" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.0" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 24) } -// SPIRV: %"class.hlsl::RWBuffer.2" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 33) } -// SPIRV: %"class.hlsl::RWBuffer.3" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 41) } -// SPIRV: %"class.hlsl::RWBuffer.4" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 40) } -// SPIRV: %"class.hlsl::RWBuffer.5" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 3) } -// SPIRV: %"class.hlsl::RWBuffer.7" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.8" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.9" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.10" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.11" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) } -// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 21) } - -RWBuffer BufI16; -RWBuffer BufU16; -RWBuffer BufI32; -RWBuffer BufU32; -RWBuffer BufI64; -RWBuffer BufU64; -RWBuffer BufF16; -RWBuffer BufF32; -RWBuffer BufF64; -RWBuffer< vector > BufI16x4; -RWBuffer< vector > BufU32x3; -RWBuffer BufF16x2; -RWBuffer BufF32x3; -RWBuffer BufI32x4; -// TODO: RWBuffer BufSNormF16; -> 11 -// TODO: RWBuffer BufUNormF16; -> 12 -// TODO: RWBuffer BufSNormF32; -> 13 -// TODO: RWBuffer BufUNormF32; -> 14 -// TODO: RWBuffer BufSNormF64; -> 15 -// TODO: RWBuffer BufUNormF64; -> 16 - -[numthreads(1,1,1)] -void main(int GI : SV_GroupIndex) { - BufI16[GI] = 0; - BufU16[GI] = 0; - BufI32[GI] = 0; - BufU32[GI] = 0; - BufI64[GI] = 0; - BufU64[GI] = 0; - BufF16[GI] = 0; - BufF32[GI] = 0; - BufF64[GI] = 0; - BufI16x4[GI] = 0; - BufU32x3[GI] = 0; - BufF16x2[GI] = 0; - BufF32x3[GI] = 0; -} diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl deleted file mode 100644 index 0de171cb452d8..0000000000000 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-subscript.hlsl +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=DXC,CHECK -// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -fspv-use-unknown-image-format -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK - -RWBuffer In; -RWBuffer Out; - -[numthreads(1,1,1)] -void main(unsigned GI : SV_GroupIndex) { - // CHECK: define void @main() - - // DXC: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) - // SPIRV: %[[INPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) - // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]] - // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) - // SPIRV: %[[OUTPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) - // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]] - Out[GI] = In[GI]; - - // DXC: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) - // SPIRV: %[[INPTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) - // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]] - // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) - // SPIRV: %[[OUTPTR:.*]] = call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) - // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]] - Out[GI] = In.Load(GI); -} diff --git a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-constructor.hlsl similarity index 77% rename from clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl rename to clang/test/CodeGenHLSL/resources/TypedBuffers-constructor.hlsl index ca33c4220dd73..1ec9f0f54441e 100644 --- a/clang/test/CodeGenHLSL/resources/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-constructor.hlsl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | \ -// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL +// RUN: llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL // FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding and resource types is not yet implemented // RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | \ // llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV @@ -14,7 +14,7 @@ RWBuffer Buf1 : register(u5, space3); // Resource with implicit binding -RWBuffer Buf2; +Buffer Buf2; export void foo() { // Local resource declaration @@ -22,12 +22,12 @@ export void foo() { } // CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 0, 0) } -// CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", double, 1, 0, 0) } -// CHECK: %"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", i32, 1, 0, 1) } +// CHECK: %"class.hlsl::Buffer" = type { target("dx.TypedBuffer", double, 0, 0, 0) } +// CHECK: %"class.hlsl::RWBuffer.0" = type { target("dx.TypedBuffer", i32, 1, 0, 1) } // CHECK: @Buf1 = internal global %"class.hlsl::RWBuffer" poison, align 4 // CHECK: @[[Buf1Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf1\00", align 1 -// CHECK: @Buf2 = internal global %"class.hlsl::RWBuffer.0" poison, align 4 +// CHECK: @Buf2 = internal global %"class.hlsl::Buffer" poison, align 4 // CHECK: @[[Buf2Str:.*]] = private unnamed_addr constant [5 x i8] c"Buf2\00", align 1 // Buf1 initialization part 1 - global init function that calls RWBuffer::__createFromBinding @@ -50,24 +50,24 @@ export void foo() { // Buf2 initialization part 1 - global init function that RWBuffer::__createFromImplicitBinding // CHECK: define internal void @__cxx_global_var_init.1() // CHECK-NEXT: entry: -// CHECK-NEXT: call void @hlsl::RWBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-NEXT: call void @hlsl::Buffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) // CHECK-SAME: (ptr {{.*}} @Buf2, i32 noundef 0, i32 noundef 0, i32 noundef 1, i32 noundef 0, ptr noundef @[[Buf2Str]]) -// Buf2 initialization part 2 - body of RWBuffer::__createFromImplicitBinding call -// CHECK: define linkonce_odr hidden void @hlsl::RWBuffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) -// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer.0") align 4 %[[RetValue2:.*]], i32 noundef %orderId, +// Buf2 initialization part 2 - body of Buffer::__createFromImplicitBinding call +// CHECK: define linkonce_odr hidden void @hlsl::Buffer::__createFromImplicitBinding(unsigned int, unsigned int, int, unsigned int, char const*) +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::Buffer") align 4 %[[RetValue2:.*]], i32 noundef %orderId, // CHECK-SAME: i32 noundef %spaceNo, i32 noundef %range, i32 noundef %index, ptr noundef %name) -// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::RWBuffer.0", align 4 -// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 1, 0, 0) -// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_1_0_0t( -// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %[[Tmp2]], i32 0, i32 0 -// CHECK-DXIL: store target("dx.TypedBuffer", double, 1, 0, 0) %[[Handle2]], ptr %__handle, align 4 -// CHECK: call void @hlsl::RWBuffer::RWBuffer(hlsl::RWBuffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]]) +// CHECK: %[[Tmp2:.*]] = alloca %"class.hlsl::Buffer", align 4 +// CHECK: %[[Handle2:.*]] = call target("dx.TypedBuffer", double, 0, 0, 0) +// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.TypedBuffer_f64_0_0_0t( +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %[[Tmp2]], i32 0, i32 0 +// CHECK-DXIL: store target("dx.TypedBuffer", double, 0, 0, 0) %[[Handle2]], ptr %__handle, align 4 +// CHECK: call void @hlsl::Buffer::Buffer(hlsl::Buffer const&)(ptr {{.*}} %[[RetValue2]], ptr {{.*}} %[[Tmp2]]) // Buf3 initialization part 1 - local variable declared in function foo() is initialized by RWBuffer C1 default constructor // CHECK: define void @foo() // CHECK-NEXT: entry: -// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RWBuffer.1", align 4 +// CHECK-NEXT: %Buf3 = alloca %"class.hlsl::RWBuffer.0", align 4 // CHECK-NEXT: call void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %Buf3) // Buf3 initialization part 2 - body of RWBuffer default C1 constructor that calls the default C2 constructor @@ -76,11 +76,11 @@ export void foo() { // Buf3 initialization part 3 - body of RWBuffer default C2 constructor that initializes handle to poison // CHECK: define linkonce_odr hidden void @hlsl::RWBuffer::RWBuffer()(ptr {{.*}} %this) -// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.1", ptr %{{.*}}, i32 0, i32 0 +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer.0", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: store target("dx.TypedBuffer", i32, 1, 0, 1) poison, ptr %__handle, align 4 // Module initialization -// CHECK: define internal void @_GLOBAL__sub_I_RWBuffer_constructor.hlsl() +// CHECK: define internal void @_GLOBAL__sub_I_TypedBuffers_constructor.hlsl() // CHECK-NEXT: entry: // CHECK-NEXT: call void @__cxx_global_var_init() // CHECK-NEXT: call void @__cxx_global_var_init.1() diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl new file mode 100644 index 0000000000000..d3dba8a69cc72 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type \ +// RUN: -emit-llvm -o - -DRESOURCE=Buffer %s | FileCheck %s -DRESOURCE=Buffer -DRW=0 -check-prefixes=DXIL + +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type \ +// RUN: -emit-llvm -o - -DRESOURCE=Buffer %s | FileCheck %s -DRESOURCE=Buffer -DRW=1 -check-prefixes=SPV-RO + +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type \ +// RUN: -emit-llvm -o - -DRESOURCE=RWBuffer %s | FileCheck %s -DRESOURCE=RWBuffer -DRW=1 -check-prefixes=DXIL + +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type \ +// RUN: -emit-llvm -o - -DRESOURCE=RWBuffer %s | FileCheck %s -DRESOURCE=RWBuffer --DRW=2 -check-prefixes=SPV-RW + +// DXIL: %"class.hlsl::[[RESOURCE]]" = type { target("dx.TypedBuffer", i16, [[RW]], 0, 1) } +// DXIL: %"class.hlsl::[[RESOURCE]].0" = type { target("dx.TypedBuffer", i16, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].1" = type { target("dx.TypedBuffer", i32, [[RW]], 0, 1) } +// DXIL: %"class.hlsl::[[RESOURCE]].2" = type { target("dx.TypedBuffer", i32, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].3" = type { target("dx.TypedBuffer", i64, [[RW]], 0, 1) } +// DXIL: %"class.hlsl::[[RESOURCE]].4" = type { target("dx.TypedBuffer", i64, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].5" = type { target("dx.TypedBuffer", half, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].6" = type { target("dx.TypedBuffer", float, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].7" = type { target("dx.TypedBuffer", double, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].8" = type { target("dx.TypedBuffer", <4 x i16>, [[RW]], 0, 1) } +// DXIL: %"class.hlsl::[[RESOURCE]].9" = type { target("dx.TypedBuffer", <3 x i32>, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].10" = type { target("dx.TypedBuffer", <2 x half>, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].11" = type { target("dx.TypedBuffer", <3 x float>, [[RW]], 0, 0) } +// DXIL: %"class.hlsl::[[RESOURCE]].12" = type { target("dx.TypedBuffer", <4 x i32>, [[RW]], 0, 1) } + +// SPV-RO: %"class.hlsl::[[RESOURCE]]" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].0" = type { target("spirv.Image", i16, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].2" = type { target("spirv.Image", i32, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].3" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].4" = type { target("spirv.Image", i64, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].5" = type { target("spirv.Image", half, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].6" = type { target("spirv.Image", float, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].7" = type { target("spirv.Image", double, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].8" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].9" = type { target("spirv.Image", i32, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].10" = type { target("spirv.Image", half, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].11" = type { target("spirv.Image", float, 5, 2, 0, 0, 1, 0) } +// SPV-RO: %"class.hlsl::[[RESOURCE]].12" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 1, 0) } + +// SPV-RW: %"class.hlsl::[[RESOURCE]]" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].0" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].1" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 24) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].2" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 33) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].3" = type { target("spirv.SignedImage", i64, 5, 2, 0, 0, 2, 41) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].4" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 40) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].5" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].6" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 3) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].7" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].8" = type { target("spirv.SignedImage", i16, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].9" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].10" = type { target("spirv.Image", half, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].11" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0) } +// SPV-RW: %"class.hlsl::[[RESOURCE]].12" = type { target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 21) } + +RESOURCE BufI16; +RESOURCE BufU16; +RESOURCE BufI32; +RESOURCE BufU32; +RESOURCE BufI64; +RESOURCE BufU64; +RESOURCE BufF16; +RESOURCE BufF32; +RESOURCE BufF64; +RESOURCE< vector > BufI16x4; +RESOURCE< vector > BufU32x3; +RESOURCE BufF16x2; +RESOURCE BufF32x3; +RESOURCE BufI32x4; +// TODO: RESOURCE BufSNormF16; -> 11 +// TODO: RESOURCE BufUNormF16; -> 12 +// TODO: RESOURCE BufSNormF32; -> 13 +// TODO: RESOURCE BufUNormF32; -> 14 +// TODO: RESOURCE BufSNormF64; -> 15 +// TODO: RESOURCE BufUNormF64; -> 16 + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + int16_t v1 = BufI16[GI]; + uint16_t v2 = BufU16[GI]; + int v3 = BufI32[GI]; + uint v4 = BufU32[GI]; + int64_t v5 = BufI64[GI]; + uint64_t v6 = BufU64[GI]; + half v7 = BufF16[GI]; + float v8 = BufF32[GI]; + double v9 = BufF64[GI]; + vector v10 = BufI16x4[GI]; + vector v11 = BufU32x3[GI]; + half2 v12 = BufF16x2[GI]; + float3 v13 = BufF32x3[GI]; +} diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-subscript.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-subscript.hlsl new file mode 100644 index 0000000000000..adc35f6097403 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-subscript.hlsl @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=DXIL,CHECK +// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -fspv-use-unknown-image-format -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK + +Buffer In; +RWBuffer Out; + +[numthreads(1,1,1)] +void main(unsigned GI : SV_GroupIndex) { + // CHECK: define void @main() + + // DXIL: %[[INPTR:.*]] = call {{.*}} ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_0_0_1t(target("dx.TypedBuffer", i32, 0, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[INPTR:.*]] = call {{.*}} ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_1_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 1, 0) %{{.*}}, i32 %{{.*}}) + // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]] + // DXIL: %[[OUTPTR:.*]] = call {{.*}} ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[OUTPTR:.*]] = call {{.*}} ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) + // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]] + Out[GI] = In[GI]; + + // DXIL: %[[INPTR:.*]] = call {{.*}} ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[INPTR:.*]] = call {{.*}} ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) + // CHECK: %[[LOAD:.*]] = load i32, ptr {{.*}}%[[INPTR]] + // DXIL: %[[OUTPTR:.*]] = call {{.*}} ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}}) + // SPIRV: %[[OUTPTR:.*]] = call {{.*}} ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.SignedImage_i32_5_2_0_0_2_0t(target("spirv.SignedImage", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}}) + // CHECK: store i32 %[[LOAD]], ptr {{.*}}%[[OUTPTR]] + Out[GI + 1] = Out[GI]; +} diff --git a/clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl new file mode 100644 index 0000000000000..b153bda167a35 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl @@ -0,0 +1,42 @@ +// 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 + +Buffer Buf : register(t0); +RWBuffer RWBuf : register(u0); + +// DXIL: %"class.hlsl::Buffer" = type { target("dx.TypedBuffer", float, 0, 0, 0) } +// DXIL: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) } + +// DXIL: @Buf = internal global %"class.hlsl::Buffer" poison +// DXIL: @RWBuf = internal global %"class.hlsl::RWBuffer" poison + +export float TestLoad() { + return Buf.Load(1) + RWBuf.Load(2).y; +} + +// CHECK: define noundef nofpclass(nan inf) float @TestLoad()() +// CHECK: call {{.*}} float @hlsl::Buffer::Load(unsigned int)(ptr {{.*}} @Buf, i32 noundef 1) +// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer::Load(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 2) +// CHECK: add +// CHECK: ret float + +// CHECK: define {{.*}} float @hlsl::Buffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %__handle +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]] +// CHECK-NEXT: ret float %[[VAL]] + +// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index) +// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 +// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %__handle +// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr +// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 %[[INDEX]]) +// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]] +// CHECK-NEXT: ret <4 x i32> %[[VEC]] + +// 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) From c2375714c7527ca9ca980f95e2c3398d89c82835 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Fri, 3 Oct 2025 14:24:28 -0700 Subject: [PATCH 3/7] Fix typo in filename --- .../{TypesBuffers-methods.hlsl => TypedBuffers-methods.hlsl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clang/test/CodeGenHLSL/resources/{TypesBuffers-methods.hlsl => TypedBuffers-methods.hlsl} (100%) diff --git a/clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl similarity index 100% rename from clang/test/CodeGenHLSL/resources/TypesBuffers-methods.hlsl rename to clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl From e50918910a0ce590228c6ecacd4ff2a578da6f58 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Fri, 3 Oct 2025 17:33:19 -0700 Subject: [PATCH 4/7] [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{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(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{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 ParamTypes; - for (Param &MP : Params) - ParamTypes.emplace_back(MP.Ty); + SmallVector 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(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' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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 Buffer; // CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' 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' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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 {{.*}} 'numStructs' 'unsigned int &__restrict' +// CHECK-NEXT: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_getstride' 'void (...) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}} +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' 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 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' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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: 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::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1) // CHECK: call {{.*}} float @hlsl::StructuredBuffer::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::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) +// CHECK: call void @hlsl::RWStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: call void @hlsl::ConsumeStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}} %dim3, ptr {{.*}} %stride3) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::StructuredBuffer::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::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::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::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer::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::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::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}} %dim1) +// CHECK: call void @hlsl::RWBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}} %dim2) +// CHECK: add +// CHECK: ret + +// CHECK: define {{.*}} void @hlsl::Buffer::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::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 Date: Wed, 8 Oct 2025 22:41:36 -0700 Subject: [PATCH 5/7] 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{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{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 Date: Thu, 9 Oct 2025 14:04:40 -0700 Subject: [PATCH 6/7] 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{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{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' -// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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 Buffer; // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' -// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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 {{.*}} 'numStructs' 'unsigned int &__restrict' // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' -// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_getstride' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getstride' 'void (...) noexcept' // CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}} // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' 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 Buffer; // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' -// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept' +// CHECK-NEXT: DeclRefExpr {{.*}} '' 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/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 Date: Thu, 16 Oct 2025 10:42:28 -0700 Subject: [PATCH 7/7] 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 ParamTypes; SmallVector 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 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 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 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::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) -// CHECK: call void @hlsl::RWStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) -// CHECK: call void @hlsl::ConsumeStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}} %dim3, ptr {{.*}} %stride3) +// CHECK: call void @hlsl::StructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::RWStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::ConsumeStructuredBuffer::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::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1) -// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}}, ptr {{.*}}) +// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer::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::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}} %dim1) -// CHECK: call void @hlsl::RWBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}} %dim2) +// CHECK: call void @hlsl::Buffer::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}}) +// CHECK: call void @hlsl::RWBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}}) // CHECK: add // CHECK: ret