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

Kaitlin Peng via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 26 23:28:26 PST 2026


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

>From fd7f821efcbd70538b273d70ec614272b2b0fc15 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/12] 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 dcf07d659cb15..bc127ff91fe50 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5001,6 +5001,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 cfe5be354a494..c5f29fd2602df 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -536,6 +536,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 f74aabf08d2c7..5d5a1758590a5 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,
@@ -453,6 +459,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");
@@ -765,7 +787,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;
 }
@@ -1165,6 +1202,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 1d8e035cd9713..93ac08dc9fe83 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3348,7 +3348,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 619b12a278b10..4bfecaeaba341 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -152,9 +152,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 956e0c3dd3d27e8d5863da2f0bc9aa74d7f6888f 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/12] 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 c5f29fd2602df..955a24cd26d7e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -584,7 +584,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 5d5a1758590a5..0877b763c21e6 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1236,20 +1236,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;
 }
@@ -1279,19 +1288,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 93ac08dc9fe83..d97c9716aef48 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3355,10 +3355,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;
   }
@@ -3372,10 +3370,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;
   }
@@ -3386,8 +3382,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 4bfecaeaba341..8be0379a76029 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 \
@@ -152,12 +152,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 f7d3112a590b328682ffee18b86fd986b5d24e1b 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/12] 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 bc127ff91fe50..86f931fa42ad6 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5007,14 +5007,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 955a24cd26d7e..392d64a435926 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -489,6 +489,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});
@@ -521,6 +525,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);
     }
 
@@ -538,65 +545,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 0877b763c21e6..2a1ae0dc1bf01 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1209,25 +1209,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();
   };
 
@@ -1244,20 +1244,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;
@@ -1276,10 +1290,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();
   };
 
@@ -1293,11 +1307,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 d97c9716aef48..bf6d50333c99a 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3323,6 +3323,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);
@@ -3344,6 +3349,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;
@@ -3360,22 +3370,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 8be0379a76029..3a6d08b20e43c 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -155,7 +155,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'
@@ -163,25 +163,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>'
@@ -189,25 +189,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>'
@@ -215,25 +215,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>'
@@ -241,25 +241,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'
@@ -267,87 +267,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 b0c5ddd62278116559fbc72cd657c15597765ccd 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/12] 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 86f931fa42ad6..4bd15d842cad0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5001,12 +5001,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 857688ed8039d..10743a6a82a0e 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 392d64a435926..238b93ebe8ff0 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -489,10 +489,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});
@@ -543,21 +539,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 2a1ae0dc1bf01..d012beeb2fc17 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -647,7 +647,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;
@@ -1215,10 +1216,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
@@ -1244,25 +1249,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 bf6d50333c99a..ebc3806121ae6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3323,11 +3323,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);
@@ -3349,7 +3349,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();
@@ -3358,18 +3358,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 671cee734bab16977edf0f6c570428b93048077a 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/12] 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 d012beeb2fc17..cc9e458cdf5de 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -647,8 +647,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;
@@ -1284,11 +1283,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();
   };
 
@@ -1303,10 +1307,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 2bcca4854b136..c6411ccf77075 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-SUBSCRIPT-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-SUBSCRIPT-UAV-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-LOAD-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-APPEND-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-CONSUME-NEXT: CallExpr
 // 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 eb53ad5e9fd0e..c2144d230887b 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-UAV-NEXT: CallExpr
 // 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: CStyleCastExpr {{.*}} 'hlsl_device element_type *'
 // CHECK-NEXT: CallExpr
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}}  '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'

>From d88f2e9e13ca69fd544286aca494f70f214ce4ee 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/12] 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 4bd15d842cad0..dcf07d659cb15 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5001,12 +5001,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 10743a6a82a0e..857688ed8039d 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 238b93ebe8ff0..532fe0673423e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -539,37 +539,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 ebc3806121ae6..805008f1670a2 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3322,14 +3322,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);
@@ -3349,8 +3357,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();
     }
@@ -3358,18 +3366,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 3a6d08b20e43c..aee1e0d8cda34 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -158,9 +158,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'
@@ -184,9 +185,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'
@@ -210,9 +212,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'
@@ -236,9 +239,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'
@@ -262,9 +266,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'
@@ -289,9 +294,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'
@@ -302,9 +309,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'
@@ -315,9 +324,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'
@@ -328,9 +339,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'
@@ -341,9 +354,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 b2f8d7007255925a09ded347be5ecce66b3f8785 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/12] 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 cc9e458cdf5de..2e6798efcf0ae 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(); }
@@ -1209,25 +1206,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,
@@ -1239,34 +1244,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;
 }
@@ -1283,14 +1261,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();
@@ -1300,23 +1281,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 7a83b89117d26865afffb32f92e2384ae6df3281 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/12] 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 805008f1670a2..0a4cc563526eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3335,6 +3335,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);
@@ -3360,7 +3365,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 c422fa529e7a795bd706df2f896164b2f604b677 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/12] 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 532fe0673423e..981f67a042598 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -521,7 +521,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 2e6798efcf0ae..27a5428d8bd26 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1212,12 +1212,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",
@@ -1256,15 +1257,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 0a4cc563526eb..360d8c218ec58 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3320,11 +3320,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);
@@ -3341,6 +3342,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);
@@ -3359,11 +3361,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();
@@ -3373,6 +3376,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 aee1e0d8cda34..a762e181ee221 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -166,6 +166,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'
@@ -193,6 +194,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'
@@ -220,6 +222,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'
@@ -247,6 +250,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'
@@ -274,6 +278,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 b5bc6c66538e178014373f3a7a238e39e5bc96ff 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/12] 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 27a5428d8bd26..a30a39c7ddb82 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -526,8 +526,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) ||

>From fb1d8eb605659307b3b4a7e63d058d99e09dd1ab Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Tue, 20 Jan 2026 16:25:28 -0800
Subject: [PATCH 11/12] address Justin

---
 clang/include/clang/AST/TypeBase.h            |   2 +
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |   4 +-
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 142 +++++++++---------
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   |   6 +-
 clang/lib/Sema/SemaHLSL.cpp                   |   4 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   8 +-
 6 files changed, 81 insertions(+), 85 deletions(-)

diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index 279b75f14d7b8..2efca8a69ded1 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -6745,6 +6745,8 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
   QualType getContainedType() const { return ContainedType; }
   bool hasContainedType() const { return !ContainedType.isNull(); }
   const Attributes &getAttrs() const { return Attrs; }
+  bool isRaw() const { return Attrs.RawBuffer; }
+  bool isStructured() const { return !ContainedType->isChar8Type(); }
 
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 981f67a042598..ee1714f568689 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -519,10 +519,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Args.push_back(HandleOp);
     Args.push_back(IndexOp);
 
-    if (RT->getAttrs().RawBuffer) {
+    if (RT->isRaw()) {
       Value *Offset = Builder.getInt32(0);
       // The offset parameter needs to be poison for ByteAddressBuffer
-      if (RT->getContainedType()->isChar8Type())
+      if (!RT->isStructured())
         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 a30a39c7ddb82..e957566b52e45 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -468,7 +468,7 @@ QualType BuiltinTypeMethodBuilder::addTemplateTypeParam(StringRef Name) {
       /* Typename */ true,
       /* ParameterPack */ false,
       /* HasTypeConstraint*/ false);
-  TemplateParamDecls.emplace_back(Decl);
+  TemplateParamDecls.push_back(Decl);
 
   return QualType(Decl->getTypeForDecl(), 0);
 }
@@ -1178,9 +1178,11 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
   DeclarationName Subscript =
       AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
 
-  addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true);
+  addHandleAccessFunction(Subscript, getHandleElementType(), /*IsConst=*/true,
+                          /*IsRef=*/true);
   if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
-    addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true);
+    addHandleAccessFunction(Subscript, getHandleElementType(),
+                            /*IsConst=*/false, /*IsRef=*/true);
 
   return *this;
 }
@@ -1192,8 +1194,9 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
   IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
   DeclarationName Load(&II);
   // TODO: We also need versions with status for CheckAccessFullyMapped.
-  addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false);
-  addLoadWithStatusFunction(Load, /*IsConst=*/false);
+  addHandleAccessFunction(Load, getHandleElementType(), /*IsConst=*/false,
+                          /*IsRef=*/false);
+  addLoadWithStatusFunction(Load, getHandleElementType(), /*IsConst=*/false);
 
   return *this;
 }
@@ -1202,50 +1205,22 @@ BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
   assert(!Record->isCompleteDefinition() && "record is already complete");
 
-  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
   ASTContext &AST = SemaRef.getASTContext();
 
-  auto addLoadMethod = [&](StringRef MethodName, QualType ReturnType) {
+  auto AddLoads = [&](StringRef MethodName, QualType ReturnType) {
     IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
     DeclarationName Load(&II);
 
-    // Load without status
-    BuiltinTypeMethodBuilder MMB(*this, Load, ReturnType);
-    QualType ElemTy = ReturnType;
-    if (ReturnType->isDependentType()) {
-      ElemTy = MMB.addTemplateTypeParam("element_type");
-      MMB.ReturnTy = ElemTy; // Update return type to template parameter
-    }
-    QualType AddrSpaceElemTy =
-        AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
-
-    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 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,
-                     PH::Handle, PH::_0, PH::_1)
-        .finalize();
+    addHandleAccessFunction(Load, ReturnType, /*IsConst=*/false,
+                            /*IsRef=*/false);
+    addLoadWithStatusFunction(Load, ReturnType, /*IsConst=*/false);
   };
 
-  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));
-  addLoadMethod("Load", AST.DependentTy); // Templated version
-
+  AddLoads("Load", AST.UnsignedIntTy);
+  AddLoads("Load2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
+  AddLoads("Load3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
+  AddLoads("Load4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
+  AddLoads("Load", AST.DependentTy); // Templated version
   return *this;
 }
 
@@ -1253,33 +1228,20 @@ BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addByteAddressBufferStoreMethods() {
   assert(!Record->isCompleteDefinition() && "record is already complete");
 
-  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
   ASTContext &AST = SemaRef.getASTContext();
 
-  auto addStoreMethod = [&](StringRef MethodName, QualType ValueType) {
+  auto AddStore = [&](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())
-      ValueType = MMB.addTemplateTypeParam("element_type");
-    QualType AddrSpaceElemTy =
-        AST.getAddrSpaceQualType(ValueType, LangAS::hlsl_device);
-
-    MMB.addParam("Index", AST.UnsignedIntTy)
-        .addParam("Value", ValueType)
-        .callBuiltin("__builtin_hlsl_resource_getpointer",
-                     AST.getPointerType(AddrSpaceElemTy), PH::Handle, PH::_0)
-        .dereference(PH::LastStmt)
-        .assign(PH::LastStmt, PH::_1)
-        .finalize();
+    addStoreFunction(Store, ValueType, /*IsConst=*/false);
   };
 
-  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));
-  addStoreMethod("Store", AST.DependentTy); // Templated version
+  AddStore("Store", AST.UnsignedIntTy);
+  AddStore("Store2", AST.getExtVectorType(AST.UnsignedIntTy, 2));
+  AddStore("Store3", AST.getExtVectorType(AST.UnsignedIntTy, 3));
+  AddStore("Store4", AST.getExtVectorType(AST.UnsignedIntTy, 4));
+  AddStore("Store", AST.DependentTy); // Templated version
 
   return *this;
 }
@@ -1372,30 +1334,38 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() {
       .finalize();
 }
 
-BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addLoadWithStatusFunction(DeclarationName &Name,
-                                                  bool IsConst) {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadWithStatusFunction(
+    DeclarationName &Name, QualType ReturnTy, bool IsConst) {
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
 
-  QualType ReturnTy = getHandleElementType();
-  return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
-      .addParam("Index", AST.UnsignedIntTy)
+  BuiltinTypeMethodBuilder MMB(*this, Name, ReturnTy, IsConst);
+
+  if (ReturnTy == AST.DependentTy) {
+    ReturnTy = MMB.addTemplateTypeParam("element_type");
+    MMB.ReturnTy = ReturnTy;
+  }
+
+  return MMB.addParam("Index", AST.UnsignedIntTy)
       .addParam("Status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out)
       .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy,
                    PH::Handle, PH::_0, PH::_1)
       .finalize();
 }
 
-BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
-                                                bool IsConst, bool IsRef) {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
+    DeclarationName &Name, QualType ElemTy, bool IsConst, bool IsRef) {
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
 
-  QualType ElemTy = getHandleElementType();
+  // The empty QualType is a placeholder. The actual return type is set below.
+  BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
+
+  if (ElemTy == AST.DependentTy) {
+    ElemTy = MMB.addTemplateTypeParam("element_type");
+  }
   QualType AddrSpaceElemTy =
       AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
   QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
@@ -1411,12 +1381,36 @@ BuiltinTypeDeclBuilder::addHandleAccessFunction(DeclarationName &Name,
     if (IsConst)
       ReturnTy.addConst();
   }
+  MMB.ReturnTy = ReturnTy;
+
+  return MMB.addParam("Index", AST.UnsignedIntTy)
+      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
+                   PH::_0)
+      .dereference(PH::LastStmt)
+      .finalize();
+}
+
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addStoreFunction(DeclarationName &Name,
+                                         QualType ValueTy, bool IsConst) {
+  assert(!Record->isCompleteDefinition() && "record is already complete");
+  ASTContext &AST = SemaRef.getASTContext();
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+
+  BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
+
+  if (ValueTy == AST.DependentTy)
+    ValueTy = MMB.addTemplateTypeParam("element_type");
+  QualType AddrSpaceElemTy =
+      AST.getAddrSpaceQualType(ValueTy, LangAS::hlsl_device);
+  QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
 
-  return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
-      .addParam("Index", AST.UnsignedIntTy)
+  return MMB.addParam("Index", AST.UnsignedIntTy)
+      .addParam("Value", ValueTy)
       .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
                    PH::_0)
       .dereference(PH::LastStmt)
+      .assign(PH::LastStmt, PH::_1)
       .finalize();
 }
 
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 8309ba990fda0..76cded6a6e33c 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -92,9 +92,13 @@ class BuiltinTypeDeclBuilder {
   BuiltinTypeDeclBuilder &addIncrementCounterMethod();
   BuiltinTypeDeclBuilder &addDecrementCounterMethod();
   BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
-                                                  bool IsConst, bool IsRef);
+                                                  QualType ElemTy, bool IsConst,
+                                                  bool IsRef);
   BuiltinTypeDeclBuilder &addLoadWithStatusFunction(DeclarationName &Name,
+                                                    QualType ReturnTy,
                                                     bool IsConst);
+  BuiltinTypeDeclBuilder &addStoreFunction(DeclarationName &Name,
+                                           QualType ValueType, bool IsConst);
   BuiltinTypeDeclBuilder &addAppendMethod();
   BuiltinTypeDeclBuilder &addConsumeMethod();
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 360d8c218ec58..f4961c3e9e55a 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3326,7 +3326,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ElementTy = ResourceTy->getContainedType();
-    if (ResourceTy->getAttrs().RawBuffer && ElementTy->isChar8Type()) {
+    if (ResourceTy->isRaw() && !ResourceTy->isStructured()) {
       // Load method uses return type
       FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
       ElementTy = FD->getReturnType();
@@ -3367,7 +3367,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
     auto *ResourceTy =
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
-    if (ResourceTy->getAttrs().RawBuffer && ReturnType->isChar8Type()) {
+    if (ResourceTy->isRaw() && !ResourceTy->isStructured()) {
       FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
       ReturnType = FD->getReturnType();
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2871f27a24658..e74c41517ecbf 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -6901,12 +6901,8 @@ 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()) {
-    // Check if D belongs to a function template
-    auto *FD = dyn_cast<FunctionDecl>(ParentDC);
-    if (!FD || !FD->getDescribedFunctionTemplate())
-      return D;
-  }
+      !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType())
+    return D;
   if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
       isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
       (ParentDependsOnArgs && (ParentDC->isFunctionOrMethod() ||

>From 42cb37f4068737b4f4cfc01a49682b682c9b4d3a Mon Sep 17 00:00:00 2001
From: kmpeng <kaitlinpeng at microsoft.com>
Date: Mon, 26 Jan 2026 23:01:28 -0800
Subject: [PATCH 12/12] create resource_getpointer_typed builtin for templated
 load/stores

---
 clang/include/clang/Basic/Builtins.td         |  6 +++
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |  3 +-
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 50 +++++++++++++------
 clang/lib/Sema/SemaHLSL.cpp                   | 46 +++++++++--------
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl |  6 ++-
 .../SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl |  4 +-
 6 files changed, 75 insertions(+), 40 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index dcf07d659cb15..90d0483354e8e 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4995,6 +4995,12 @@ def HLSLResourceGetPointer : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLResourceGetPointerTyped : Builtin {
+  let Spellings = ["__builtin_hlsl_resource_getpointer_typed"];
+  let Attributes = [NoThrow];
+  let Prototype = "void(...)";
+}
+
 def HLSLResourceLoadWithStatus : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_resource_load_with_status"];
   let Attributes = [NoThrow];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index ee1714f568689..cb633baec5380 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -484,7 +484,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
                                          "hlsl.AddUint64");
     return Result;
   }
-  case Builtin::BI__builtin_hlsl_resource_getpointer: {
+  case Builtin::BI__builtin_hlsl_resource_getpointer:
+  case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
     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 e957566b52e45..b1f06ed2fda7a 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -178,6 +178,7 @@ struct BuiltinTypeMethodBuilder {
   Expr *convertPlaceholder(PlaceHolder PH);
   Expr *convertPlaceholder(LocalVar &Var);
   Expr *convertPlaceholder(Expr *E) { return E; }
+  Expr *convertPlaceholder(QualType Ty);
 
 public:
   friend BuiltinTypeDeclBuilder;
@@ -425,6 +426,16 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(LocalVar &Var) {
       VD->getType(), VK_LValue);
 }
 
+// Converts a QualType to an Expr that carries type information through template
+// instantiation. Creates `Ty*()`, a value-initialized null pointer of type Ty*.
+Expr *BuiltinTypeMethodBuilder::convertPlaceholder(QualType Ty) {
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  QualType PtrTy = AST.getPointerType(Ty);
+  return CXXUnresolvedConstructExpr::Create(
+      AST, PtrTy, AST.getTrivialTypeSourceInfo(PtrTy), SourceLocation(), {},
+      SourceLocation(), false);
+}
+
 BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
                                                    StringRef NameStr,
                                                    QualType ReturnTy,
@@ -1359,13 +1370,13 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  bool IsTemplated = (ElemTy == AST.DependentTy);
 
   // The empty QualType is a placeholder. The actual return type is set below.
   BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
 
-  if (ElemTy == AST.DependentTy) {
+  if (IsTemplated)
     ElemTy = MMB.addTemplateTypeParam("element_type");
-  }
   QualType AddrSpaceElemTy =
       AST.getAddrSpaceQualType(ElemTy, LangAS::hlsl_device);
   QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
@@ -1383,11 +1394,16 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
   }
   MMB.ReturnTy = ReturnTy;
 
-  return MMB.addParam("Index", AST.UnsignedIntTy)
-      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
-                   PH::_0)
-      .dereference(PH::LastStmt)
-      .finalize();
+  MMB.addParam("Index", AST.UnsignedIntTy);
+
+  if (IsTemplated)
+    MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
+                    PH::Handle, PH::_0, ElemTy);
+  else
+    MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
+                    PH::_0);
+
+  return MMB.dereference(PH::LastStmt).finalize();
 }
 
 BuiltinTypeDeclBuilder &
@@ -1396,22 +1412,26 @@ BuiltinTypeDeclBuilder::addStoreFunction(DeclarationName &Name,
   assert(!Record->isCompleteDefinition() && "record is already complete");
   ASTContext &AST = SemaRef.getASTContext();
   using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  bool IsTemplated = (ValueTy == AST.DependentTy);
 
   BuiltinTypeMethodBuilder MMB(*this, Name, AST.VoidTy, IsConst);
 
-  if (ValueTy == AST.DependentTy)
+  if (IsTemplated)
     ValueTy = MMB.addTemplateTypeParam("element_type");
   QualType AddrSpaceElemTy =
       AST.getAddrSpaceQualType(ValueTy, LangAS::hlsl_device);
   QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
 
-  return MMB.addParam("Index", AST.UnsignedIntTy)
-      .addParam("Value", ValueTy)
-      .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
-                   PH::_0)
-      .dereference(PH::LastStmt)
-      .assign(PH::LastStmt, PH::_1)
-      .finalize();
+  MMB.addParam("Index", AST.UnsignedIntTy).addParam("Value", ValueTy);
+
+  if (IsTemplated)
+    MMB.callBuiltin("__builtin_hlsl_resource_getpointer_typed", ElemPtrTy,
+                    PH::Handle, PH::_0, ValueTy);
+  else
+    MMB.callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
+                    PH::_0);
+
+  return MMB.dereference(PH::LastStmt).assign(PH::LastStmt, PH::_1).finalize();
 }
 
 BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addAppendMethod() {
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f4961c3e9e55a..a09ff2eb99aa6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3320,28 +3320,34 @@ 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();
-    if (ResourceTy->isRaw() && !ResourceTy->isStructured()) {
-      // 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();
-      }
+    QualType ContainedTy = ResourceTy->getContainedType();
+    auto ReturnType =
+        SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);
+    ReturnType = SemaRef.Context.getPointerType(ReturnType);
+    TheCall->setType(ReturnType);
+    TheCall->setValueKind(VK_LValue);
 
-      // Reject array types
-      if (ElementTy->isArrayType())
-        return SemaRef.Diag(FD->getPointOfInstantiation(),
-                            diag::err_invalid_use_of_array_type);
-    }
+    break;
+  }
+  case Builtin::BI__builtin_hlsl_resource_getpointer_typed: {
+    if (SemaRef.checkArgCount(TheCall, 3) ||
+        CheckResourceHandle(&SemaRef, TheCall, 0) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),
+                            SemaRef.getASTContext().UnsignedIntTy))
+      return true;
+
+    QualType ElementTy = TheCall->getArg(2)->getType();
+    assert(ElementTy->isPointerType() &&
+           "expected pointer type for second argument");
+    ElementTy = ElementTy->getPointeeType();
+
+    // Reject array types
+    if (ElementTy->isArrayType())
+      return SemaRef.Diag(
+          cast<FunctionDecl>(SemaRef.CurContext)->getPointOfInstantiation(),
+          diag::err_invalid_use_of_array_type);
 
     auto ReturnType =
         SemaRef.Context.getAddrSpaceQualType(ElementTy, LangAS::hlsl_device);
@@ -3368,7 +3374,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
         TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();
     QualType ReturnType = ResourceTy->getContainedType();
     if (ResourceTy->isRaw() && !ResourceTy->isStructured()) {
-      FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.CurContext);
+      FunctionDecl *FD = cast<FunctionDecl>(SemaRef.CurContext);
       ReturnType = FD->getReturnType();
 
       // Reject array types
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index a762e181ee221..317c895b9f840 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -273,10 +273,11 @@ RESOURCE Buffer;
 // 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_resource_getpointer' 'void (...) noexcept'
+// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' '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'
+// CHECK-LOAD-NEXT: CXXUnresolvedConstructExpr {{.*}} 'element_type *' 'element_type *'
 // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)
@@ -363,10 +364,11 @@ RESOURCE Buffer;
 // 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_getpointer' 'void (...) noexcept'
+// CHECK-STORE-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' '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'
+// CHECK-STORE-NEXT: CXXUnresolvedConstructExpr {{.*}} 'element_type *' 'element_type *'
 // CHECK-STORE-NEXT: DeclRefExpr {{.*}} 'element_type' ParmVar {{.*}} 'Value' 'element_type'
 // CHECK-STORE-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
diff --git a/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl
index d7d48bf427ea7..bd5759ddc0f04 100644
--- a/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffers.hlsl
@@ -3,7 +3,7 @@
 ByteAddressBuffer Buf : register(t0);
 RWByteAddressBuffer RWBuf : register(u0);
 
-int test_load_uint_array()[4] {
+uint 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}}
@@ -15,7 +15,7 @@ float test_load_float_array()[2] {
   // 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 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}}



More information about the cfe-commits mailing list