|
| 1 | +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s |
| 2 | + |
| 3 | +// CHECK: [[ONE_STR:@.*]] = private unnamed_addr constant [4 x i8] c"One\00" |
| 4 | +// CHECK: [[ARRAY_STR:@.*]] = private unnamed_addr constant [6 x i8] c"Array\00" |
| 5 | +// CHECK-NOT: private unnamed_addr constant [{{[0-9]+}} x i8] c"Static |
| 6 | + |
| 7 | +RWBuffer<float> One : register(u1, space5); |
| 8 | +RWBuffer<float> Array[4][2] : register(u10, space6); |
| 9 | + |
| 10 | +// Check that the non-static resource One is initialized from binding on |
| 11 | +// startup (register 1, space 5). |
| 12 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 13 | +// CHECK-NEXT: entry: |
| 14 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 15 | +// CHECK-SAME: (ptr {{.*}} @One, i32 noundef 1, i32 noundef 5, i32 noundef 1, i32 noundef 0, ptr noundef [[ONE_STR]]) |
| 16 | + |
| 17 | +// Note that non-static resource arrays are not initialized on startup. |
| 18 | +// The individual resources from the array are initialized on access. |
| 19 | + |
| 20 | +static RWBuffer<float> StaticOne; |
| 21 | +static RWBuffer<float> StaticArray[2]; |
| 22 | + |
| 23 | +// Check that StaticOne resource is initialized on startup with the default |
| 24 | +// constructor and not from binding. It will initalize the handle to poison. |
| 25 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 26 | +// CHECK-NEXT: entry: |
| 27 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} @StaticOne) |
| 28 | + |
| 29 | +// Check that StaticArray elements are initialized on startup with the default |
| 30 | +// constructor and not from binding. The initializer will loop over the array |
| 31 | +// elements and call the default constructor for each one, setting the handle to poison. |
| 32 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 33 | +// CHECK-NEXT: entry: |
| 34 | +// CHECK-NEXT: br label %arrayctor.loop |
| 35 | +// CHECK: arrayctor.loop: ; preds = %arrayctor.loop, %entry |
| 36 | +// CHECK-NEXT: %arrayctor.cur = phi ptr [ @StaticArray, %entry ], [ %arrayctor.next, %arrayctor.loop ] |
| 37 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} %arrayctor.cur) |
| 38 | +// CHECK-NEXT: %arrayctor.next = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %arrayctor.cur, i32 1 |
| 39 | +// CHECK-NEXT: %arrayctor.done = icmp eq ptr %arrayctor.next, getelementptr inbounds (%"class.hlsl::RWBuffer", ptr @StaticArray, i32 2) |
| 40 | +// CHECK-NEXT: br i1 %arrayctor.done, label %arrayctor.cont, label %arrayctor.loop |
| 41 | +// CHECK: arrayctor.cont: ; preds = %arrayctor.loop |
| 42 | +// CHECK-NEXT: ret void |
| 43 | + |
| 44 | +// No other global initialization routines should be present. |
| 45 | +// CHECK-NOT: define internal void @__cxx_global_var_init{{.*}} |
| 46 | + |
| 47 | +[numthreads(4,1,1)] |
| 48 | +void main() { |
| 49 | +// CHECK: define internal void @main()() |
| 50 | +// CHECK-NEXT: entry: |
| 51 | +// CHECK-NEXT: %[[TMP0:.*]] = alloca %"class.hlsl::RWBuffer" |
| 52 | + |
| 53 | + static RWBuffer<float> StaticLocal; |
| 54 | +// Check that StaticLocal is initialized to by default constructor to poison and not from binding |
| 55 | +// call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} @main()::StaticLocal) |
| 56 | + |
| 57 | + StaticLocal = Array[2][0]; |
| 58 | +// A[2][0] is accessed here, so it should be initialized from binding (register 10, space 6, index 4), |
| 59 | +// and then assigned to StaticLocal using = operator. |
| 60 | +// CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 61 | +// CHECK-SAME: (ptr {{.*}} %[[TMP0]], i32 noundef 10, i32 noundef 6, i32 noundef 8, i32 noundef 4, ptr noundef [[ARRAY_STR]]) |
| 62 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=({{.*}})(ptr {{.*}} @main()::StaticLocal, ptr {{.*}} %[[TMP0]]) |
| 63 | + |
| 64 | + StaticOne = One; |
| 65 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=({{.*}})(ptr {{.*}} @StaticOne, ptr {{.*}} @One) |
| 66 | + |
| 67 | + StaticArray[1] = One; |
| 68 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=(hlsl::RWBuffer<float> const&) |
| 69 | +// CHECK-SAME: (ptr {{.*}} getelementptr inbounds ([2 x %"class.hlsl::RWBuffer"], ptr @StaticArray, i32 0, i32 1), ptr {{.*}} @One) |
| 70 | + |
| 71 | + StaticLocal[0] = 123; |
| 72 | +// CHECK-NEXT: %[[PTR0:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} @main()::StaticLocal, i32 noundef 0) |
| 73 | +// CHECK-NEXT: store float 1.230000e+02, ptr %[[PTR0]] |
| 74 | + |
| 75 | + StaticOne[1] = 456; |
| 76 | +// CHECK-NEXT: %[[PTR1:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}}) @StaticOne, i32 noundef 1) |
| 77 | +// CHECK-NEXT: store float 4.560000e+02, ptr %[[PTR1]], align 4 |
| 78 | + |
| 79 | + StaticArray[1][2] = 789; |
| 80 | +// CHECK-NEXT: %[[PTR2:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int) |
| 81 | +// CHECK-SAME: (ptr {{.*}} getelementptr inbounds ([2 x %"class.hlsl::RWBuffer"], ptr @StaticArray, i32 0, i32 1), i32 noundef 2) |
| 82 | +// CHECK-NEXT: store float 7.890000e+02, ptr %[[PTR2]], align 4 |
| 83 | +} |
| 84 | + |
| 85 | +// No other binding initialization calls should be present. |
| 86 | +// CHECK-NOT: call void @hlsl::RWBuffer<float>::__createFrom{{.*}}Binding{{.*}} |
0 commit comments