[clang] Implement `ByteAddressBuffer` Load/Store methods (PR #176058)

Kaitlin Peng via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 20 09:53:21 PST 2026


https://github.com/kmpeng updated https://github.com/llvm/llvm-project/pull/176058

>From 0189a078898dd3639f779e5166f9b09813e347a3 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Thu, 18 Dec 2025 04:28:46 -0800
Subject: [PATCH 01/10] regular uint load/store working, templated WIP

---
 clang/include/clang/Basic/Builtins.td         |  18 +++
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |  58 ++++++++
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 135 +++++++++++++++++-
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   |   2 +
 clang/lib/Sema/HLSLExternalSemaSource.cpp     |   3 +
 clang/lib/Sema/SemaHLSL.cpp                   |  43 ++++++
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl |   9 +-
 .../resources/ByteAddressBuffers-methods.hlsl |  34 +++++
 8 files changed, 299 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 7a639c858d21f..92e6c0bb77ac3 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4977,6 +4977,24 @@ def HLSLResourceLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLByteAddressBufferLoad : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_byteaddressbuffer_load"];
+  let Attributes = [NoThrow];
+  let Prototype = "void(...)";
+}
+
+def HLSLByteAddressBufferLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_byteaddressbuffer_load_with_status"];
+  let Attributes = [NoThrow];
+  let Prototype = "void(...)";
+}
+
+def HLSLByteAddressBufferStore : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_byteaddressbuffer_store"];
+  let Attributes = [NoThrow];
+  let Prototype = "void(...)";
+}
+
 def HLSLResourceUninitializedHandle : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_resource_uninitializedhandle"];
   let Attributes = [NoThrow];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 1b6c3714f7821..0ae3dfa6a2997 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -447,6 +447,64 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 
     return LoadedValue;
   }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load: {
+    Value *HandleOp = EmitScalarExpr(E->getArg(0));
+    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
+    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
+
+    llvm::Type *DataTy = ConvertType(E->getType());
+    llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),
+                                              {DataTy, Builder.getInt1Ty()});
+
+    SmallVector<Value *, 3> Args = {HandleOp, ByteOffsetOp, ElementOffset};
+
+    Value *ResRet = Builder.CreateIntrinsic(
+        RetTy, Intrinsic::dx_resource_load_rawbuffer, Args);
+    return Builder.CreateExtractValue(ResRet, {0}, "ld.value");
+  }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load_with_status: {
+    Value *HandleOp = EmitScalarExpr(E->getArg(0));
+    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
+    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
+
+    // Get the *address* of the status argument to write to it by reference
+    LValue StatusLVal = EmitLValue(E->getArg(2));
+    Address StatusAddr = StatusLVal.getAddress();
+
+    assert(CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&
+           "Only DXIL currently implements load with status");
+
+    llvm::Type *DataTy = ConvertType(E->getType());
+    llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),
+                                              {DataTy, Builder.getInt1Ty()});
+
+    SmallVector<Value *, 3> Args = {HandleOp, ByteOffsetOp, ElementOffset};
+
+    // The load intrinsics give us a (T value, i1 status) pair -
+    // shepherd these into the return value and out reference respectively.
+    Value *ResRet = Builder.CreateIntrinsic(
+        RetTy, Intrinsic::dx_resource_load_rawbuffer, Args, {}, "ld.struct");
+    Value *LoadedValue = Builder.CreateExtractValue(ResRet, {0}, "ld.value");
+    Value *StatusBit = Builder.CreateExtractValue(ResRet, {1}, "ld.status");
+    Value *ExtendedStatus =
+        Builder.CreateZExt(StatusBit, Builder.getInt32Ty(), "ld.status.ext");
+    Builder.CreateStore(ExtendedStatus, StatusAddr);
+
+    return LoadedValue;
+  }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_store: {
+    Value *HandleOp = EmitScalarExpr(E->getArg(0));
+    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
+    Value *ValueOp = EmitScalarExpr(E->getArg(2));
+    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
+
+    SmallVector<Value *, 4> Args = {HandleOp, ByteOffsetOp, ElementOffset,
+                                    ValueOp};
+
+    return Builder.CreateIntrinsic(Intrinsic::dx_resource_store_rawbuffer,
+                                   {HandleOp->getType(), ValueOp->getType()},
+                                   Args);
+  }
   case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
     llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
     return llvm::PoisonValue::get(HandleTy);
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 868f894a03c49..2d149de61aac3 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -153,6 +153,8 @@ struct BuiltinTypeMethodBuilder {
   StorageClass SC;
   llvm::SmallVector<Param> Params;
   llvm::SmallVector<Stmt *> StmtsList;
+  TemplateParameterList *TemplateParams;
+  llvm::SmallVector<NamedDecl *> TemplateParamDecls;
 
   // Argument placeholders, inspired by std::placeholder. These are the indices
   // of arguments to forward to `callBuiltin` and other method builder methods.
@@ -184,11 +186,14 @@ struct BuiltinTypeMethodBuilder {
                            QualType ReturnTy, bool IsConst = false,
                            bool IsCtor = false, StorageClass SC = SC_None)
       : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
-        IsConst(IsConst), IsCtor(IsCtor), SC(SC) {}
+        IsConst(IsConst), IsCtor(IsCtor), SC(SC), TemplateParams(nullptr) {}
 
   BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
                            QualType ReturnTy, bool IsConst = false,
                            bool IsCtor = false, StorageClass SC = SC_None);
+
+  // converttype maybe? - qualtype or template parameter index
+
   BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
 
   ~BuiltinTypeMethodBuilder() { finalize(); }
@@ -199,6 +204,7 @@ struct BuiltinTypeMethodBuilder {
   BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
                                      HLSLParamModifierAttr::Spelling Modifier =
                                          HLSLParamModifierAttr::Keyword_in);
+  QualType addTemplateTypeParam(StringRef Name);
   BuiltinTypeMethodBuilder &declareLocalVar(LocalVar &Var);
   template <typename... Ts>
   BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
@@ -449,6 +455,22 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
   Params.emplace_back(II, Ty, Modifier);
   return *this;
 }
+QualType BuiltinTypeMethodBuilder::addTemplateTypeParam(StringRef Name) {
+  assert(Method == nullptr &&
+         "Cannot add template param, method already created");
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  unsigned Position = static_cast<unsigned>(TemplateParamDecls.size());
+  auto *Decl = TemplateTypeParmDecl::Create(
+      AST, DeclBuilder.Record, SourceLocation(), SourceLocation(),
+      /* TemplateDepth */ 0, Position,
+      &AST.Idents.get(Name, tok::TokenKind::identifier),
+      /* Typename */ true,
+      /* ParameterPack */ false,
+      /* HasTypeConstraint*/ false);
+  TemplateParamDecls.emplace_back(Decl);
+
+  return QualType(Decl->getTypeForDecl(), 0);
+}
 
 void BuiltinTypeMethodBuilder::createDecl() {
   assert(Method == nullptr && "Method or constructor is already created");
@@ -747,7 +769,22 @@ BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
     Method->setAccess(AS_public);
     Method->addAttr(AlwaysInlineAttr::CreateImplicit(
         AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
-    DeclBuilder.Record->addDecl(Method);
+    if (!TemplateParamDecls.empty()) {
+      TemplateParams = TemplateParameterList::Create(
+          AST, SourceLocation(), SourceLocation(), TemplateParamDecls,
+          SourceLocation(), nullptr);
+
+      auto *FuncTemplate = FunctionTemplateDecl::Create(AST, DeclBuilder.Record,
+                                                        SourceLocation(), Name,
+                                                        TemplateParams, Method);
+      FuncTemplate->setAccess(AS_public);
+      FuncTemplate->setLexicalDeclContext(DeclBuilder.Record);
+      FuncTemplate->setImplicit(true);
+      Method->setDescribedFunctionTemplate(FuncTemplate);
+      DeclBuilder.Record->addDecl(FuncTemplate);
+    } else {
+      DeclBuilder.Record->addDecl(Method);
+    }
   }
   return DeclBuilder;
 }
@@ -1145,6 +1182,100 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
   return *this;
 }
 
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
+  assert(!Record->isCompleteDefinition() && "record is already complete");
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  ASTContext &AST = SemaRef.getASTContext();
+
+  // Helper to add uint Load methods
+  auto addLoadMethod = [&](StringRef MethodName, QualType ReturnType) {
+    IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
+    DeclarationName Load(&II);
+
+    // Load without status
+    BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
+        .addParam("byteOffset", AST.UnsignedIntTy)
+        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
+                     PH::Handle, PH::_0)
+        .finalize();
+
+    // Load with status
+    BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
+        .addParam("byteOffset", AST.UnsignedIntTy)
+        .addParam("status", AST.UnsignedIntTy,
+                  HLSLParamModifierAttr::Keyword_out)
+        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load_with_status",
+                     ReturnType, PH::Handle, PH::_0, PH::_1)
+        .finalize();
+  };
+
+  addLoadMethod("Load", AST.UnsignedIntTy);
+  addLoadMethod("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
+  addLoadMethod("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
+  addLoadMethod("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
+
+  // templated
+  {
+    IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
+    DeclarationName Load(&II);
+    BuiltinTypeMethodBuilder Builder(*this, Load, AST.UnsignedIntTy,
+                                     /*IsConst=*/false);
+    QualType TType = Builder.addTemplateTypeParam("element_type");
+    Builder.ReturnTy = TType; // Update return type to template parameter
+
+    Builder.addParam("byteOffset", AST.UnsignedIntTy)
+        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", TType, PH::Handle,
+                     PH::_0)
+        .finalize();
+  }
+
+  return *this;
+}
+
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
+  assert(!Record->isCompleteDefinition() && "record is already complete");
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  ASTContext &AST = SemaRef.getASTContext();
+
+  // Helper to add uint Store methods
+  auto addStoreMethod = [&](StringRef MethodName, QualType ValueType) {
+    IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
+    DeclarationName Store(&II);
+
+    BuiltinTypeMethodBuilder(*this, Store, AST.VoidTy, /*IsConst=*/false)
+        .addParam("byteOffset", AST.UnsignedIntTy)
+        .addParam("value", ValueType)
+        .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
+                     PH::Handle, PH::_0, PH::_1)
+        .finalize();
+  };
+
+  addStoreMethod("Store", AST.UnsignedIntTy);
+  addStoreMethod("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
+  addStoreMethod("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
+  addStoreMethod("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
+
+  // {
+  //   IdentifierInfo &II = AST.Idents.get("Store", tok::TokenKind::identifier);
+  //   DeclarationName Store(&II);
+
+  //   BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy,
+  //   /*IsConst=*/false); QualType TType =
+  //   Builder.addTemplateTypeParam("element_type");
+  //   Builder.addParam("byteOffset", AST.UnsignedIntTy)
+  //         .addParam("value", TType)
+  //         .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
+  //                     PH::Handle, PH::_0, PH::_1)
+  //         .finalize();
+  // }
+
+  return *this;
+}
+
 FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
   auto I = Fields.find("__handle");
   assert(I != Fields.end() &&
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 47c8b0e225612..8309ba990fda0 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -87,6 +87,8 @@ class BuiltinTypeDeclBuilder {
 
   // Builtin types methods
   BuiltinTypeDeclBuilder &addLoadMethods();
+  BuiltinTypeDeclBuilder &addByteAddressBufferLoadMethods();
+  BuiltinTypeDeclBuilder &addByteAddressBufferStoreMethods();
   BuiltinTypeDeclBuilder &addIncrementCounterMethod();
   BuiltinTypeDeclBuilder &addDecrementCounterMethod();
   BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 6be84f19a8f08..948005312f4dd 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -480,6 +480,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
   onCompletion(Decl, [this](CXXRecordDecl *Decl) {
     setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
                     /*RawBuffer=*/true, /*HasCounter=*/false)
+        .addByteAddressBufferLoadMethods()
         .addGetDimensionsMethodForBuffer()
         .completeDefinition();
   });
@@ -488,6 +489,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
   onCompletion(Decl, [this](CXXRecordDecl *Decl) {
     setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
                     /*RawBuffer=*/true, /*HasCounter=*/false)
+        .addByteAddressBufferLoadMethods()
+        .addByteAddressBufferStoreMethods()
         .addGetDimensionsMethodForBuffer()
         .completeDefinition();
   });
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f15b274a65a53..8a4f9becf4440 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3334,7 +3334,50 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     break;
   }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load: {
+    if (SemaRef.checkArgCount(TheCall, 2) ||
+        CheckResourceHandle(&SemaRef, TheCall, 0) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
+                            SemaRef.getASTContext().UnsignedIntTy))
+      return true;
+
+    auto *ResourceTy =
+        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
+    QualType ReturnType = ResourceTy->getContainedType();
+    TheCall->setType(ReturnType);
 
+    break;
+  }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load_with_status: {
+    if (SemaRef.checkArgCount(TheCall, 3) ||
+        CheckResourceHandle(&SemaRef, TheCall, 0) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
+                            SemaRef.getASTContext().UnsignedIntTy) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(2),
+                            SemaRef.getASTContext().UnsignedIntTy) ||
+        CheckModifiableLValue(&SemaRef, TheCall, 2))
+      return true;
+
+    auto *ResourceTy =
+        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
+    QualType ReturnType = ResourceTy->getContainedType();
+    TheCall->setType(ReturnType);
+
+    break;
+  }
+  case Builtin::BI__builtin_hlsl_byteaddressbuffer_store: {
+    if (SemaRef.checkArgCount(TheCall, 3) ||
+        CheckResourceHandle(&SemaRef, TheCall, 0) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
+                            SemaRef.getASTContext().UnsignedIntTy))
+      return true;
+
+    //  || CheckArgTypeMatches(&SemaRef, TheCall->getArg(2),
+    //  SemaRef.getASTContext().UnsignedIntTy)
+
+    TheCall->setType(SemaRef.Context.VoidTy);
+    break;
+  }
   case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
     assert(TheCall->getNumArgs() == 1 && "expected 1 arg");
     // Update return type to be the attributed resource type from arg0.
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 2713cc19ea2be..f2f52945f72f0 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -142,9 +142,16 @@ RESOURCE Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
+// Load method
+
+// CHECK-SRV: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int)'
+// CHECK-SRV: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int, out unsigned int)
+
+// Store method
+
 // GetDimensions method
 
-// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int)'
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int)'
 // CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict'
 // CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-NEXT: CompoundStmt
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index 9dd02287620e7..0233c117bc000 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -12,6 +12,40 @@ RWByteAddressBuffer RWBuf : register(u0);
 // DXIL: @Buf = internal global %"class.hlsl::ByteAddressBuffer" poison
 // DXIL: @RWBuf = internal global %"class.hlsl::RWByteAddressBuffer" poison
 
+export uint TestLoad() {
+    uint u = Buf.Load(0);
+    uint2 v = Buf.Load2(0);
+    float f = Buf.Load<float>(4);
+    //float4 v = RWBuf.Load<float4>(8);
+    return u;
+}
+
+// CHECK: define {{.*}} i32 @TestLoad()()
+// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int)(ptr {{.*}} @Buf, i32 noundef 0)
+// CHECK: ret i32
+
+export uint TestLoadWithStatus() {
+    uint s1;
+    uint u = Buf.Load(0, s1);
+    return u;
+}
+
+// CHECK: define {{.*}} i32 @TestLoadWithStatus()()
+// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 0, ptr {{.*}} %tmp)
+// CHECK: ret i32
+
+export void TestStore() {
+    uint u0;
+    //float f0;
+    RWBuf.Store(0, u0);
+    //RWBuf.Store<float>(0, f0);
+    return;
+}
+
+// CHECK: define void @TestStore()()
+// CHECK: call void @hlsl::RWByteAddressBuffer::Store(unsigned int, unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 0, i32 noundef %{{.*}})
+// CHECK: ret void
+
 export uint TestGetDimensions() {
     uint dim1, dim2;
     Buf.GetDimensions(dim1);

>From af8ba042d25863c7b2b6151fa437fe18b2c1578b Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Thu, 18 Dec 2025 21:47:07 -0800
Subject: [PATCH 02/10] templated load/store mostly working, bugs with
 bool/aggregate types

---
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |   6 +-
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp |  61 +++---
 clang/lib/Sema/SemaHLSL.cpp                   |  15 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  16 +-
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 201 +++++++++++++++++-
 .../resources/ByteAddressBuffers-methods.hlsl |  18 +-
 6 files changed, 268 insertions(+), 49 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 0ae3dfa6a2997..9c753dd0aedc4 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -495,7 +495,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
   case Builtin::BI__builtin_hlsl_byteaddressbuffer_store: {
     Value *HandleOp = EmitScalarExpr(E->getArg(0));
     Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
-    Value *ValueOp = EmitScalarExpr(E->getArg(2));
+    RValue RVal = EmitAnyExpr(E->getArg(2));
+    Value *ValueOp =
+        RVal.isScalar()
+            ? RVal.getScalarVal()
+            : Builder.CreateLoad(RVal.getAggregateAddress(), "store_val");
     Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
 
     SmallVector<Value *, 4> Args = {HandleOp, ByteOffsetOp, ElementOffset,
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 2d149de61aac3..2b014a86b0e6e 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1216,20 +1216,29 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   addLoadMethod("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   addLoadMethod("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
 
-  // templated
-  {
-    IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
-    DeclarationName Load(&II);
-    BuiltinTypeMethodBuilder Builder(*this, Load, AST.UnsignedIntTy,
-                                     /*IsConst=*/false);
-    QualType TType = Builder.addTemplateTypeParam("element_type");
-    Builder.ReturnTy = TType; // Update return type to template parameter
-
-    Builder.addParam("byteOffset", AST.UnsignedIntTy)
-        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", TType, PH::Handle,
-                     PH::_0)
-        .finalize();
-  }
+  // Templated Load method
+  IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
+  DeclarationName Load(&II);
+
+  BuiltinTypeMethodBuilder MMB(*this, Load, AST.UnsignedIntTy,
+                               /*IsConst=*/false);
+  QualType ReturnType = MMB.addTemplateTypeParam("element_type");
+  MMB.ReturnTy = ReturnType; // Update return type to template parameter
+  MMB.addParam("byteOffset", AST.UnsignedIntTy)
+      .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
+                   PH::Handle, PH::_0)
+      .finalize();
+
+  // Templated Load with status method
+  BuiltinTypeMethodBuilder MMB2(*this, Load, AST.UnsignedIntTy,
+                                /*IsConst=*/false);
+  QualType ReturnType2 = MMB2.addTemplateTypeParam("element_type");
+  MMB2.ReturnTy = ReturnType2; // Update return type to template parameter
+  MMB2.addParam("byteOffset", AST.UnsignedIntTy)
+      .addParam("status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
+      .callBuiltin("__builtin_hlsl_byteaddressbuffer_load_with_status",
+                   ReturnType2, PH::Handle, PH::_0, PH::_1)
+      .finalize();
 
   return *this;
 }
@@ -1259,19 +1268,17 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
   addStoreMethod("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   addStoreMethod("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
 
-  // {
-  //   IdentifierInfo &II = AST.Idents.get("Store", tok::TokenKind::identifier);
-  //   DeclarationName Store(&II);
-
-  //   BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy,
-  //   /*IsConst=*/false); QualType TType =
-  //   Builder.addTemplateTypeParam("element_type");
-  //   Builder.addParam("byteOffset", AST.UnsignedIntTy)
-  //         .addParam("value", TType)
-  //         .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
-  //                     PH::Handle, PH::_0, PH::_1)
-  //         .finalize();
-  // }
+  // Templated Store method
+  IdentifierInfo &II = AST.Idents.get("Store", tok::TokenKind::identifier);
+  DeclarationName Store(&II);
+
+  BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy, /*IsConst=*/false);
+  QualType ReturnType = Builder.addTemplateTypeParam("element_type");
+  Builder.addParam("byteOffset", AST.UnsignedIntTy)
+      .addParam("value", ReturnType)
+      .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
+                   PH::Handle, PH::_0, PH::_1)
+      .finalize();
 
   return *this;
 }
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 8a4f9becf4440..17b756830560b 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3341,10 +3341,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
                             SemaRef.getASTContext().UnsignedIntTy))
       return true;
 
-    auto *ResourceTy =
-        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
-    QualType ReturnType = ResourceTy->getContainedType();
-    TheCall->setType(ReturnType);
+    auto *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
+    TheCall->setType(FD->getReturnType());
 
     break;
   }
@@ -3358,10 +3356,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
         CheckModifiableLValue(&SemaRef, TheCall, 2))
       return true;
 
-    auto *ResourceTy =
-        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
-    QualType ReturnType = ResourceTy->getContainedType();
-    TheCall->setType(ReturnType);
+    auto *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
+    TheCall->setType(FD->getReturnType());
 
     break;
   }
@@ -3372,8 +3368,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
                             SemaRef.getASTContext().UnsignedIntTy))
       return true;
 
-    //  || CheckArgTypeMatches(&SemaRef, TheCall->getArg(2),
-    //  SemaRef.getASTContext().UnsignedIntTy)
+    // need to check anything for the 2nd parameter? not an array?
 
     TheCall->setType(SemaRef.Context.VoidTy);
     break;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e74c41517ecbf..348ac5e75af7c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -6901,8 +6901,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   //    whose type is not instantiation dependent, do nothing to the decl
   //  - otherwise find its instantiated decl.
   if (isa<ParmVarDecl>(D) && !ParentDependsOnArgs &&
-      !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType())
-    return D;
+      !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) {
+    // Check if D belongs to a function template
+    auto *PVD = cast<ParmVarDecl>(D);
+    bool IsFromFunctionTemplate =
+        llvm::any_of(ParentDC->decls(), [PVD](Decl *D) {
+          if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+            return llvm::is_contained(FTD->getTemplatedDecl()->parameters(),
+                                      PVD);
+          return false;
+        });
+
+    if (!IsFromFunctionTemplate)
+      return D;
+  }
   if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
       isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
       (ParentDependsOnArgs && (ParentDC->isFunctionOrMethod() ||
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index f2f52945f72f0..d97c28275579d 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -4,7 +4,7 @@
 //
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
 // RUN:   -DRESOURCE=ByteAddressBuffer %s | FileCheck -DRESOURCE=ByteAddressBuffer \
-// RUN:   -check-prefixes=CHECK,CHECK-SRV,CHECK-NOSUBSCRIPT %s
+// RUN:   -check-prefixes=CHECK,CHECK-SRV,CHECK-NOSUBSCRIPT,CHECK-LOAD %s
 //
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
 // RUN:  -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \
@@ -12,7 +12,7 @@
 //
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
 // RUN:   -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \
-// RUN:   -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT %s
+// RUN:   -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT,CHECK-LOAD,CHECK-STORE %s
 //
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
 // RUN:  -DRESOURCE=RasterizerOrderedByteAddressBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedByteAddressBuffer \
@@ -142,12 +142,203 @@ RESOURCE Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
-// Load method
+// Load methods
+
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int)'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'unsigned int'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int, out unsigned int)
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'unsigned int'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int (unsigned int), 2>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 2>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int (unsigned int, out unsigned int), 2>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 2>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int (unsigned int), 3>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 3>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int (unsigned int, out unsigned int), 3>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 3>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int (unsigned int), 4>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 4>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int (unsigned int, out unsigned int), 4>'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 4>'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
-// CHECK-SRV: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int)'
-// CHECK-SRV: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int, out unsigned int)
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-LOAD-NEXT: CompoundStmt
+// CHECK-LOAD-NEXT: ReturnStmt
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type'
+// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Store method
+// CHECK-STORE: CXXMethodDecl {{.*}} Store 'void (unsigned int, unsigned int)'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'unsigned int'
+// CHECK-STORE-NEXT: CompoundStmt
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'value' 'unsigned int'
+// CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-STORE: CXXMethodDecl {{.*}} Store2 'void (unsigned int, vector<unsigned int, 2>)'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 2>'
+// CHECK-STORE-NEXT: CompoundStmt
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 2>' ParmVar {{.*}} 'value' 'vector<unsigned int, 2>'
+// CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-STORE: CXXMethodDecl {{.*}} Store3 'void (unsigned int, vector<unsigned int, 3>)'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 3>'
+// CHECK-STORE-NEXT: CompoundStmt
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 3>' ParmVar {{.*}} 'value' 'vector<unsigned int, 3>'
+// CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-STORE: CXXMethodDecl {{.*}} Store4 'void (unsigned int, vector<unsigned int, 4>)'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 4>'
+// CHECK-STORE-NEXT: CompoundStmt
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 4>' ParmVar {{.*}} 'value' 'vector<unsigned int, 4>'
+// CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// CHECK-STORE: CXXMethodDecl {{.*}} Store 'void (unsigned int, element_type)'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'element_type'
+// CHECK-STORE-NEXT: CompoundStmt
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'element_type' ParmVar {{.*}} 'value' 'element_type'
+// CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // GetDimensions method
 
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index 0233c117bc000..ba6f059c6346b 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -3,6 +3,11 @@
 
 // NOTE: SPIRV codegen for resource methods is not yet implemented
 
+struct SmallStruct {
+  int a;
+  uint b;
+};
+
 ByteAddressBuffer Buf : register(t0);
 RWByteAddressBuffer RWBuf : register(u0);
 
@@ -16,7 +21,8 @@ export uint TestLoad() {
     uint u = Buf.Load(0);
     uint2 v = Buf.Load2(0);
     float f = Buf.Load<float>(4);
-    //float4 v = RWBuf.Load<float4>(8);
+    float4 g = Buf.Load<float4>(8);
+    SmallStruct U9 = Buf.Load<SmallStruct>(0);
     return u;
 }
 
@@ -25,8 +31,10 @@ export uint TestLoad() {
 // CHECK: ret i32
 
 export uint TestLoadWithStatus() {
-    uint s1;
+    uint s1, s2, s3;
     uint u = Buf.Load(0, s1);
+    float f = Buf.Load<float>(4, s2);
+    SmallStruct U9 = Buf.Load<SmallStruct>(0, s3);
     return u;
 }
 
@@ -36,9 +44,11 @@ export uint TestLoadWithStatus() {
 
 export void TestStore() {
     uint u0;
-    //float f0;
+    float f0;
     RWBuf.Store(0, u0);
-    //RWBuf.Store<float>(0, f0);
+    RWBuf.Store<float>(0, f0);
+    SmallStruct TempStruct1;
+    RWBuf.Store<SmallStruct>(144, TempStruct1);
     return;
 }
 

>From 3e692ae8bf06249333d365469922b7e9cd317f00 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Fri, 19 Dec 2025 01:43:59 -0800
Subject: [PATCH 03/10] change load with status and store builtins, change
 param names

---
 clang/include/clang/Basic/Builtins.td         |  10 +-
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |  73 +++++------
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp |  54 +++++---
 clang/lib/Sema/SemaHLSL.cpp                   |  27 ++--
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 120 +++++++++---------
 5 files changed, 139 insertions(+), 145 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 92e6c0bb77ac3..9d708b2980dfe 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4983,14 +4983,8 @@ def HLSLByteAddressBufferLoad : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
-def HLSLByteAddressBufferLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
-  let Spellings = ["__builtin_hlsl_byteaddressbuffer_load_with_status"];
-  let Attributes = [NoThrow];
-  let Prototype = "void(...)";
-}
-
-def HLSLByteAddressBufferStore : LangBuiltin<"HLSL_LANG"> {
-  let Spellings = ["__builtin_hlsl_byteaddressbuffer_store"];
+def HLSLResourceStore : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_resource_store"];
   let Attributes = [NoThrow];
   let Prototype = "void(...)";
 }
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 9c753dd0aedc4..c3337ada45ee0 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -400,6 +400,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *IndexOp = EmitScalarExpr(E->getArg(1));
 
     llvm::Type *RetTy = ConvertType(E->getType());
+    // byteaddressbufferload attempt
+    // tried replacing last parameter with a SmallVector<Value *> Args like
+    // load_with_status where the last arg is poison but that broke every
+    // intrinsic that uses this builtin
     return Builder.CreateIntrinsic(
         RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
         ArrayRef<Value *>{HandleOp, IndexOp});
@@ -432,6 +436,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 
     if (RT->getAttrs().RawBuffer) {
       Value *Offset = Builder.getInt32(0);
+      // Offset is poison for ByteAddressBuffer
+      if (RT->getContainedType()->isChar8Type())
+        Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
       Args.push_back(Offset);
     }
 
@@ -449,65 +456,49 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
   }
   case Builtin::BI__builtin_hlsl_byteaddressbuffer_load: {
     Value *HandleOp = EmitScalarExpr(E->getArg(0));
-    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
-    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
+    Value *IndexOp = EmitScalarExpr(E->getArg(1));
+    Value *Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
 
     llvm::Type *DataTy = ConvertType(E->getType());
     llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),
                                               {DataTy, Builder.getInt1Ty()});
 
-    SmallVector<Value *, 3> Args = {HandleOp, ByteOffsetOp, ElementOffset};
+    SmallVector<Value *, 3> Args = {HandleOp, IndexOp, Offset};
 
     Value *ResRet = Builder.CreateIntrinsic(
         RetTy, Intrinsic::dx_resource_load_rawbuffer, Args);
     return Builder.CreateExtractValue(ResRet, {0}, "ld.value");
   }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load_with_status: {
+  case Builtin::BI__builtin_hlsl_resource_store: {
     Value *HandleOp = EmitScalarExpr(E->getArg(0));
-    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
-    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
-
-    // Get the *address* of the status argument to write to it by reference
-    LValue StatusLVal = EmitLValue(E->getArg(2));
-    Address StatusAddr = StatusLVal.getAddress();
-
-    assert(CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&
-           "Only DXIL currently implements load with status");
-
-    llvm::Type *DataTy = ConvertType(E->getType());
-    llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),
-                                              {DataTy, Builder.getInt1Ty()});
-
-    SmallVector<Value *, 3> Args = {HandleOp, ByteOffsetOp, ElementOffset};
-
-    // The load intrinsics give us a (T value, i1 status) pair -
-    // shepherd these into the return value and out reference respectively.
-    Value *ResRet = Builder.CreateIntrinsic(
-        RetTy, Intrinsic::dx_resource_load_rawbuffer, Args, {}, "ld.struct");
-    Value *LoadedValue = Builder.CreateExtractValue(ResRet, {0}, "ld.value");
-    Value *StatusBit = Builder.CreateExtractValue(ResRet, {1}, "ld.status");
-    Value *ExtendedStatus =
-        Builder.CreateZExt(StatusBit, Builder.getInt32Ty(), "ld.status.ext");
-    Builder.CreateStore(ExtendedStatus, StatusAddr);
-
-    return LoadedValue;
-  }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_store: {
-    Value *HandleOp = EmitScalarExpr(E->getArg(0));
-    Value *ByteOffsetOp = EmitScalarExpr(E->getArg(1));
+    Value *IndexOp = EmitScalarExpr(E->getArg(1));
     RValue RVal = EmitAnyExpr(E->getArg(2));
     Value *ValueOp =
         RVal.isScalar()
             ? RVal.getScalarVal()
             : Builder.CreateLoad(RVal.getAggregateAddress(), "store_val");
-    Value *ElementOffset = llvm::PoisonValue::get(Builder.getInt32Ty());
 
-    SmallVector<Value *, 4> Args = {HandleOp, ByteOffsetOp, ElementOffset,
-                                    ValueOp};
+    QualType HandleTy = E->getArg(0)->getType();
+    const HLSLAttributedResourceType *RT =
+        HandleTy->getAs<HLSLAttributedResourceType>();
+    Intrinsic::ID IntrID = RT->getAttrs().RawBuffer
+                               ? llvm::Intrinsic::dx_resource_store_rawbuffer
+                               : llvm::Intrinsic::dx_resource_store_typedbuffer;
 
-    return Builder.CreateIntrinsic(Intrinsic::dx_resource_store_rawbuffer,
-                                   {HandleOp->getType(), ValueOp->getType()},
-                                   Args);
+    SmallVector<Value *, 4> Args;
+    Args.push_back(HandleOp);
+    Args.push_back(IndexOp);
+    if (RT->getAttrs().RawBuffer) {
+      Value *Offset = Builder.getInt32(0);
+      // Offset is poison for ByteAddressBuffer
+      if (RT->getContainedType()->isChar8Type())
+        Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
+      Args.push_back(Offset);
+    }
+    Args.push_back(ValueOp);
+
+    return Builder.CreateIntrinsic(
+        IntrID, {HandleOp->getType(), ValueOp->getType()}, Args);
   }
   case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
     llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 2b014a86b0e6e..c1d4e9299a502 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1189,25 +1189,25 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
   ASTContext &AST = SemaRef.getASTContext();
 
-  // Helper to add uint Load methods
+  // Add uint Load methods
   auto addLoadMethod = [&](StringRef MethodName, QualType ReturnType) {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Load(&II);
 
     // Load without status
     BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
-        .addParam("byteOffset", AST.UnsignedIntTy)
+        .addParam("Index", AST.UnsignedIntTy)
         .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
                      PH::Handle, PH::_0)
         .finalize();
 
     // Load with status
     BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
-        .addParam("byteOffset", AST.UnsignedIntTy)
-        .addParam("status", AST.UnsignedIntTy,
+        .addParam("Index", AST.UnsignedIntTy)
+        .addParam("Status", AST.UnsignedIntTy,
                   HLSLParamModifierAttr::Keyword_out)
-        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load_with_status",
-                     ReturnType, PH::Handle, PH::_0, PH::_1)
+        .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnType,
+                     PH::Handle, PH::_0, PH::_1)
         .finalize();
   };
 
@@ -1224,20 +1224,34 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
                                /*IsConst=*/false);
   QualType ReturnType = MMB.addTemplateTypeParam("element_type");
   MMB.ReturnTy = ReturnType; // Update return type to template parameter
-  MMB.addParam("byteOffset", AST.UnsignedIntTy)
+  MMB.addParam("Index", AST.UnsignedIntTy)
       .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
                    PH::Handle, PH::_0)
       .finalize();
 
+  // __builtin_hlsl_resource_getpointer attempt
+  // BuiltinTypeMethodBuilder MMB(*this, Load, AST.UnsignedIntTy,
+  //                              /*IsConst=*/false);
+  // QualType ReturnType = MMB.addTemplateTypeParam("element_type");
+  // MMB.ReturnTy = ReturnType; // Update return type to template parameter
+  // QualType AddrSpaceElemTy =
+  //     AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
+  // QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
+  // MMB.addParam("Index", AST.UnsignedIntTy)
+  //     .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
+  //                  PH::Handle, PH::_0)
+  //     .dereference(PH::LastStmt)
+  //     .finalize();
+
   // Templated Load with status method
   BuiltinTypeMethodBuilder MMB2(*this, Load, AST.UnsignedIntTy,
                                 /*IsConst=*/false);
   QualType ReturnType2 = MMB2.addTemplateTypeParam("element_type");
   MMB2.ReturnTy = ReturnType2; // Update return type to template parameter
-  MMB2.addParam("byteOffset", AST.UnsignedIntTy)
-      .addParam("status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
-      .callBuiltin("__builtin_hlsl_byteaddressbuffer_load_with_status",
-                   ReturnType2, PH::Handle, PH::_0, PH::_1)
+  MMB2.addParam("Index", AST.UnsignedIntTy)
+      .addParam("Status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
+      .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnType2,
+                   PH::Handle, PH::_0, PH::_1)
       .finalize();
 
   return *this;
@@ -1256,10 +1270,10 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
     DeclarationName Store(&II);
 
     BuiltinTypeMethodBuilder(*this, Store, AST.VoidTy, /*IsConst=*/false)
-        .addParam("byteOffset", AST.UnsignedIntTy)
-        .addParam("value", ValueType)
-        .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
-                     PH::Handle, PH::_0, PH::_1)
+        .addParam("Index", AST.UnsignedIntTy)
+        .addParam("Value", ValueType)
+        .callBuiltin("__builtin_hlsl_resource_store", AST.VoidTy, PH::Handle,
+                     PH::_0, PH::_1)
         .finalize();
   };
 
@@ -1273,11 +1287,11 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
   DeclarationName Store(&II);
 
   BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy, /*IsConst=*/false);
-  QualType ReturnType = Builder.addTemplateTypeParam("element_type");
-  Builder.addParam("byteOffset", AST.UnsignedIntTy)
-      .addParam("value", ReturnType)
-      .callBuiltin("__builtin_hlsl_byteaddressbuffer_store", AST.VoidTy,
-                   PH::Handle, PH::_0, PH::_1)
+  QualType ValueType = Builder.addTemplateTypeParam("element_type");
+  Builder.addParam("Index", AST.UnsignedIntTy)
+      .addParam("Value", ValueType)
+      .callBuiltin("__builtin_hlsl_resource_store", AST.VoidTy, PH::Handle,
+                   PH::_0, PH::_1)
       .finalize();
 
   return *this;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 17b756830560b..704579394b4cc 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3309,6 +3309,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ContainedTy = ResourceTy->getContainedType();
+    // byteaddressbuffer load attempt
+    // if (ResourceTy->getAttrs().RawBuffer && ContainedTy->isChar8Type()) {
+    //   ContainedTy =
+    //   dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
+    // }
     auto ReturnType =
         SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
     ReturnType = SemaRef.Context.getPointerType(ReturnType);
@@ -3330,6 +3335,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
+    // ByteAddressBuffer returns FunctionDecl return type instead of contained
+    // type
+    if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
+      ReturnType = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
+    }
     TheCall->setType(ReturnType);
 
     break;
@@ -3346,22 +3356,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     break;
   }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load_with_status: {
-    if (SemaRef.checkArgCount(TheCall, 3) ||
-        CheckResourceHandle(&SemaRef, TheCall, 0) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
-                            SemaRef.getASTContext().UnsignedIntTy) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(2),
-                            SemaRef.getASTContext().UnsignedIntTy) ||
-        CheckModifiableLValue(&SemaRef, TheCall, 2))
-      return true;
-
-    auto *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
-    TheCall->setType(FD->getReturnType());
-
-    break;
-  }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_store: {
+  case Builtin::BI__builtin_hlsl_resource_store: {
     if (SemaRef.checkArgCount(TheCall, 3) ||
         CheckResourceHandle(&SemaRef, TheCall, 0) ||
         CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index d97c28275579d..7c2c51a895071 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -145,7 +145,7 @@ RESOURCE Buffer;
 // Load methods
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int)'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'unsigned int'
@@ -153,25 +153,25 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int, out unsigned int)
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'unsigned int'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int (unsigned int), 2>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 2>'
@@ -179,25 +179,25 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int (unsigned int, out unsigned int), 2>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 2>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int (unsigned int), 3>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 3>'
@@ -205,25 +205,25 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int (unsigned int, out unsigned int), 3>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 3>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int (unsigned int), 4>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 4>'
@@ -231,25 +231,25 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int (unsigned int, out unsigned int), 4>'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 4>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type'
@@ -257,87 +257,87 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} status 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load_with_status' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'status' 'unsigned int &__restrict'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Store method
 // CHECK-STORE: CXXMethodDecl {{.*}} Store 'void (unsigned int, unsigned int)'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'unsigned int'
 // CHECK-STORE-NEXT: CompoundStmt
 // CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'value' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Value' 'unsigned int'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-STORE: CXXMethodDecl {{.*}} Store2 'void (unsigned int, vector<unsigned int, 2>)'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 2>'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 2>'
 // CHECK-STORE-NEXT: CompoundStmt
 // CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 2>' ParmVar {{.*}} 'value' 'vector<unsigned int, 2>'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 2>' ParmVar {{.*}} 'Value' 'vector<unsigned int, 2>'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-STORE: CXXMethodDecl {{.*}} Store3 'void (unsigned int, vector<unsigned int, 3>)'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 3>'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 3>'
 // CHECK-STORE-NEXT: CompoundStmt
 // CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 3>' ParmVar {{.*}} 'value' 'vector<unsigned int, 3>'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 3>' ParmVar {{.*}} 'Value' 'vector<unsigned int, 3>'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-STORE: CXXMethodDecl {{.*}} Store4 'void (unsigned int, vector<unsigned int, 4>)'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'vector<unsigned int, 4>'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 4>'
 // CHECK-STORE-NEXT: CompoundStmt
 // CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 4>' ParmVar {{.*}} 'value' 'vector<unsigned int, 4>'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'vector<unsigned int, 4>' ParmVar {{.*}} 'Value' 'vector<unsigned int, 4>'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-STORE: CXXMethodDecl {{.*}} Store 'void (unsigned int, element_type)'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} byteOffset 'unsigned int'
-// CHECK-STORE-NEXT: ParmVarDecl {{.*}} value 'element_type'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
+// CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'element_type'
 // CHECK-STORE-NEXT: CompoundStmt
 // CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'byteOffset' 'unsigned int'
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'element_type' ParmVar {{.*}} 'value' 'element_type'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'element_type' ParmVar {{.*}} 'Value' 'element_type'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // GetDimensions method

>From 9f52ba82dd996a2ff654c7326a6ac74fa3caeca0 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Fri, 19 Dec 2025 15:45:45 -0800
Subject: [PATCH 04/10] change load builtin, bugs with vector uint loads

---
 clang/include/clang/Basic/Builtins.td         |  6 ----
 clang/lib/AST/ExprConstant.cpp                |  5 +++
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          | 19 ------------
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 31 ++++++++-----------
 clang/lib/Sema/SemaHLSL.cpp                   | 24 ++++----------
 5 files changed, 24 insertions(+), 61 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 9d708b2980dfe..344ff56f21a43 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4977,12 +4977,6 @@ def HLSLResourceLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
-def HLSLByteAddressBufferLoad : LangBuiltin<"HLSL_LANG"> {
-  let Spellings = ["__builtin_hlsl_byteaddressbuffer_load"];
-  let Attributes = [NoThrow];
-  let Prototype = "void(...)";
-}
-
 def HLSLResourceStore : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_resource_store"];
   let Attributes = [NoThrow];
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2a228d2896730..99bcf9c51e4dc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11974,6 +11974,11 @@ static std::optional<APValue> handleVectorUnaryOperator(ASTContext &Ctx,
 
 bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   Expr *SubExpr = E->getSubExpr();
+  // solution #2?
+  // auto Pointee = SubExpr->getType();
+  // if (const auto *PT = SubExpr->getType()->getAs<clang::PointerType>())
+  //   Pointee = PT->getPointeeType();
+  // const auto *VD = Pointee->castAs<VectorType>();
   const auto *VD = SubExpr->getType()->castAs<VectorType>();
   // This result element type differs in the case of negating a floating point
   // vector, since the result type is the a vector of the equivilant sized
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index c3337ada45ee0..9ac87c6a3f12e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -400,10 +400,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *IndexOp = EmitScalarExpr(E->getArg(1));
 
     llvm::Type *RetTy = ConvertType(E->getType());
-    // byteaddressbufferload attempt
-    // tried replacing last parameter with a SmallVector<Value *> Args like
-    // load_with_status where the last arg is poison but that broke every
-    // intrinsic that uses this builtin
     return Builder.CreateIntrinsic(
         RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
         ArrayRef<Value *>{HandleOp, IndexOp});
@@ -454,21 +450,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 
     return LoadedValue;
   }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load: {
-    Value *HandleOp = EmitScalarExpr(E->getArg(0));
-    Value *IndexOp = EmitScalarExpr(E->getArg(1));
-    Value *Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
-
-    llvm::Type *DataTy = ConvertType(E->getType());
-    llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),
-                                              {DataTy, Builder.getInt1Ty()});
-
-    SmallVector<Value *, 3> Args = {HandleOp, IndexOp, Offset};
-
-    Value *ResRet = Builder.CreateIntrinsic(
-        RetTy, Intrinsic::dx_resource_load_rawbuffer, Args);
-    return Builder.CreateExtractValue(ResRet, {0}, "ld.value");
-  }
   case Builtin::BI__builtin_hlsl_resource_store: {
     Value *HandleOp = EmitScalarExpr(E->getArg(0));
     Value *IndexOp = EmitScalarExpr(E->getArg(1));
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index c1d4e9299a502..9d2885c4c2e00 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -637,7 +637,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
   Expr *Deref =
       UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
                             UO_Deref, PtrExpr->getType()->getPointeeType(),
-                            VK_PRValue, OK_Ordinary, SourceLocation(),
+                            /*solution #1? use VK_LValue instead*/ VK_PRValue,
+                            OK_Ordinary, SourceLocation(),
                             /*CanOverflow=*/false, FPOptionsOverride());
   StmtsList.push_back(Deref);
   return *this;
@@ -1195,10 +1196,14 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
     DeclarationName Load(&II);
 
     // Load without status
+    QualType AddrSpaceElemTy =
+        AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
+    QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
     BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
         .addParam("Index", AST.UnsignedIntTy)
-        .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
+        .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
                      PH::Handle, PH::_0)
+        .dereference(PH::LastStmt)
         .finalize();
 
     // Load with status
@@ -1224,25 +1229,15 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
                                /*IsConst=*/false);
   QualType ReturnType = MMB.addTemplateTypeParam("element_type");
   MMB.ReturnTy = ReturnType; // Update return type to template parameter
+  QualType AddrSpaceElemTy =
+      AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
+  QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
   MMB.addParam("Index", AST.UnsignedIntTy)
-      .callBuiltin("__builtin_hlsl_byteaddressbuffer_load", ReturnType,
-                   PH::Handle, PH::_0)
+      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
+                   PH::_0)
+      .dereference(PH::LastStmt)
       .finalize();
 
-  // __builtin_hlsl_resource_getpointer attempt
-  // BuiltinTypeMethodBuilder MMB(*this, Load, AST.UnsignedIntTy,
-  //                              /*IsConst=*/false);
-  // QualType ReturnType = MMB.addTemplateTypeParam("element_type");
-  // MMB.ReturnTy = ReturnType; // Update return type to template parameter
-  // QualType AddrSpaceElemTy =
-  //     AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
-  // QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
-  // MMB.addParam("Index", AST.UnsignedIntTy)
-  //     .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
-  //                  PH::Handle, PH::_0)
-  //     .dereference(PH::LastStmt)
-  //     .finalize();
-
   // Templated Load with status method
   BuiltinTypeMethodBuilder MMB2(*this, Load, AST.UnsignedIntTy,
                                 /*IsConst=*/false);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 704579394b4cc..c3728d79dd662 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3309,11 +3309,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ContainedTy = ResourceTy->getContainedType();
-    // byteaddressbuffer load attempt
-    // if (ResourceTy->getAttrs().RawBuffer && ContainedTy->isChar8Type()) {
-    //   ContainedTy =
-    //   dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
-    // }
+    // ByteAddressBuffer uses FunctionDecl return type instead of contained
+    // type
+    if (ResourceTy->getAttrs().RawBuffer && ContainedTy->isChar8Type()) {
+      ContainedTy = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
+    }
     auto ReturnType =
         SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
     ReturnType = SemaRef.Context.getPointerType(ReturnType);
@@ -3335,7 +3335,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
-    // ByteAddressBuffer returns FunctionDecl return type instead of contained
+    // ByteAddressBuffer uses FunctionDecl return type instead of contained
     // type
     if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
       ReturnType = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
@@ -3344,18 +3344,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     break;
   }
-  case Builtin::BI__builtin_hlsl_byteaddressbuffer_load: {
-    if (SemaRef.checkArgCount(TheCall, 2) ||
-        CheckResourceHandle(&SemaRef, TheCall, 0) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
-                            SemaRef.getASTContext().UnsignedIntTy))
-      return true;
-
-    auto *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
-    TheCall->setType(FD->getReturnType());
-
-    break;
-  }
   case Builtin::BI__builtin_hlsl_resource_store: {
     if (SemaRef.checkArgCount(TheCall, 3) ||
         CheckResourceHandle(&SemaRef, TheCall, 0) ||

>From 3186e233cd3cf55c5e90dbcb72636f28bdf1c865 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Tue, 23 Dec 2025 15:17:25 -0800
Subject: [PATCH 05/10] fix load bugs, change store to use
 __builtin_hlsl_resource_getpointer, bugs with templated store

---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 21 +++++++++++++------
 .../test/AST/HLSL/StructuredBuffers-AST.hlsl  | 10 ++++-----
 clang/test/AST/HLSL/TypedBuffers-AST.hlsl     |  6 +++---
 3 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 9d2885c4c2e00..2a08bbfcf16ee 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -637,8 +637,7 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
   Expr *Deref =
       UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
                             UO_Deref, PtrExpr->getType()->getPointeeType(),
-                            /*solution #1? use VK_LValue instead*/ VK_PRValue,
-                            OK_Ordinary, SourceLocation(),
+                            VK_LValue, OK_Ordinary, SourceLocation(),
                             /*CanOverflow=*/false, FPOptionsOverride());
   StmtsList.push_back(Deref);
   return *this;
@@ -1264,11 +1263,16 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Store(&II);
 
+    QualType AddrSpaceElemTy =
+        AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
+    QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
     BuiltinTypeMethodBuilder(*this, Store, AST.VoidTy, /*IsConst=*/false)
         .addParam("Index", AST.UnsignedIntTy)
         .addParam("Value", ValueType)
-        .callBuiltin("__builtin_hlsl_resource_store", AST.VoidTy, PH::Handle,
-                     PH::_0, PH::_1)
+        .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
+                     PH::Handle, PH::_0)
+        .dereference(PH::LastStmt)
+        .assign(PH::LastStmt, PH::_1)
         .finalize();
   };
 
@@ -1283,10 +1287,15 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
 
   BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy, /*IsConst=*/false);
   QualType ValueType = Builder.addTemplateTypeParam("element_type");
+  QualType AddrSpaceElemTy =
+      AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
+  QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
   Builder.addParam("Index", AST.UnsignedIntTy)
       .addParam("Value", ValueType)
-      .callBuiltin("__builtin_hlsl_resource_store", AST.VoidTy, PH::Handle,
-                   PH::_0, PH::_1)
+      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
+                   PH::_0)
+      .dereference(PH::LastStmt)
+      .assign(PH::LastStmt, PH::_1)
       .finalize();
 
   return *this;
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index eb65a28dba6ff..4a3df5de59fa2 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -275,7 +275,7 @@ RESOURCE<float> Buffer;
 // CHECK-SUBSCRIPT-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-SUBSCRIPT-NEXT: CompoundStmt
 // CHECK-SUBSCRIPT-NEXT: ReturnStmt
-// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-SUBSCRIPT-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -292,7 +292,7 @@ RESOURCE<float> Buffer;
 // CHECK-SUBSCRIPT-UAV-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-SUBSCRIPT-UAV-NEXT: CompoundStmt
 // CHECK-SUBSCRIPT-UAV-NEXT: ReturnStmt
-// CHECK-SUBSCRIPT-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-SUBSCRIPT-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-SUBSCRIPT-UAV-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-SUBSCRIPT-UAV-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-SUBSCRIPT-UAV-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -314,7 +314,7 @@ RESOURCE<float> Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-LOAD-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -384,7 +384,7 @@ RESOURCE<float> Buffer;
 // CHECK-APPEND-NEXT: ParmVarDecl {{.*}} value 'element_type'
 // CHECK-APPEND-NEXT: CompoundStmt
 // CHECK-APPEND-NEXT: BinaryOperator {{.*}} 'hlsl_device element_type' '='
-// CHECK-APPEND-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-APPEND-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-APPEND-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-APPEND-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-APPEND-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -409,7 +409,7 @@ RESOURCE<float> Buffer;
 // CHECK-CONSUME: CXXMethodDecl {{.*}} Consume 'element_type ()'
 // CHECK-CONSUME-NEXT: CompoundStmt
 // CHECK-CONSUME-NEXT: ReturnStmt
-// CHECK-CONSUME-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-CONSUME-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-CONSUME-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-CONSUME-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-CONSUME-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 762386c622dad..9a4a3e137e0c4 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -166,7 +166,7 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: ReturnStmt
-// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}}  '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -183,7 +183,7 @@ RESOURCE<float> Buffer;
 // CHECK-UAV-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-UAV-NEXT: CompoundStmt
 // CHECK-UAV-NEXT: ReturnStmt
-// CHECK-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-UAV-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-UAV-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-UAV-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}}  '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
@@ -201,7 +201,7 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: ReturnStmt
-// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow
+// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
 // CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} <BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}}  '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'

>From dbb45a3e6d130864ba6ded3d2e85e862ce27b0cb Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Wed, 14 Jan 2026 01:01:18 -0800
Subject: [PATCH 06/10] fix templated store

---
 clang/include/clang/Basic/Builtins.td         |  6 --
 clang/lib/AST/ExprConstant.cpp                |  5 --
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          | 31 -----------
 clang/lib/Sema/SemaHLSL.cpp                   | 33 +++++------
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 55 ++++++++++++-------
 5 files changed, 50 insertions(+), 80 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 344ff56f21a43..7a639c858d21f 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4977,12 +4977,6 @@ def HLSLResourceLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
-def HLSLResourceStore : LangBuiltin<"HLSL_LANG"> {
-  let Spellings = ["__builtin_hlsl_resource_store"];
-  let Attributes = [NoThrow];
-  let Prototype = "void(...)";
-}
-
 def HLSLResourceUninitializedHandle : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_resource_uninitializedhandle"];
   let Attributes = [NoThrow];
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 99bcf9c51e4dc..2a228d2896730 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11974,11 +11974,6 @@ static std::optional<APValue> handleVectorUnaryOperator(ASTContext &Ctx,
 
 bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   Expr *SubExpr = E->getSubExpr();
-  // solution #2?
-  // auto Pointee = SubExpr->getType();
-  // if (const auto *PT = SubExpr->getType()->getAs<clang::PointerType>())
-  //   Pointee = PT->getPointeeType();
-  // const auto *VD = Pointee->castAs<VectorType>();
   const auto *VD = SubExpr->getType()->castAs<VectorType>();
   // This result element type differs in the case of negating a floating point
   // vector, since the result type is the a vector of the equivilant sized
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 9ac87c6a3f12e..98708f23a35e6 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -450,37 +450,6 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 
     return LoadedValue;
   }
-  case Builtin::BI__builtin_hlsl_resource_store: {
-    Value *HandleOp = EmitScalarExpr(E->getArg(0));
-    Value *IndexOp = EmitScalarExpr(E->getArg(1));
-    RValue RVal = EmitAnyExpr(E->getArg(2));
-    Value *ValueOp =
-        RVal.isScalar()
-            ? RVal.getScalarVal()
-            : Builder.CreateLoad(RVal.getAggregateAddress(), "store_val");
-
-    QualType HandleTy = E->getArg(0)->getType();
-    const HLSLAttributedResourceType *RT =
-        HandleTy->getAs<HLSLAttributedResourceType>();
-    Intrinsic::ID IntrID = RT->getAttrs().RawBuffer
-                               ? llvm::Intrinsic::dx_resource_store_rawbuffer
-                               : llvm::Intrinsic::dx_resource_store_typedbuffer;
-
-    SmallVector<Value *, 4> Args;
-    Args.push_back(HandleOp);
-    Args.push_back(IndexOp);
-    if (RT->getAttrs().RawBuffer) {
-      Value *Offset = Builder.getInt32(0);
-      // Offset is poison for ByteAddressBuffer
-      if (RT->getContainedType()->isChar8Type())
-        Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
-      Args.push_back(Offset);
-    }
-    Args.push_back(ValueOp);
-
-    return Builder.CreateIntrinsic(
-        IntrID, {HandleOp->getType(), ValueOp->getType()}, Args);
-  }
   case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
     llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
     return llvm::PoisonValue::get(HandleTy);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c3728d79dd662..a705e5d9792f3 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3308,14 +3308,22 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
-    QualType ContainedTy = ResourceTy->getContainedType();
-    // ByteAddressBuffer uses FunctionDecl return type instead of contained
+    QualType ElementTy = ResourceTy->getContainedType();
+    // ByteAddressBuffer uses the FunctionDecl types instead of the contained
     // type
-    if (ResourceTy->getAttrs().RawBuffer && ContainedTy->isChar8Type()) {
-      ContainedTy = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
+    if (ResourceTy->getAttrs().RawBuffer && ElementTy->isChar8Type()) {
+      // Load method uses return type
+      FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
+      ElementTy = FD->getReturnType();
+      // Store method uses 2nd parameter type
+      if (ElementTy->isVoidType()) {
+        assert(FD->getNumParams() == 2 &&
+               "expected 2 parameters for Store method");
+        ElementTy = FD->getParamDecl(1)->getType();
+      }
     }
     auto ReturnType =
-        SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
+        SemaRef.Context.getAddrSpaceQualType(ElementTy, LangAS::hlsl_device);
     ReturnType = SemaRef.Context.getPointerType(ReturnType);
     TheCall->setType(ReturnType);
     TheCall->setValueKind(VK_LValue);
@@ -3335,8 +3343,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
-    // ByteAddressBuffer uses FunctionDecl return type instead of contained
-    // type
+    // ByteAddressBuffer uses the FunctionDecl return type instead of the
+    // contained type
     if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
       ReturnType = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
     }
@@ -3344,18 +3352,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     break;
   }
-  case Builtin::BI__builtin_hlsl_resource_store: {
-    if (SemaRef.checkArgCount(TheCall, 3) ||
-        CheckResourceHandle(&SemaRef, TheCall, 0) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
-                            SemaRef.getASTContext().UnsignedIntTy))
-      return true;
-
-    // need to check anything for the 2nd parameter? not an array?
 
-    TheCall->setType(SemaRef.Context.VoidTy);
-    break;
-  }
   case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
     assert(TheCall->getNumArgs() == 1 && "expected 1 arg");
     // Update return type to be the attributed resource type from arg0.
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 7c2c51a895071..212c8b0cbbb39 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -148,9 +148,10 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'unsigned int'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device unsigned int' lvalue prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'hlsl_device unsigned int *'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -174,9 +175,10 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 2>'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 2>' lvalue prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 2>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -200,9 +202,10 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 3>'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 3>' lvalue prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 3>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -226,9 +229,10 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int, 4>'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 4>' lvalue prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 4>'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -252,9 +256,10 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: CompoundStmt
 // CHECK-LOAD-NEXT: ReturnStmt
-// CHECK-LOAD-NEXT: CallExpr {{.*}} 'element_type'
+// CHECK-LOAD-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
+// CHECK-LOAD-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_byteaddressbuffer_load' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -279,9 +284,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'unsigned int'
 // CHECK-STORE-NEXT: CompoundStmt
-// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: BinaryOperator {{.*}} 'hlsl_device unsigned int' '='
+// CHECK-STORE-NEXT: UnaryOperator {{.*}} 'hlsl_device unsigned int' lvalue prefix '*' cannot overflow
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'hlsl_device unsigned int *'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -292,9 +299,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 2>'
 // CHECK-STORE-NEXT: CompoundStmt
-// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: BinaryOperator {{.*}} 'vector<unsigned int hlsl_device, 2>' '='
+// CHECK-STORE-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 2>' lvalue prefix '*' cannot overflow
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 2>'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -305,9 +314,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 3>'
 // CHECK-STORE-NEXT: CompoundStmt
-// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: BinaryOperator {{.*}} 'vector<unsigned int hlsl_device, 3>' '='
+// CHECK-STORE-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 3>' lvalue prefix '*' cannot overflow
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 3>'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -318,9 +329,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'vector<unsigned int, 4>'
 // CHECK-STORE-NEXT: CompoundStmt
-// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: BinaryOperator {{.*}} 'vector<unsigned int hlsl_device, 4>' '='
+// CHECK-STORE-NEXT: UnaryOperator {{.*}} 'vector<unsigned int hlsl_device, 4>' lvalue prefix '*' cannot overflow
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'vector<unsigned int hlsl_device *, 4>'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
@@ -331,9 +344,11 @@ RESOURCE Buffer;
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-STORE-NEXT: ParmVarDecl {{.*}} Value 'element_type'
 // CHECK-STORE-NEXT: CompoundStmt
-// CHECK-STORE-NEXT: CallExpr {{.*}} 'void'
+// CHECK-STORE-NEXT: BinaryOperator {{.*}} 'hlsl_device element_type' '='
+// CHECK-STORE-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' lvalue prefix '*' cannot overflow
+// CHECK-STORE-NEXT: CallExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-STORE-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_store' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
 // CHECK-STORE-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
 // CHECK-STORE-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'

>From f3bc01e2aee9489f7621461bdd25c824b66fe0d8 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Wed, 14 Jan 2026 15:05:10 -0800
Subject: [PATCH 07/10] finish tests, clean up code

---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp |  87 +++------
 .../resources/ByteAddressBuffers-methods.hlsl | 174 +++++++++++++++---
 2 files changed, 171 insertions(+), 90 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 2a08bbfcf16ee..fea27d487526c 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -191,9 +191,6 @@ struct BuiltinTypeMethodBuilder {
   BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
                            QualType ReturnTy, bool IsConst = false,
                            bool IsCtor = false, StorageClass SC = SC_None);
-
-  // converttype maybe? - qualtype or template parameter index
-
   BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
 
   ~BuiltinTypeMethodBuilder() { finalize(); }
@@ -1189,25 +1186,33 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
   ASTContext &AST = SemaRef.getASTContext();
 
-  // Add uint Load methods
   auto addLoadMethod = [&](StringRef MethodName, QualType ReturnType) {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Load(&II);
 
     // Load without status
+    BuiltinTypeMethodBuilder MMB(*this, Load, ReturnType);
+    if (ReturnType->isDependentType()) {
+      ReturnType = MMB.addTemplateTypeParam("element_type");
+      MMB.ReturnTy = ReturnType; // Update return type to template parameter
+    }
     QualType AddrSpaceElemTy =
         AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
-    QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
-    BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
-        .addParam("Index", AST.UnsignedIntTy)
-        .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
-                     PH::Handle, PH::_0)
+
+    MMB.addParam("Index", AST.UnsignedIntTy)
+        .callBuiltin("__builtin_hlsl_resource_getpointer",
+                     AST.getPointerType(AddrSpaceElemTy), PH::Handle, PH::_0)
         .dereference(PH::LastStmt)
         .finalize();
 
     // Load with status
-    BuiltinTypeMethodBuilder(*this, Load, ReturnType, /*IsConst=*/false)
-        .addParam("Index", AST.UnsignedIntTy)
+    BuiltinTypeMethodBuilder MMB2(*this, Load, ReturnType);
+    if (ReturnType->isDependentType()) {
+      ReturnType = MMB2.addTemplateTypeParam("element_type");
+      MMB2.ReturnTy = ReturnType; // Update return type to template parameter
+    }
+
+    MMB2.addParam("Index", AST.UnsignedIntTy)
         .addParam("Status", AST.UnsignedIntTy,
                   HLSLParamModifierAttr::Keyword_out)
         .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnType,
@@ -1219,34 +1224,7 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   addLoadMethod("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
   addLoadMethod("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   addLoadMethod("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
-
-  // Templated Load method
-  IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
-  DeclarationName Load(&II);
-
-  BuiltinTypeMethodBuilder MMB(*this, Load, AST.UnsignedIntTy,
-                               /*IsConst=*/false);
-  QualType ReturnType = MMB.addTemplateTypeParam("element_type");
-  MMB.ReturnTy = ReturnType; // Update return type to template parameter
-  QualType AddrSpaceElemTy =
-      AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
-  QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
-  MMB.addParam("Index", AST.UnsignedIntTy)
-      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
-                   PH::_0)
-      .dereference(PH::LastStmt)
-      .finalize();
-
-  // Templated Load with status method
-  BuiltinTypeMethodBuilder MMB2(*this, Load, AST.UnsignedIntTy,
-                                /*IsConst=*/false);
-  QualType ReturnType2 = MMB2.addTemplateTypeParam("element_type");
-  MMB2.ReturnTy = ReturnType2; // Update return type to template parameter
-  MMB2.addParam("Index", AST.UnsignedIntTy)
-      .addParam("Status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
-      .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnType2,
-                   PH::Handle, PH::_0, PH::_1)
-      .finalize();
+  addLoadMethod("Load", AST.DependentTy); // Templated version
 
   return *this;
 }
@@ -1263,14 +1241,17 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Store(&II);
 
+    BuiltinTypeMethodBuilder MMB(*this, Store, AST.VoidTy);
+    if (ValueType->isDependentType()) {
+      ValueType = MMB.addTemplateTypeParam("element_type");
+    }
     QualType AddrSpaceElemTy =
         AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
-    QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
-    BuiltinTypeMethodBuilder(*this, Store, AST.VoidTy, /*IsConst=*/false)
-        .addParam("Index", AST.UnsignedIntTy)
+
+    MMB.addParam("Index", AST.UnsignedIntTy)
         .addParam("Value", ValueType)
-        .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy,
-                     PH::Handle, PH::_0)
+        .callBuiltin("__builtin_hlsl_resource_getpointer",
+                     AST.getPointerType(AddrSpaceElemTy), PH::Handle, PH::_0)
         .dereference(PH::LastStmt)
         .assign(PH::LastStmt, PH::_1)
         .finalize();
@@ -1280,23 +1261,7 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
   addStoreMethod("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
   addStoreMethod("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
   addStoreMethod("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
-
-  // Templated Store method
-  IdentifierInfo &II = AST.Idents.get("Store", tok::TokenKind::identifier);
-  DeclarationName Store(&II);
-
-  BuiltinTypeMethodBuilder Builder(*this, Store, AST.VoidTy, /*IsConst=*/false);
-  QualType ValueType = Builder.addTemplateTypeParam("element_type");
-  QualType AddrSpaceElemTy =
-      AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
-  QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
-  Builder.addParam("Index", AST.UnsignedIntTy)
-      .addParam("Value", ValueType)
-      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
-                   PH::_0)
-      .dereference(PH::LastStmt)
-      .assign(PH::LastStmt, PH::_1)
-      .finalize();
+  addStoreMethod("Store", AST.DependentTy); // Templated version
 
   return *this;
 }
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index ba6f059c6346b..af0fc75df6e89 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -3,11 +3,6 @@
 
 // NOTE: SPIRV codegen for resource methods is not yet implemented
 
-struct SmallStruct {
-  int a;
-  uint b;
-};
-
 ByteAddressBuffer Buf : register(t0);
 RWByteAddressBuffer RWBuf : register(u0);
 
@@ -17,45 +12,166 @@ RWByteAddressBuffer RWBuf : register(u0);
 // DXIL: @Buf = internal global %"class.hlsl::ByteAddressBuffer" poison
 // DXIL: @RWBuf = internal global %"class.hlsl::RWByteAddressBuffer" poison
 
-export uint TestLoad() {
-    uint u = Buf.Load(0);
-    uint2 v = Buf.Load2(0);
-    float f = Buf.Load<float>(4);
-    float4 g = Buf.Load<float4>(8);
-    SmallStruct U9 = Buf.Load<SmallStruct>(0);
-    return u;
+export float TestLoad() {
+    return Buf.Load(0) + RWBuf.Load4(4).w + Buf.Load<float>(20) + RWBuf.Load<float4>(24).w;
 }
 
-// CHECK: define {{.*}} i32 @TestLoad()()
+// CHECK: define {{.*}} float @TestLoad()()
 // CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int)(ptr {{.*}} @Buf, i32 noundef 0)
-// CHECK: ret i32
-
-export uint TestLoadWithStatus() {
-    uint s1, s2, s3;
-    uint u = Buf.Load(0, s1);
-    float f = Buf.Load<float>(4, s2);
-    SmallStruct U9 = Buf.Load<SmallStruct>(0, s3);
-    return u;
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 4)
+// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int)(ptr {{.*}} @Buf, i32 noundef 20)
+// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 24)
+// CHECK: add
+// CHECK: ret float
+
+// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VAL:.*]] = load i32, ptr %[[PTR]]
+// CHECK-NEXT: ret i32 %[[VAL]]
+
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]]
+// CHECK-NEXT: ret <4 x i32> %[[VEC]]
+
+// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
+// CHECK-NEXT: ret float %[[VAL]]
+
+// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VEC:.*]] = load <4 x float>, ptr %[[PTR]]
+// CHECK-NEXT: ret <4 x float> %[[VEC]]
+
+export float TestLoadWithStatus() {
+    uint s1, s2, s3, s4;
+    float ret = Buf.Load(0, s1) + RWBuf.Load4(4, s2).w + Buf.Load<float>(20, s3) + RWBuf.Load<float4>(24, s4).w;
+    ret += float(s1 + s2 + s3 + s4);
+    return ret;
 }
 
-// CHECK: define {{.*}} i32 @TestLoadWithStatus()()
+// CHECK: define {{.*}} float @TestLoadWithStatus()()
 // CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 0, ptr {{.*}} %tmp)
-// CHECK: ret i32
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 4, ptr {{.*}} %tmp1)
+// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 20, ptr {{.*}} %tmp4)
+// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 24, ptr {{.*}} %tmp7)
+// CHECK: add
+// CHECK: ret float
+
+// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 %[[INDEX]], i32 poison)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { i32, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { i32, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { <4 x i32>, i1 } @llvm.dx.resource.load.rawbuffer.v4i32.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]], i32 poison)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { <4 x i32>, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { <4 x i32>, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret <4 x i32> %[[VALUE]]
+
+// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 %[[INDEX]], i32 poison)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { float, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { float, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret float %[[VALUE]]
+
+// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { <4 x float>, i1 } @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]], i32 poison)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { <4 x float>, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { <4 x float>, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret <4 x float> %[[VALUE]]
 
 export void TestStore() {
-    uint u0;
-    float f0;
-    RWBuf.Store(0, u0);
-    RWBuf.Store<float>(0, f0);
-    SmallStruct TempStruct1;
-    RWBuf.Store<SmallStruct>(144, TempStruct1);
+    uint4 a;
+    float4 b;
+    RWBuf.Store(0, a.x);
+    RWBuf.Store4(4, a);
+    RWBuf.Store<float>(20, b.x);
+    RWBuf.Store<float4>(24, b);
     return;
 }
 
 // CHECK: define void @TestStore()()
 // CHECK: call void @hlsl::RWByteAddressBuffer::Store(unsigned int, unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 0, i32 noundef %{{.*}})
+// CHECK: call void @hlsl::RWByteAddressBuffer::Store4(unsigned int, unsigned int vector[4])(ptr {{.*}} @RWBuf, i32 noundef 4, <4 x i32> noundef %{{.*}})
+// CHECK: call void @void hlsl::RWByteAddressBuffer::Store<float>(unsigned int, float)(ptr {{.*}} @RWBuf, i32 noundef 20, float noundef {{.*}})
+// CHECK: call void @void hlsl::RWByteAddressBuffer::Store<float vector[4]>(unsigned int, float vector[4])(ptr {{.*}} @RWBuf, i32 noundef 24, <4 x float> noundef {{.*}})
 // CHECK: ret void
 
+// CHECK: define {{.*}} void @hlsl::RWByteAddressBuffer::Store(unsigned int, unsigned int)(ptr {{.*}} %this, i32 noundef %Index, i32 noundef %Value)
+// CHECK: %[[VALUE:.*]] = load i32, ptr %Value.addr
+// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: store i32 %[[VALUE]], ptr %[[PTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::RWByteAddressBuffer::Store4(unsigned int, unsigned int vector[4])(ptr {{.*}} %this, i32 noundef %Index, <4 x i32> noundef %Value)
+// CHECK: %[[VALUE:.*]] = load <4 x i32>, ptr %Value.addr
+// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: store <4 x i32> %[[VALUE]], ptr %[[PTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @void hlsl::RWByteAddressBuffer::Store<float>(unsigned int, float)(ptr {{.*}} %this, i32 noundef %Index, float noundef {{.*}} %Value)
+// CHECK: %[[VALUE:.*]] = load float, ptr %Value.addr
+// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: store float %[[VALUE]], ptr %[[PTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @void hlsl::RWByteAddressBuffer::Store<float vector[4]>(unsigned int, float vector[4])(ptr {{.*}} %this, i32 noundef %Index, <4 x float> noundef {{.*}} %Value)
+// CHECK: %[[VALUE:.*]] = load <4 x float>, ptr %Value.addr
+// CHECK-NEXT: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// DXIL-NEXT: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: store <4 x float> %[[VALUE]], ptr %[[PTR]]
+// CHECK-NEXT: ret void
+
 export uint TestGetDimensions() {
     uint dim1, dim2;
     Buf.GetDimensions(dim1);

>From a6aa781d5c59105a14afc544c338a60b7eef00ff Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Wed, 14 Jan 2026 19:37:38 -0800
Subject: [PATCH 08/10] reject array types, add array error tests

---
 clang/lib/Sema/SemaHLSL.cpp                   | 13 +++++-
 .../SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl | 44 +++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a705e5d9792f3..f13026737ade7 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3321,6 +3321,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
                "expected 2 parameters for Store method");
         ElementTy = FD->getParamDecl(1)->getType();
       }
+
+      // Reject array types
+      if (ElementTy->isArrayType())
+        return SemaRef.Diag(FD->getPointOfInstantiation(),
+                            diag::err_invalid_use_of_array_type);
     }
     auto ReturnType =
         SemaRef.Context.getAddrSpaceQualType(ElementTy, LangAS::hlsl_device);
@@ -3346,7 +3351,13 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     // ByteAddressBuffer uses the FunctionDecl return type instead of the
     // contained type
     if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
-      ReturnType = dyn_cast<FunctionDecl>(SemaRef.CurContext)->getReturnType();
+      FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
+      ReturnType = FD->getReturnType();
+
+      // Reject array types
+      if (ReturnType->isArrayType())
+        return SemaRef.Diag(FD->getPointOfInstantiation(),
+                            diag::err_invalid_use_of_array_type);
     }
     TheCall->setType(ReturnType);
 
diff --git a/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl
new file mode 100644
index 0000000000000..d7d48bf427ea7
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library -x hlsl -fsyntax-only -verify %s
+
+ByteAddressBuffer Buf : register(t0);
+RWByteAddressBuffer RWBuf : register(u0);
+
+int test_load_uint_array()[4] {
+  return Buf.Load<uint[4]>(0);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::ByteAddressBuffer::Load<unsigned int[4]>' requested here}}
+}
+
+float test_load_float_array()[2] {
+  return RWBuf.Load<float[2]>(0);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::RWByteAddressBuffer::Load<float[2]>' requested here}}
+}
+
+int test_load_uint_array_with_status()[4] {
+  uint s1;
+  return RWBuf.Load<uint[4]>(0, s1);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::RWByteAddressBuffer::Load<unsigned int[4]>' requested here}}
+}
+
+float test_load_float_array_with_status()[2] {
+  uint s1;
+  return Buf.Load<float[2]>(0, s1);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::ByteAddressBuffer::Load<float[2]>' requested here}}
+}
+
+void test_store_uint_array() {
+  uint UIntArray[4];
+  RWBuf.Store<uint[4]>(0, UIntArray);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::RWByteAddressBuffer::Store<unsigned int[4]>' requested here}}
+}
+
+void test_store_float_array() {
+  float FloatArray[2];
+  RWBuf.Store<float[2]>(0, FloatArray);
+  // expected-error at -1 {{an array type is not allowed here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'hlsl::RWByteAddressBuffer::Store<float[2]>' requested here}}
+}

>From 432b9f83da82885723a35fe9c45ead3397021bda Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Thu, 15 Jan 2026 19:00:44 -0800
Subject: [PATCH 09/10] address PR comments

---
 clang/lib/CodeGen/CGHLSLBuiltins.cpp            |  2 +-
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp   | 11 +++++------
 clang/lib/Sema/SemaHLSL.cpp                     | 12 ++++++++----
 clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl |  5 +++++
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 98708f23a35e6..cd0e057ce0658 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -432,7 +432,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 
     if (RT->getAttrs().RawBuffer) {
       Value *Offset = Builder.getInt32(0);
-      // Offset is poison for ByteAddressBuffer
+      // The offset parameter needs to be poison for ByteAddressBuffer
       if (RT->getContainedType()->isChar8Type())
         Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
       Args.push_back(Offset);
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index fea27d487526c..90465f0710fdb 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1192,12 +1192,13 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
 
     // Load without status
     BuiltinTypeMethodBuilder MMB(*this, Load, ReturnType);
+    QualType ElemTy = ReturnType;
     if (ReturnType->isDependentType()) {
-      ReturnType = MMB.addTemplateTypeParam("element_type");
-      MMB.ReturnTy = ReturnType; // Update return type to template parameter
+      ElemTy = MMB.addTemplateTypeParam("element_type");
+      MMB.ReturnTy = ElemTy; // Update return type to template parameter
     }
     QualType AddrSpaceElemTy =
-        AST.getAddrSpaceQualType(ReturnType, LangAS::hlsl_device);
+        AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
 
     MMB.addParam("Index", AST.UnsignedIntTy)
         .callBuiltin("__builtin_hlsl_resource_getpointer",
@@ -1236,15 +1237,13 @@ BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
   ASTContext &AST = SemaRef.getASTContext();
 
-  // Helper to add uint Store methods
   auto addStoreMethod = [&](StringRef MethodName, QualType ValueType) {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Store(&II);
 
     BuiltinTypeMethodBuilder MMB(*this, Store, AST.VoidTy);
-    if (ValueType->isDependentType()) {
+    if (ValueType->isDependentType())
       ValueType = MMB.addTemplateTypeParam("element_type");
-    }
     QualType AddrSpaceElemTy =
         AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f13026737ade7..a4d8548f8af31 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3306,11 +3306,12 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
                             SemaRef.getASTContext().UnsignedIntTy))
       return true;
 
+    // Figure out the return type of the intrinsic. For most resources it is the
+    // contained type. For ByteAddressBuffer it is determined by the type used
+    // on the FunctionDecl.
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ElementTy = ResourceTy->getContainedType();
-    // ByteAddressBuffer uses the FunctionDecl types instead of the contained
-    // type
     if (ResourceTy->getAttrs().RawBuffer && ElementTy->isChar8Type()) {
       // Load method uses return type
       FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
@@ -3327,6 +3328,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
         return SemaRef.Diag(FD->getPointOfInstantiation(),
                             diag::err_invalid_use_of_array_type);
     }
+
     auto ReturnType =
         SemaRef.Context.getAddrSpaceQualType(ElementTy, LangAS::hlsl_device);
     ReturnType = SemaRef.Context.getPointerType(ReturnType);
@@ -3345,11 +3347,12 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
         CheckModifiableLValue(&SemaRef, TheCall, 2))
       return true;
 
+    // Figure out the return type of the intrinsic. For most resources it is the
+    // contained type. For ByteAddressBuffer it is determined by the return
+    // value type.
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
-    // ByteAddressBuffer uses the FunctionDecl return type instead of the
-    // contained type
     if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
       FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
       ReturnType = FD->getReturnType();
@@ -3359,6 +3362,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
         return SemaRef.Diag(FD->getPointOfInstantiation(),
                             diag::err_invalid_use_of_array_type);
     }
+
     TheCall->setType(ReturnType);
 
     break;
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 212c8b0cbbb39..c4496f099ef86 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -156,6 +156,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int, out unsigned int)
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
@@ -183,6 +184,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int (unsigned int, out unsigned int), 2>'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
@@ -210,6 +212,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int (unsigned int, out unsigned int), 3>'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
@@ -237,6 +240,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int (unsigned int, out unsigned int), 4>'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
@@ -264,6 +268,7 @@ RESOURCE Buffer;
 // CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
 // CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'

>From ef8d7b2a520eb628284c63a5f5bded27fc21fe03 Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Tue, 20 Jan 2026 09:53:01 -0800
Subject: [PATCH 10/10] change parmvardecl declcontext

---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp  |  3 +--
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 ++----------
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 90465f0710fdb..4cc68f8c1f14f 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -522,8 +522,7 @@ void BuiltinTypeMethodBuilder::createDecl() {
   for (int I = 0, E = Params.size(); I != E; I++) {
     Param &MP = Params[I];
     ParmVarDecl *Parm = ParmVarDecl::Create(
-        AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
-        &MP.NameII, MP.Ty,
+        AST, Method, SourceLocation(), SourceLocation(), &MP.NameII, MP.Ty,
         AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
         nullptr);
     if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 348ac5e75af7c..2871f27a24658 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -6903,16 +6903,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   if (isa<ParmVarDecl>(D) && !ParentDependsOnArgs &&
       !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) {
     // Check if D belongs to a function template
-    auto *PVD = cast<ParmVarDecl>(D);
-    bool IsFromFunctionTemplate =
-        llvm::any_of(ParentDC->decls(), [PVD](Decl *D) {
-          if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
-            return llvm::is_contained(FTD->getTemplatedDecl()->parameters(),
-                                      PVD);
-          return false;
-        });
-
-    if (!IsFromFunctionTemplate)
+    auto *FD = dyn_cast<FunctionDecl>(ParentDC);
+    if (!FD || !FD->getDescribedFunctionTemplate())
       return D;
   }
   if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||



More information about the cfe-commits mailing list