[llvm-branch-commits] [clang] [HLSL] Global resource arrays element access (PR #152454)
Alex Sepkowski via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Aug 7 18:19:53 PDT 2025
================
@@ -84,6 +84,124 @@ void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer,
RootSignatureValMD->addOperand(MDVals);
}
+// If the specified expr is a simple decay from an array to pointer,
+// return the array subexpression. Otherwise, return nullptr.
+static const Expr *getSubExprFromArrayDecayOperand(const Expr *E) {
+ const auto *CE = dyn_cast<CastExpr>(E);
+ if (!CE || CE->getCastKind() != CK_ArrayToPointerDecay)
+ return nullptr;
+ return CE->getSubExpr();
+}
+
+// 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 = getSubExprFromArrayDecayOperand(ASE->getBase());
+ 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(const clang::Type *Ty) {
+ assert(Ty->isArrayType() && "expected array type");
+ if (Ty->isIncompleteArrayType())
+ return -1;
+ int Size = 1;
+ while (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
+ Size *= CAT->getSExtSize();
+ Ty = CAT->getArrayElementTypeNoTypeQual();
+ }
+ return Size;
+}
+
+// Find constructor decl for a specific resource record type and binding
+// (implicit vs. explicit). The constructor has 6 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) {
+ SmallVector<QualType> 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;
+ ParmVarDecl **ParmIt = Ctor->param_begin();
+ QualType *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) {
+ std::string Str(BaseName);
+ std::string GlobalName(Str + ".str");
+ return CGM.GetAddrOfConstantCString(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) {
+ 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()) {
----------------
alsepkow wrote:
Ah, maybe this is where the order would matter?
Do we want the argument ordering to match for both the explicit/implicit case? Right now they are different and that would explain the difference in ordering in the test cases that I commented on.
https://github.com/llvm/llvm-project/pull/152454
More information about the llvm-branch-commits
mailing list