https://github.com/spall created https://github.com/llvm/llvm-project/pull/109323
Make Constant Arrays in HLSL assignable. Closes #109043 >From b24aed9771a415a4dc896c48cfc0481574a0773c Mon Sep 17 00:00:00 2001 From: Sarah Spall <sp...@planetbauer.com> Date: Wed, 18 Sep 2024 22:19:07 +0000 Subject: [PATCH 1/2] enable array by value assignment --- clang/include/clang/AST/CanonicalType.h | 1 + clang/lib/AST/ExprClassification.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 11 ++++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index dde08f0394c98d..6102eb01793530 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -299,6 +299,7 @@ class CanProxyBase { LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 5dde923312698f..9d97633309ada2 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -704,7 +704,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_ConstAddrSpace; // Arrays are not modifiable, only their elements are. - if (CT->isArrayType()) + if (CT->isArrayType() && + !(Ctx.getLangOpts().HLSL && CT->isConstantArrayType())) return Cl::CM_ArrayType; // Incomplete types are not modifiable. if (CT->isIncompleteType()) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d304f322aced64..ce503f9c69b411 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2232,16 +2232,21 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // just strip the qualifiers because they don't matter. FromType = FromType.getUnqualifiedType(); } else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() && - ToType->isArrayParameterType()) { + ToType->isConstantArrayType()) { // HLSL constant array parameters do not decay, so if the argument is a // constant array and the parameter is an ArrayParameterType we have special // handling here. - FromType = S.Context.getArrayParameterType(FromType); + if (ToType->isArrayParameterType()) { + FromType = S.Context.getArrayParameterType(FromType); + SCS.First = ICK_HLSL_Array_RValue; + } else { + SCS.First = ICK_Identity; + } + if (S.Context.getCanonicalType(FromType) != S.Context.getCanonicalType(ToType)) return false; - SCS.First = ICK_HLSL_Array_RValue; SCS.setAllToTypes(ToType); return true; } else if (FromType->isArrayType()) { >From a81247d0992a3fb2376a9b3dc60e5fbfd782ffbf Mon Sep 17 00:00:00 2001 From: Sarah Spall <sp...@planetbauer.com> Date: Thu, 19 Sep 2024 19:33:39 +0000 Subject: [PATCH 2/2] test assignable arrays --- clang/test/AST/HLSL/ArrayAssignable.hlsl | 80 +++++++++++++++++++ clang/test/CodeGenHLSL/ArrayAssignable.hlsl | 50 ++++++++++++ .../test/SemaHLSL/ArrayAssignable_errors.hlsl | 29 +++++++ 3 files changed, 159 insertions(+) create mode 100644 clang/test/AST/HLSL/ArrayAssignable.hlsl create mode 100644 clang/test/CodeGenHLSL/ArrayAssignable.hlsl create mode 100644 clang/test/SemaHLSL/ArrayAssignable_errors.hlsl diff --git a/clang/test/AST/HLSL/ArrayAssignable.hlsl b/clang/test/AST/HLSL/ArrayAssignable.hlsl new file mode 100644 index 00000000000000..52c9918aa85334 --- /dev/null +++ b/clang/test/AST/HLSL/ArrayAssignable.hlsl @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s + +// CHECK-LABEL: arr_assign1 +// CHECK: CompoundStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[A:0x[0-9a-f]+]] {{.*}} col:7 used Arr 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[B:0x[0-9a-f]+]] {{.*}} col:7 used Arr2 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[A]] 'Arr' 'int[2]' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[B]] 'Arr2' 'int[2]' +void arr_assign1() { + int Arr[2] = {0, 1}; + int Arr2[2] = {0, 0}; + Arr = Arr2; +} + +// CHECK-LABEL: arr_assign2 +// CHECK: CompoundStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[A:0x[0-9a-f]+]] {{.*}} col:7 used Arr 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[B:0x[0-9a-f]+]] {{.*}} col:7 used Arr2 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[C:0x[0-9a-f]+]] {{.*}} col:7 used Arr3 'int[2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 2 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 2 +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[A]] 'Arr' 'int[2]' +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[B]] 'Arr2' 'int[2]' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var [[C]] 'Arr3' 'int[2]' +void arr_assign2() { + int Arr[2] = {0, 1}; + int Arr2[2] = {0, 0}; + int Arr3[2] = {2, 2}; + Arr = Arr2 = Arr3; +} + +// CHECK-LABEL: arr_assign3 +// CHECK: CompoundStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[A:0x[0-9a-f]+]] {{.*}} col:7 used Arr 'int[2][2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 2 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 3 +// CHECK: DeclStmt 0x{{[0-9a-f]+}} {{.*}} +// CHECK: VarDecl [[B:0x[0-9a-f]+]] {{.*}} col:7 used Arr2 'int[2][2]' cinit +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0 +// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 1 +// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue '=' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var [[A]] 'Arr' 'int[2][2]' +// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var [[B]] 'Arr2' 'int[2][2]' +void arr_assign3() { + int Arr[2][2] = {{0, 1}, {2, 3}}; + int Arr2[2][2] = {{0, 0}, {1, 1}}; + Arr = Arr2; +} \ No newline at end of file diff --git a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl new file mode 100644 index 00000000000000..769154df2bfb43 --- /dev/null +++ b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope + +// CHECK-LABEL: define void {{.*}}arr_assign1 +// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr2:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) +// CHECK: ret void +void arr_assign1() { + int Arr[2] = {0, 1}; + int Arr2[2] = {0, 0}; + Arr = Arr2; +} + +// CHECK-LABEL: define void {{.*}}arr_assign2 +// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr2:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Arr3:%.*]] = alloca [2 x i32], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr2]], ptr align 4 [[Arr3]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) +// CHECK: ret void +void arr_assign2() { + int Arr[2] = {0, 1}; + int Arr2[2] = {0, 0}; + int Arr3[2] = {3, 4}; + Arr = Arr2 = Arr3; +} + +// CHECK-LABEL: define void {{.*}}arr_assign3 +// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4 +// CHECK: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4 +// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x i32]], align 4 +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr4]], ptr align 4 {{@.*}}, i32 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 [[Arr4]], i32 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr3]], i32 16, i1 false) +// CHECK: ret void +void arr_assign3() { + int Arr2[2][2] = {{0, 0}, {1, 1}}; + int Arr3[2][2] = {{1, 1}, {0, 0}}; + Arr2 = Arr3; +} diff --git a/clang/test/SemaHLSL/ArrayAssignable_errors.hlsl b/clang/test/SemaHLSL/ArrayAssignable_errors.hlsl new file mode 100644 index 00000000000000..1925032a93d488 --- /dev/null +++ b/clang/test/SemaHLSL/ArrayAssignable_errors.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify + +void test_wrong_size1() { + int Arr[2] = {0, 1}; + int Arr2[3] = {1, 2, 0}; + Arr = Arr2; + // expected-error@-1 {{assigning to 'int[2]' from incompatible type 'int[3]'}} +} + +void test_wrong_size2() { + int Arr[2] = {0, 1}; + int Arr2[3] = {1, 2, 0}; + Arr2 = Arr; + // expected-error@-1 {{assigning to 'int[3]' from incompatible type 'int[2]'}} +} + +void test_wrong_size3() { + int Arr[2][2] = {{0, 1}, {2, 3}}; + int Arr2[2] = {4, 5}; + Arr = Arr2; + // expected-error@-1 {{assigning to 'int[2][2]' from incompatible type 'int[2]'}} +} + +void test_wrong_size4() { + int Arr[2][2] = {{0, 1}, {2, 3}}; + int Arr2[2] = {4, 5}; + Arr2 = Arr; + // expected-error@-1 {{assigning to 'int[2]' from incompatible type 'int[2][2]'}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits