https://github.com/s-perron created 
https://github.com/llvm/llvm-project/pull/156075

The wrapper used to hold the handle for resource type has just the
default copy constructor and assignment operator. This causes clang to
insert memcpys when it does an assignment of a resource type. The
memcpy then cause optimizations to fail when the memcpy is turned into a
load and store of an i64.

To fix this, we should define copying of a resource type by adding the
operator= and copy constructor.

Partially fixes #154669


>From cfaf08898c046baaa41cb1cbe75ed9682da8bc1f Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenper...@google.com>
Date: Fri, 29 Aug 2025 13:40:55 -0400
Subject: [PATCH] [HLSL] Add copy assignment and construtor to resource types

The wrapper used to hold the handle for resource type has just the
default copy constructor and assignment operator. This causes clang to
insert memcpys when it does an assignment of a resource type. The
memcpy then cause optimizations to fail when the memcpy is turned into a
load and store of an i64.

To fix this, we should define copying of a resource type by adding the
operator= and copy constructor.

Partially fixes #154669
---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 69 +++++++++++++++++++
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   |  2 +
 clang/lib/Sema/HLSLExternalSemaSource.cpp     |  2 +
 3 files changed, 73 insertions(+)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 806800cb7b213..6c39fe504d3f3 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -676,6 +676,75 @@ 
BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
       .finalize();
 }
 
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
+  if (Record->isCompleteDefinition())
+    return *this;
+
+  ASTContext &AST = SemaRef.getASTContext();
+  QualType RecordType = AST.getCanonicalTagType(Record);
+  QualType ConstRecordType = RecordType.withConst();
+  QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+
+  BuiltinTypeMethodBuilder Builder(*this, "", AST.VoidTy, false, true);
+  Builder.addParam("other", ConstRecordRefType);
+  Builder.ensureCompleteDecl();
+
+  ParmVarDecl *OtherParam = Builder.Method->getParamDecl(0);
+
+  Expr *OtherDeclRef = DeclRefExpr::Create(
+      AST, NestedNameSpecifierLoc(), SourceLocation(), OtherParam, false,
+      DeclarationNameInfo(OtherParam->getDeclName(), SourceLocation()),
+      ConstRecordType, VK_LValue);
+
+  FieldDecl *HandleField = getResourceHandleField();
+  Expr *OtherHandleMemberExpr = MemberExpr::CreateImplicit(
+      AST, OtherDeclRef, false, HandleField, HandleField->getType(), VK_LValue,
+      OK_Ordinary);
+
+  return Builder.assign(PH::Handle, OtherHandleMemberExpr).finalize();
+}
+
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
+  if (Record->isCompleteDefinition())
+    return *this;
+
+  ASTContext &AST = SemaRef.getASTContext();
+  QualType RecordType = AST.getCanonicalTagType(Record);
+  QualType ConstRecordType = RecordType.withConst();
+  QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
+  QualType RecordRefType = AST.getLValueReferenceType(RecordType);
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+
+  DeclarationName Name = AST.DeclarationNames.getCXXOperatorName(OO_Equal);
+  BuiltinTypeMethodBuilder Builder(*this, Name, RecordRefType, false, false);
+  Builder.addParam("other", ConstRecordRefType);
+  Builder.ensureCompleteDecl();
+
+  ParmVarDecl *OtherParam = Builder.Method->getParamDecl(0);
+  Expr *OtherDeclRef = DeclRefExpr::Create(
+      AST, NestedNameSpecifierLoc(), SourceLocation(), OtherParam, false,
+      DeclarationNameInfo(OtherParam->getDeclName(), SourceLocation()),
+      ConstRecordType, VK_LValue);
+
+  FieldDecl *HandleField = getResourceHandleField();
+  Expr *OtherHandleMemberExpr = MemberExpr::CreateImplicit(
+      AST, OtherDeclRef, false, HandleField, HandleField->getType(), VK_LValue,
+      OK_Ordinary);
+
+  Builder.assign(PH::Handle, OtherHandleMemberExpr);
+
+  // return *this;
+  CXXThisExpr *This = CXXThisExpr::Create(
+      AST, SourceLocation(), Builder.Method->getFunctionObjectParameterType(),
+      true);
+  Builder.StmtsList.push_back(This);
+
+  return Builder.finalize();
+}
+
 BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
   ASTContext &AST = Record->getASTContext();
   DeclarationName Subscript =
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 098b72692bd3a..4c4c2083a8440 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -80,6 +80,8 @@ class BuiltinTypeDeclBuilder {
   BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
   BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
   BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
+  BuiltinTypeDeclBuilder &addCopyConstructor();
+  BuiltinTypeDeclBuilder &addCopyAssignmentOperator();
 
   // Builtin types methods
   BuiltinTypeDeclBuilder &addLoadMethods();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp 
b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 726581d131623..8c893c0c30baf 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -132,6 +132,8 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl 
*Decl, Sema &S,
   return BuiltinTypeDeclBuilder(S, Decl)
       .addHandleMember(RC, IsROV, RawBuffer)
       .addDefaultHandleConstructor()
+      .addCopyConstructor()
+      .addCopyAssignmentOperator()
       .addHandleConstructorFromBinding()
       .addHandleConstructorFromImplicitBinding();
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to