diff --git a/clang/test/AST/HLSL/ArrayOutArgExpr.hlsl b/clang/test/AST/HLSL/ArrayOutArgExpr.hlsl new file mode 100644 index 00000000000000..10825bf0f93bc7 --- /dev/null +++ b/clang/test/AST/HLSL/ArrayOutArgExpr.hlsl @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s + +// CHECK-LABEL: increment +void increment(inout int Arr[2]) { + for (int I = 0; I < 2; I++) + Arr[0] += 2; +} + +// CHECK-LABEL: call +// CHECK: CallExpr 0x{{.*}} {{.*}} 'void' +// CHECK: ImplicitCastExpr 0x{{.*}} {{.*}} 'void (*)(inout int[2])' +// CHECK: DeclRefExpr 0x{{.*}} {{.*}} 'void (inout int[2])' lvalue Function 0x{{.*}} 'increment' 'void (inout int[2])' +// CHECK: HLSLOutArgExpr 0x{{.*}} {{.*}} 'int[2]' lvalue inout +// CHECK: OpaqueValueExpr [[A:0x.*]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B:0x.*]] {{.*}} 'int[2]' lvalue Var [[E:0x.*]] 'A' 'int[2]' +// CHECK: OpaqueValueExpr [[C:0x.*]] {{.*}} 'int[2]' lvalue +// CHECK: ImplicitCastExpr [[D:0x.*]] {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B]] {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +// CHECK: BinaryOperator 0x{{.*}} {{.*}} 'int[2]' lvalue '=' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr 0x{{.*}} {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +// CHECK: ImplicitCastExpr 0x{{.*}} {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[C]] {{.*}} 'int[2]' lvalue +// CHECK: ImplicitCastExpr [[D]] {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B]] {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +export int call() { + int A[2] = { 0, 1 }; + increment(A); + return A[0]; +} + +// CHECK-LABEL: fn2 +void fn2(out int Arr[2]) { + Arr[0] += 5; + Arr[1] += 6; +} + +// CHECK-LABEL: call2 +// CHECK: CallExpr 0x{{.*}} {{.*}} 'void' +// CHECK: ImplicitCastExpr 0x{{.*}} {{.*}} 'void (*)(out int[2])' +// CHECK: DeclRefExpr 0x{{.*}} {{.*}} 'void (out int[2])' lvalue Function 0x{{.*}} 'fn2' 'void (out int[2])' +// CHECK: HLSLOutArgExpr 0x{{.*}} {{.*}} 'int[2]' lvalue out +// CHECK: OpaqueValueExpr [[A:0x.*]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B:0x.*]] {{.*}} 'int[2]' lvalue Var [[E:0x.*]] 'A' 'int[2]' +// CHECK: OpaqueValueExpr [[C:0x.*]] {{.*}} 'int[2]' lvalue +// CHECK: ImplicitCastExpr [[D:0x.*]] {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B]] {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +// CHECK: BinaryOperator 0x{{.*}} {{.*}} 'int[2]' lvalue '=' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B]] {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +// CHECK: ImplicitCastExpr 0x{{.*}} {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[C]] {{.*}} 'int[2]' lvalue +// CHECK: ImplicitCastExpr [[D]] {{.*}} 'int[2]' +// CHECK: OpaqueValueExpr [[A]] {{.*}} 'int[2]' lvalue +// CHECK: DeclRefExpr [[B]] {{.*}} 'int[2]' lvalue Var [[E]] 'A' 'int[2]' +export int call2() { + int A[2] = { 0, 1 }; + fn2(A); + return 1; +} diff --git a/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl new file mode 100644 index 00000000000000..d4a5cdb9445a7f --- /dev/null +++ b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s + +// CHECK-LABEL: increment +void increment(inout int Arr[2]) { + for (int I = 0; I < 2; I++) + Arr[0] += 2; +} + +// CHECK-LABEL: call +// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[Tmp2:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) +// CHECK-NEXT: store ptr [[Tmp]], ptr [[Tmp2]], align 4 +// CHECK-NEXT: call void @"?increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp2]]) #3 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) +// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 +// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 +// CHECK-NEXT: ret i32 [[B]] +export int call() { + int A[2] = { 0, 1 }; + increment(A); + return A[0]; +} + +// CHECK-LABEL: fn2 +void fn2(out int Arr[2]) { + Arr[0] += 5; + Arr[1] += 6; +} + +// CHECK-LABEL: call2 +// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: [[Tmp2:%.*]] = alloca [2 x i32], align 4 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) +// CHECK-NEXT: store ptr [[Tmp]], ptr [[Tmp2]], align 4 +// CHECK-NEXT: call void @"?fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp2]]) #3 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) +// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 +// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 +// CHECK-NEXT: ret i32 [[B]] +export int call2() { + int A[2] = { 0, 1 }; + fn2(A); + return A[0]; +} diff --git a/clang/test/SemaHLSL/Language/ArrayOutputArgs-errors.hlsl b/clang/test/SemaHLSL/Language/ArrayOutputArgs-errors.hlsl new file mode 100644 index 00000000000000..46bed0d5a7cbdc --- /dev/null +++ b/clang/test/SemaHLSL/Language/ArrayOutputArgs-errors.hlsl @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify + +void increment(inout int Arr[2]) { + for (int I = 0; I < 2; I++) + Arr[0] += 2; +} + +export int wrongSize() { + int A[3] = { 0, 1, 2 }; + increment(A); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'int[3]' to 'int[2]' for 1st argument}} + return A[0]; +} + +export int wrongSize2() { + int A[1] = { 0 }; + increment(A); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'int[1]' to 'int[2]' for 1st argument}} + return A[0]; +} + +export void tooFewArgs() { + increment(); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: requires single argument 'Arr', but no arguments were provided}} +} + +export float wrongType() { + float A[2] = { 0, 1 }; + increment(A); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'float[2]' to 'int[2]' for 1st argument}} + return A[0]; +} + +export int wrongType2() { + increment(5); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'int[2]' for 1st argument}} + return 1; +} + +export void tooManyArgs() { + int A[2] = { 0, 1 }; + int B[2] = { 2, 3 }; + increment(A, B); + // expected-error@-1 {{no matching function for call to 'increment'}} + // expected-note@*:* {{candidate function not viable: requires single argument 'Arr', but 2 arguments were provided}} +}