Author: Chris B Date: 2024-09-13T17:36:41-05:00 New Revision: 03618ceabd003be94190b068db11b607fd1108ef
URL: https://github.com/llvm/llvm-project/commit/03618ceabd003be94190b068db11b607fd1108ef DIFF: https://github.com/llvm/llvm-project/commit/03618ceabd003be94190b068db11b607fd1108ef.diff LOG: [HLSL] Fix move assignment of `this` (#108445) Under HLSL 202x+ move assignment can occur and when targeting `this` move assignment was generating some really odd errors. This corrects the errors by properly generating the `this` object reference for HLSL and always treating it as a reference. This mirrors the implementation added eariler for copy assignment, and extends the test case to cover both move and copy assignment under HLSL 202x+. Added: Modified: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenHLSL/this-assignment.hlsl Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6b6fa98bf394ca..d8cdfcf8c6ec05 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -15331,6 +15331,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, std::optional<DerefBuilder> DerefThis; std::optional<RefBuilder> ExplicitObject; QualType ObjectType; + bool IsArrow = false; if (MoveAssignOperator->isExplicitObjectMemberFunction()) { ObjectType = MoveAssignOperator->getParamDecl(0)->getType(); if (ObjectType->isReferenceType()) @@ -15340,6 +15341,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, ObjectType = getCurrentThisType(); This.emplace(); DerefThis.emplace(*This); + IsArrow = !getLangOpts().HLSL; } ExprBuilder &ObjectParameter = ExplicitObject ? *ExplicitObject : static_cast<ExprBuilder &>(*This); @@ -15441,8 +15443,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); MemberBuilder From(MoveOther, OtherRefType, /*IsArrow=*/false, MemberLookup); - MemberBuilder To(ObjectParameter, ObjectType, /*IsArrow=*/!ExplicitObject, - MemberLookup); + MemberBuilder To(ObjectParameter, ObjectType, IsArrow, MemberLookup); assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue "Member reference with rvalue base must be rvalue except for reference " @@ -15465,8 +15466,9 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" Expr *ThisExpr = - (ExplicitObject ? static_cast<ExprBuilder &>(*ExplicitObject) - : static_cast<ExprBuilder &>(*DerefThis)) + (ExplicitObject ? static_cast<ExprBuilder &>(*ExplicitObject) + : LangOpts.HLSL ? static_cast<ExprBuilder &>(*This) + : static_cast<ExprBuilder &>(*DerefThis)) .build(*this, Loc); StmtResult Return = BuildReturnStmt(Loc, ThisExpr); diff --git a/clang/test/CodeGenHLSL/this-assignment.hlsl b/clang/test/CodeGenHLSL/this-assignment.hlsl index 5c8de0a18ef7ca..7408d199910e5c 100644 --- a/clang/test/CodeGenHLSL/this-assignment.hlsl +++ b/clang/test/CodeGenHLSL/this-assignment.hlsl @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s | FileCheck %s struct Pair { int First; @@ -10,10 +11,18 @@ struct Pair { return this.First; } + // In HLSL 202x, this is a move assignment rather than a copy. int getSecond() { this = Pair(); return Second; } + + // In HLSL 202x, this is a copy assignment. + Pair DoSilly(Pair Obj) { + this = Obj; + First += 2; + return Obj; + } }; [numthreads(1, 1, 1)] @@ -21,10 +30,11 @@ void main() { Pair Vals = {1, 2.0}; Vals.First = Vals.getFirst(); Vals.Second = Vals.getSecond(); + (void) Vals.DoSilly(Vals); } // This tests reference like implicit this in HLSL -// CHECK: define linkonce_odr noundef i32 @"?getFirst@Pair@@QAAHXZ"(ptr noundef nonnull align 4 dereferenceable(8) %this) #0 align 2 { +// CHECK-LABEL: define {{.*}}getFirst // CHECK-NEXT:entry: // CHECK-NEXT:%this.addr = alloca ptr, align 4 // CHECK-NEXT:%Another = alloca %struct.Pair, align 4 @@ -34,7 +44,7 @@ void main() { // CHECK-NEXT:call void @llvm.memcpy.p0.p0.i32(ptr align 4 %this1, ptr align 4 %Another, i32 8, i1 false) // CHECK-NEXT:%First = getelementptr inbounds nuw %struct.Pair, ptr %this1, i32 0, i32 0 -// CHECK: define linkonce_odr noundef i32 @"?getSecond@Pair@@QAAHXZ"(ptr noundef nonnull align 4 dereferenceable(8) %this) #0 align 2 { +// CHECK-LABEL: define {{.*}}getSecond // CHECK-NEXT:entry: // CHECK-NEXT:%this.addr = alloca ptr, align 4 // CHECK-NEXT:%ref.tmp = alloca %struct.Pair, align 4 @@ -43,3 +53,17 @@ void main() { // CHECK-NEXT:call void @llvm.memset.p0.i32(ptr align 4 %ref.tmp, i8 0, i32 8, i1 false) // CHECK-NEXT:call void @llvm.memcpy.p0.p0.i32(ptr align 4 %this1, ptr align 4 %ref.tmp, i32 8, i1 false) // CHECK-NEXT:%Second = getelementptr inbounds nuw %struct.Pair, ptr %this1, i32 0, i32 1 + +// CHECK-LABEL: define {{.*}}DoSilly +// CHECK-NEXT:entry: +// CHECK-NEXT: [[ResPtr:%.*]] = alloca ptr +// CHECK-NEXT: [[ThisPtrAddr:%.*]] = alloca ptr +// CHECK-NEXT: store ptr [[AggRes:%.*]], ptr [[ResPtr]] +// CHECK-NEXT: store ptr {{.*}}, ptr [[ThisPtrAddr]] +// CHECK-NEXT: [[ThisPtr:%.*]] = load ptr, ptr [[ThisPtrAddr]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ThisPtr]], ptr align 4 [[Obj:%.*]], i32 8, i1 false) +// CHECK-NEXT: [[FirstAddr:%.*]] = getelementptr inbounds nuw %struct.Pair, ptr [[ThisPtr]], i32 0, i32 0 +// CHECK-NEXT: [[First:%.*]] = load i32, ptr [[FirstAddr]] +// CHECK-NEXT: [[FirstPlusTwo:%.*]] = add nsw i32 [[First]], 2 +// CHECK-NEXT: store i32 [[FirstPlusTwo]], ptr [[FirstAddr]] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AggRes]], ptr align 4 [[Obj]], i32 8, i1 false) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits