diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "CGCXXABI.h" +#include "CGHLSLRuntime.h" #include "CGObjCRuntime.h" #include "CGOpenMPRuntime.h" #include "CodeGenFunction.h" @@ -977,6 +978,9 @@ EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit); } + if (getLangOpts().HLSL) + CGM.getHLSLRuntime().annotateHLSLResource(D, Addr); + FinishFunction(); } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -15,7 +15,16 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H +#include "clang/Basic/HLSLRuntime.h" + +namespace llvm { +class Value; +class GlobalVariable; +} // namespace llvm namespace clang { +class CallExpr; +class Type; +class VarDecl; namespace CodeGen { @@ -24,11 +33,15 @@ class CGHLSLRuntime { protected: CodeGenModule &CGM; + uint32_t ResourceCounters[static_cast( + hlsl::ResourceClass::NumClasses)] = {0}; public: CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} virtual ~CGHLSLRuntime() {} + void annotateHLSLResource(const VarDecl *D, llvm::GlobalVariable *GV); + void finishCodeGen(); }; diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -20,6 +20,7 @@ using namespace clang; using namespace CodeGen; +using namespace hlsl; using namespace llvm; namespace { @@ -50,3 +51,38 @@ llvm::Module &M = CGM.getModule(); addDxilValVersion(TargetOpts.DxilValidatorVersion, M); } + +void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { + const Type *Ty = D->getType()->getPointeeOrArrayElementType(); + if (!Ty) + return; + const auto *RD = Ty->getAsCXXRecordDecl(); + if (!RD) + return; + const auto *Attr = RD->getAttr(); + if (!Attr) + return; + + HLSLResourceAttr::ResourceClass RC = Attr->getResourceType(); + uint32_t Counter = ResourceCounters[static_cast(RC)]++; + + NamedMDNode *ResourceMD = nullptr; + switch (RC) { + case HLSLResourceAttr::ResourceClass::UAV: + ResourceMD = CGM.getModule().getOrInsertNamedMetadata("hlsl.uavs"); + break; + default: + assert(false && "Unsupported buffer type!"); + return; + } + + assert(ResourceMD != nullptr && + "ResourceMD must have been set by the switch above."); + + auto &Ctx = CGM.getModule().getContext(); + IRBuilder<> B(Ctx); + QualType QT(Ty, 0); + ResourceMD->addOperand(MDNode::get( + Ctx, {ValueAsMetadata::get(GV), MDString::get(Ctx, QT.getAsString()), + ConstantAsMetadata::get(B.getInt32(Counter))})); +} diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +RWBuffer Buffer1; +RWBuffer > BufferArray[4]; + +[numthreads(1,1,1)] +void main() { +} + +// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]]} +// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 0} +// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 1}