================ @@ -115,48 +83,176 @@ llvm::Triple::ArchType CGHLSLRuntime::getArch() { return CGM.getTarget().getTriple().getArch(); } -void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) { - if (D->getStorageClass() == SC_Static) { - // For static inside cbuffer, take as global static. - // Don't add to cbuffer. - CGM.EmitGlobal(D); - return; - } +// Returns true if the type is an HLSL resource class +static bool isResourceRecordType(const clang::Type *Ty) { + return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr; +} - auto *GV = cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(D)); - GV->setExternallyInitialized(true); - // Add debug info for constVal. - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::DebugInfoKind::LimitedDebugInfo) - DI->EmitGlobalVariable(cast<GlobalVariable>(GV), D); - - // FIXME: support packoffset. - // See https://github.com/llvm/llvm-project/issues/57914. - uint32_t Offset = 0; - bool HasUserOffset = false; - - unsigned LowerBound = HasUserOffset ? Offset : UINT_MAX; - CB.Constants.emplace_back(std::make_pair(GV, LowerBound)); +// Returns true if the type is an HLSL resource class or an array of them +static bool isResourceRecordTypeOrArrayOf(const clang::Type *Ty) { + while (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) + Ty = CAT->getArrayElementTypeNoTypeQual(); + return isResourceRecordType(Ty); } -void CGHLSLRuntime::addBufferDecls(const DeclContext *DC, Buffer &CB) { - for (Decl *it : DC->decls()) { - if (auto *ConstDecl = dyn_cast<VarDecl>(it)) { - addConstant(ConstDecl, CB); - } else if (isa<CXXRecordDecl, EmptyDecl>(it)) { +// Emits constant global variables for buffer constants declarations +// and creates metadata linking the constant globals with the buffer global. +void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl, + llvm::GlobalVariable *BufGV) { + LLVMContext &Ctx = CGM.getLLVMContext(); + + // get the layout struct from constant buffer target type + llvm::Type *BufType = BufGV->getValueType(); + assert(isa<llvm::TargetExtType>(BufType) && + "expected target type for HLSL buffer resource"); + llvm::Type *BufLayoutType = + cast<llvm::TargetExtType>(BufType)->getTypeParameter(0); + assert(isa<llvm::TargetExtType>(BufLayoutType) && + "expected target type for buffer layout struct"); + llvm::StructType *LayoutStruct = cast<llvm::StructType>( + cast<llvm::TargetExtType>(BufLayoutType)->getTypeParameter(0)); + + // Start metadata list associating the buffer global variable with its + // constatns + SmallVector<llvm::Metadata *> BufGlobals; + BufGlobals.push_back(ValueAsMetadata::get(BufGV)); + + const auto *ElemIt = LayoutStruct->element_begin(); + for (Decl *D : BufDecl->decls()) { + if (isa<CXXRecordDecl, EmptyDecl>(D)) // Nothing to do for this declaration. - } else if (isa<FunctionDecl>(it)) { - // A function within an cbuffer is effectively a top-level function, - // as it only refers to globally scoped declarations. - CGM.EmitTopLevelDecl(it); + continue; + if (isa<FunctionDecl>(D)) { + // A function within an cbuffer is effectively a top-level function. + CGM.EmitTopLevelDecl(D); + continue; + } + VarDecl *VD = dyn_cast<VarDecl>(D); + if (!VD) + continue; + + QualType VDTy = VD->getType(); + if (VDTy.getAddressSpace() != LangAS::hlsl_constant) { + if (VD->getStorageClass() == SC_Static || + VDTy.getAddressSpace() == LangAS::hlsl_groupshared || + isResourceRecordTypeOrArrayOf(VDTy.getTypePtr())) { + // Emit static and groupshared variables and resource classes inside + // cbuffer as regular globals + CGM.EmitGlobal(VD); + } + // Anything else that is not in the hlsl_constant address space must be + // an empty struct or a zero-sized array and can be ignored + continue; + } + + assert(ElemIt != LayoutStruct->element_end() && + "number of elements in layout struct does not match"); + llvm::Type *LayoutType = *ElemIt++; + + // there might be resources inside the used defined structs + if (VDTy->isStructureType() && VDTy->isHLSLIntangibleType()) + // FIXME: handle resources in cbuffer structs + llvm_unreachable("resources in cbuffer are not supported yet"); ---------------- bogner wrote:
`report_fatal_error` might be better here - I imagine something will crash later anyway if we get here. https://github.com/llvm/llvm-project/pull/124886 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits