|
| 1 | +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s |
| 2 | + |
| 3 | +// CHECK-DAG: [[ONE_STR:@.*]] = private unnamed_addr constant [4 x i8] c"One\00" |
| 4 | +// CHECK-DAG: [[ARRAY_STR:@.*]] = private unnamed_addr constant [6 x i8] c"Array\00" |
| 5 | +// CHECK-DAG: [[ONEWITHCOUNTER_STR:@.*]] = private unnamed_addr constant [15 x i8] c"OneWithCounter\00" |
| 6 | +// CHECK-DAG: [[ARRAYWITHCOUNTER_STR:@.*]] = private unnamed_addr constant [17 x i8] c"ArrayWithCounter\00" |
| 7 | +// CHECK-NOT: private unnamed_addr constant [{{[0-9]+}} x i8] c"Static |
| 8 | + |
| 9 | +RWBuffer<float> One : register(u1, space5); |
| 10 | +RWBuffer<float> Array[2] : register(u10, space6); |
| 11 | +RWStructuredBuffer<int> OneWithCounter : register(u2, space4); |
| 12 | +RWStructuredBuffer<int> ArrayWithCounter[2] : register(u7, space4); |
| 13 | + |
| 14 | +// Check that the non-static resource One is initialized from binding on |
| 15 | +// startup (register 1, space 5). |
| 16 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 17 | +// CHECK-NEXT: entry: |
| 18 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 19 | +// CHECK-SAME: (ptr {{.*}} @One, i32 noundef 1, i32 noundef 5, i32 noundef 1, i32 noundef 0, ptr noundef [[ONE_STR]]) |
| 20 | + |
| 21 | +// Check that the non-static resource OneWithCounter is initialized from binding on |
| 22 | +// startup (register 2, space 4). |
| 23 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 24 | +// CHECK-NEXT: entry: |
| 25 | +// CHECK-NEXT: call void @hlsl::RWStructuredBuffer<int>::__createFromBindingWithImplicitCounter(unsigned int, unsigned int, int, unsigned int, char const*, unsigned int) |
| 26 | +// CHECK-SAME: (ptr {{.*}} @OneWithCounter, i32 noundef 2, i32 noundef 4, i32 noundef 1, i32 noundef 0, ptr noundef [[ONEWITHCOUNTER_STR]], i32 noundef 0) |
| 27 | + |
| 28 | +// Note that non-static resource arrays are not initialized on startup. |
| 29 | +// The individual resources from the array are initialized on access. |
| 30 | + |
| 31 | +static RWBuffer<float> StaticOne; |
| 32 | +static RWBuffer<float> StaticArray[2]; |
| 33 | + |
| 34 | +// Check that StaticOne resource is initialized on startup with the default |
| 35 | +// constructor and not from binding. It will initalize the handle to poison. |
| 36 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 37 | +// CHECK-NEXT: entry: |
| 38 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} @StaticOne) |
| 39 | + |
| 40 | +// Check that StaticArray elements are initialized on startup with the default |
| 41 | +// constructor and not from binding. The initializer will loop over the array |
| 42 | +// elements and call the default constructor for each one, setting the handle to poison. |
| 43 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 44 | +// CHECK-NEXT: entry: |
| 45 | +// CHECK-NEXT: br label %arrayctor.loop |
| 46 | +// CHECK: arrayctor.loop: ; preds = %arrayctor.loop, %entry |
| 47 | +// CHECK-NEXT: %arrayctor.cur = phi ptr [ @StaticArray, %entry ], [ %arrayctor.next, %arrayctor.loop ] |
| 48 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} %arrayctor.cur) |
| 49 | +// CHECK-NEXT: %arrayctor.next = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %arrayctor.cur, i32 1 |
| 50 | +// CHECK-NEXT: %arrayctor.done = icmp eq ptr %arrayctor.next, getelementptr inbounds (%"class.hlsl::RWBuffer", ptr @StaticArray, i32 2) |
| 51 | +// CHECK-NEXT: br i1 %arrayctor.done, label %arrayctor.cont, label %arrayctor.loop |
| 52 | +// CHECK: arrayctor.cont: ; preds = %arrayctor.loop |
| 53 | +// CHECK-NEXT: ret void |
| 54 | + |
| 55 | +static RWStructuredBuffer<int> StaticOneWithCounter; |
| 56 | + |
| 57 | +// Check that StaticOneWithCounter resource is initialized on startup with the default |
| 58 | +// constructor and not from binding. It will initalize the handle to poison. |
| 59 | +// CHECK: define internal void @__cxx_global_var_init{{.*}} |
| 60 | +// CHECK-NEXT: entry: |
| 61 | +// CHECK-NEXT: call void @hlsl::RWStructuredBuffer<int>::RWStructuredBuffer()(ptr {{.*}} @StaticOneWithCounter) |
| 62 | + |
| 63 | +// No other global initialization routines should be present. |
| 64 | +// CHECK-NOT: define internal void @__cxx_global_var_init{{.*}} |
| 65 | + |
| 66 | +[numthreads(4,1,1)] |
| 67 | +void main() { |
| 68 | +// CHECK: define internal void @main()() |
| 69 | +// CHECK-NEXT: entry: |
| 70 | +// CHECK-NEXT: %[[TMP0:.*]] = alloca %"class.hlsl::RWBuffer" |
| 71 | + |
| 72 | + static RWBuffer<float> StaticLocal; |
| 73 | +// Check that StaticLocal is initialized by default constructor (handle set to poison) |
| 74 | +// and not from binding. |
| 75 | +// call void @hlsl::RWBuffer<float>::RWBuffer()(ptr {{.*}} @main()::StaticLocal) |
| 76 | + |
| 77 | + StaticLocal = Array[1]; |
| 78 | +// A[2][0] is accessed here, so it should be initialized from binding (register 10, space 6, index 1), |
| 79 | +// and then assigned to StaticLocal using = operator. |
| 80 | +// CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 81 | +// CHECK-SAME: (ptr {{.*}} %[[TMP0]], i32 noundef 10, i32 noundef 6, i32 noundef 2, i32 noundef 1, ptr noundef [[ARRAY_STR]]) |
| 82 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=({{.*}})(ptr {{.*}} @main()::StaticLocal, ptr {{.*}} %[[TMP0]]) |
| 83 | + |
| 84 | + StaticOne = One; |
| 85 | +// Operator = call to assign non-static One handle to static StaticOne. |
| 86 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=({{.*}})(ptr {{.*}} @StaticOne, ptr {{.*}} @One) |
| 87 | + |
| 88 | + StaticArray = Array; |
| 89 | +// Check that each elements of StaticArray is initialized from binding (register 10, space 6, indices 0 and 1). |
| 90 | +// CHECK: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 91 | +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 @StaticArray, i32 noundef 10, i32 noundef 6, i32 noundef 2, i32 noundef 0, ptr noundef [[ARRAY_STR]]) |
| 92 | +// CHECK-NEXT: call void @hlsl::RWBuffer<float>::__createFromBinding(unsigned int, unsigned int, int, unsigned int, char const*) |
| 93 | +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWBuffer") align 4 getelementptr ([2 x %"class.hlsl::RWBuffer"], ptr @StaticArray, i32 0, i32 1), |
| 94 | +// CHECK-SAME: i32 noundef 10, i32 noundef 6, i32 noundef 2, i32 noundef 1, ptr noundef [[ARRAY_STR]] |
| 95 | + |
| 96 | + StaticArray[1] = One; |
| 97 | +// Operator = call to assign non-static One handle to StaticArray element. |
| 98 | +// CHECK-NEXT: call {{.*}} ptr @hlsl::RWBuffer<float>::operator=(hlsl::RWBuffer<float> const&) |
| 99 | +// CHECK-SAME: (ptr {{.*}} getelementptr inbounds ([2 x %"class.hlsl::RWBuffer"], ptr @StaticArray, i32 0, i32 1), ptr {{.*}} @One) |
| 100 | + |
| 101 | + StaticLocal[0] = 123; |
| 102 | +// CHECK-NEXT: %[[PTR0:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}} @main()::StaticLocal, i32 noundef 0) |
| 103 | +// CHECK-NEXT: store float 1.230000e+02, ptr %[[PTR0]] |
| 104 | + |
| 105 | + StaticOne[1] = 456; |
| 106 | +// CHECK-NEXT: %[[PTR1:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int)(ptr {{.*}}) @StaticOne, i32 noundef 1) |
| 107 | +// CHECK-NEXT: store float 4.560000e+02, ptr %[[PTR1]], align 4 |
| 108 | + |
| 109 | + StaticArray[1][2] = 789; |
| 110 | +// CHECK-NEXT: %[[PTR2:.*]] = call {{.*}} ptr @hlsl::RWBuffer<float>::operator[](unsigned int) |
| 111 | +// CHECK-SAME: (ptr {{.*}} getelementptr inbounds ([2 x %"class.hlsl::RWBuffer"], ptr @StaticArray, i32 0, i32 1), i32 noundef 2) |
| 112 | +// CHECK-NEXT: store float 7.890000e+02, ptr %[[PTR2]], align 4 |
| 113 | + |
| 114 | + static RWStructuredBuffer<int> StaticLocalWithCounter; |
| 115 | +// Check that StaticLocalWithCounter is initialized by default constructor (handle set to poison) |
| 116 | +// and not from binding. |
| 117 | +// call void @hlsl::RWStructuredBuffer<int>::RWStructuredBuffer()(ptr {{.*}} @main()::StaticLocalWithCounter) |
| 118 | + |
| 119 | + static RWStructuredBuffer<int> StaticLocalArrayWithCounter[2]; |
| 120 | + |
| 121 | + StaticLocalWithCounter = OneWithCounter; |
| 122 | +// Operator = call to assign non-static OneWithCounter handles to StaticLocalWithCounter handles. |
| 123 | +// CHECK: call {{.*}} ptr @hlsl::RWStructuredBuffer<int>::operator=(hlsl::RWStructuredBuffer<int> const&)(ptr {{.*}} @main()::StaticLocalWithCounter, ptr {{.*}} @OneWithCounter) |
| 124 | + |
| 125 | + StaticLocalArrayWithCounter = ArrayWithCounter; |
| 126 | +// Check that each elements of StaticLocalArrayWithCounter is initialized from binding |
| 127 | +// of ArrayWithCounter (register 7, space 4, indices 0 and 1). |
| 128 | +// CHECK: call void @hlsl::RWStructuredBuffer<int>::__createFromBindingWithImplicitCounter(unsigned int, unsigned int, int, unsigned int, char const*, unsigned int) |
| 129 | +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 @main()::StaticLocalArrayWithCounter, |
| 130 | +// CHECK-SAME: i32 noundef 7, i32 noundef 4, i32 noundef 2, i32 noundef 0, ptr noundef [[ARRAYWITHCOUNTER_STR]], i32 noundef 1) |
| 131 | + |
| 132 | +// CHECK-NEXT: call void @hlsl::RWStructuredBuffer<int>::__createFromBindingWithImplicitCounter(unsigned int, unsigned int, int, unsigned int, char const*, unsigned int) |
| 133 | +// CHECK-SAME: (ptr {{.*}} sret(%"class.hlsl::RWStructuredBuffer") align 4 getelementptr ([2 x %"class.hlsl::RWStructuredBuffer"], ptr @main()::StaticLocalArrayWithCounter, i32 0, i32 1), |
| 134 | +// CHECK-SAME: i32 noundef 7, i32 noundef 4, i32 noundef 2, i32 noundef 1, ptr noundef [[ARRAYWITHCOUNTER_STR]], i32 noundef 1) |
| 135 | +} |
| 136 | + |
| 137 | +// No other binding initialization calls should be present. |
| 138 | +// CHECK-NOT: call void @hlsl::RWBuffer<float>::__createFrom{{.*}}Binding{{.*}} |
0 commit comments