[clang] [HLSL] Global resource arrays element access (PR #152454)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 27 09:08:43 PDT 2025
================
@@ -84,6 +85,111 @@ void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer,
RootSignatureValMD->addOperand(MDVals);
}
+// Find array variable declaration from nested array subscript AST nodes
+static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
+ const Expr *E = nullptr;
+ while (ASE != nullptr) {
+ E = ASE->getBase()->IgnoreImpCasts();
+ if (!E)
+ return nullptr;
+ ASE = dyn_cast<ArraySubscriptExpr>(E);
+ }
+ if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
+ return DRE->getDecl();
+ return nullptr;
+}
+
+// Get the total size of the array, or -1 if the array is unbounded.
+static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
+ Ty = Ty->getUnqualifiedDesugaredType();
+ assert(Ty->isArrayType() && "expected array type");
+ if (Ty->isIncompleteArrayType())
+ return -1;
+ return AST.getConstantArrayElementCount(cast<ConstantArrayType>(Ty));
+}
+
+// Find constructor decl for a specific resource record type and binding
+// (implicit vs. explicit). The constructor has 5 parameters.
+// For explicit binding the signature is:
+// void(unsigned, unsigned, int, unsigned, const char *).
+// For implicit binding the signature is:
+// void(unsigned, int, unsigned, unsigned, const char *).
+static CXXConstructorDecl *findResourceConstructorDecl(ASTContext &AST,
+ QualType ResTy,
+ bool ExplicitBinding) {
+ std::array<QualType, 5> ExpParmTypes = {
+ AST.UnsignedIntTy, AST.UnsignedIntTy, AST.UnsignedIntTy,
+ AST.UnsignedIntTy, AST.getPointerType(AST.CharTy.withConst())};
+ ExpParmTypes[ExplicitBinding ? 2 : 1] = AST.IntTy;
+
+ CXXRecordDecl *ResDecl = ResTy->getAsCXXRecordDecl();
+ for (auto *Ctor : ResDecl->ctors()) {
+ if (Ctor->getNumParams() != ExpParmTypes.size())
+ continue;
+ auto *ParmIt = Ctor->param_begin();
+ auto ExpTyIt = ExpParmTypes.begin();
+ for (; ParmIt != Ctor->param_end() && ExpTyIt != ExpParmTypes.end();
+ ++ParmIt, ++ExpTyIt) {
+ if ((*ParmIt)->getType() != *ExpTyIt)
+ break;
+ }
+ if (ParmIt == Ctor->param_end())
+ return Ctor;
+ }
+ llvm_unreachable("did not find constructor for resource class");
+}
+
+static Value *buildNameForResource(llvm::StringRef BaseName,
+ CodeGenModule &CGM) {
+ llvm::SmallString<64> GlobalName = {BaseName, ".str"};
+ return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
+ .getPointer();
+}
+
+static void createResourceCtorArgs(CodeGenModule &CGM, CXXConstructorDecl *CD,
+ llvm::Value *ThisPtr, llvm::Value *Range,
+ llvm::Value *Index, StringRef Name,
+ HLSLResourceBindingAttr *RBA,
+ HLSLVkBindingAttr *VkBinding,
+ CallArgList &Args) {
+ assert((VkBinding || RBA) && "at least one a binding attribute expected");
+
+ std::optional<uint32_t> RegisterSlot;
+ uint32_t SpaceNo = 0;
+ if (VkBinding) {
+ RegisterSlot = VkBinding->getBinding();
+ SpaceNo = VkBinding->getSet();
+ } else {
+ if (RBA->hasRegisterSlot())
+ RegisterSlot = RBA->getSlotNumber();
+ SpaceNo = RBA->getSpaceNumber();
+ }
+
+ ASTContext &AST = CD->getASTContext();
+ Value *NameStr = buildNameForResource(Name, CGM);
+ Value *Space = llvm::ConstantInt::get(CGM.IntTy, SpaceNo);
+
+ Args.add(RValue::get(ThisPtr), CD->getThisType());
+ if (RegisterSlot.has_value()) {
+ // explicit binding
+ auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RegisterSlot.value());
+ Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
+ Args.add(RValue::get(Space), AST.UnsignedIntTy);
+ Args.add(RValue::get(Range), AST.IntTy);
+ Args.add(RValue::get(Index), AST.UnsignedIntTy);
+
+ } else {
+ // implicit binding
+ auto *OrderID =
+ llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
----------------
llvm-beanz wrote:
Since the logic here is a bit unclear, maybe it warrants an assert to ensure that the surrounding code never changes the preconditions?
https://github.com/llvm/llvm-project/pull/152454
More information about the cfe-commits
mailing list