[clang] [llvm] [HLSL] Add list of exported functions as named metadata node 'dx.exports` (PR #102275)

Helena Kotas via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 6 23:36:35 PDT 2024


https://github.com/hekota created https://github.com/llvm/llvm-project/pull/102275

Adds list of exported functions as named metadata node 'dx.exports`.

During CodeGen each exported functions is marked with an "hlsl.export" attribute. Based on these attributes the DXILTranslateMetadata pass will create a list of all export functions and will add it to the module under `dx.exports`.

This information will be then used by DXILFinalizeLinkage pass (coming soon) to determine which functions should have internal linkage in the final DXIL code. After this pass is completed the `dx.exports` metadata node will be removed.



>From 340834e9c1ea12c8de4ee9f5a6b7c0191e96f489 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 6 Aug 2024 23:19:20 -0700
Subject: [PATCH] [HLSL] Add list of exported functions as named metadata node
 'dx.exports'

This information will be used by DXILFinalizeLinkage pass (coming soon)
to determine which functions should have internal linkage in the final
DXIL code. After this pass is completed the `dx.exports` metadata node
will be removed.
---
 clang/lib/CodeGen/CGHLSLRuntime.cpp           |  8 ++++++++
 clang/lib/CodeGen/CGHLSLRuntime.h             |  2 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         | 10 +++++++---
 clang/test/CodeGenHLSL/export.hlsl            | 18 +++++++++++++----
 llvm/lib/Target/DirectX/DXILMetadata.cpp      | 20 +++++++++++++++++++
 llvm/lib/Target/DirectX/DXILMetadata.h        |  1 +
 .../Target/DirectX/DXILTranslateMetadata.cpp  |  1 +
 7 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index a2c3e76f77b7c..5e59b0f00ebd6 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -412,6 +412,14 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
   B.CreateRetVoid();
 }
 
+void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
+                                              llvm::Function *Fn) {
+  if (FD->isInExportDeclContext()) {
+    const StringRef ExportAttrKindStr = "hlsl.export";
+    Fn->addFnAttr(ExportAttrKindStr);
+  }
+}
+
 static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
                             bool CtorOrDtor) {
   const auto *GV =
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 527e73a0e21fc..590d388c456c4 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -124,7 +124,7 @@ class CGHLSLRuntime {
   void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);
 
   void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);
-  void setHLSLFunctionAttributes(llvm::Function *, const FunctionDecl *);
+  void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
 
 private:
   void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index af201554898f3..9e9dd6b9c8e17 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1223,9 +1223,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   if (getLangOpts().OpenMP && CurCodeDecl)
     CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
 
-  // Handle emitting HLSL entry functions.
-  if (D && D->hasAttr<HLSLShaderAttr>())
-    CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
+  if (FD && getLangOpts().HLSL) {
+    // Handle emitting HLSL entry functions.
+    if (FD->hasAttr<HLSLShaderAttr>()) {
+      CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
+    }
+    CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
+  }
 
   EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
diff --git a/clang/test/CodeGenHLSL/export.hlsl b/clang/test/CodeGenHLSL/export.hlsl
index 53f603739e329..98d1a5a2f13fb 100644
--- a/clang/test/CodeGenHLSL/export.hlsl
+++ b/clang/test/CodeGenHLSL/export.hlsl
@@ -1,20 +1,30 @@
 // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s \
 // RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+// RUN: %clang --driver-mode=dxc -T lib_6_3 -Od %s | FileCheck %s --check-prefix=CHECK-MD
 
-// CHECK: define void @"?f1@@YAXXZ"()
+// CHECK: define void @"?f1@@YAXXZ"() [[Attr:\#[0-9]+]]
 export void f1() {
 }
 
-// CHECK: define void @"?f2 at MyNamespace@@YAXXZ"()
+// CHECK: define void @"?f2 at MyNamespace@@YAXXZ"() [[Attr]]
 namespace MyNamespace {
   export void f2() {
   }
 }
 
 export {
-// CHECK: define void @"?f3@@YAXXZ"()
-// CHECK: define void @"?f4@@YAXXZ"()    
+// CHECK: define void @"?f3@@YAXXZ"() [[Attr]]
+// CHECK: define void @"?f4@@YAXXZ"() [[Attr]]
     void f3() {}
     void f4() {}
 }
+
+// CHECK: attributes [[Attr]] = { {{.*}} "hlsl.export" {{.*}} }
+
+// CHECK-MD: !dx.exports = !{[[Exp1:![0-9]+]], [[Exp2:![0-9]+]], [[Exp3:![0-9]+]], [[Exp4:![0-9]+]]}
+// CHECK-MD: [[Exp1]] = !{ptr @"?f1@@YAXXZ", !"?f1@@YAXXZ"}
+// CHECK-MD: [[Exp2]] = !{ptr @"?f2 at MyNamespace@@YAXXZ", !"?f2 at MyNamespace@@YAXXZ"}
+// CHECK-MD: [[Exp3]] = !{ptr @"?f3@@YAXXZ", !"?f3@@YAXXZ"}
+// CHECK-MD: [[Exp4]] = !{ptr @"?f4@@YAXXZ", !"?f4@@YAXXZ"}
+
diff --git a/llvm/lib/Target/DirectX/DXILMetadata.cpp b/llvm/lib/Target/DirectX/DXILMetadata.cpp
index ed0434ac98a18..cd554471b15c7 100644
--- a/llvm/lib/Target/DirectX/DXILMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILMetadata.cpp
@@ -328,3 +328,23 @@ void dxil::createEntryMD(Module &M, const uint64_t ShaderFlags) {
   for (auto *Entry : Entries)
     EntryPointsNamedMD->addOperand(Entry);
 }
+
+void dxil::createExportsMD(Module &M) {
+  LLVMContext &Ctx = M.getContext();
+  std::vector<MDNode *> ExportsMDList;
+  for (auto &F : M.functions()) {
+    if (!F.hasFnAttribute("hlsl.export"))
+      continue;
+    
+    Metadata *MDVals[2];
+    MDVals[0] = ValueAsMetadata::get(&F);
+    MDVals[1] = MDString::get(Ctx, F.getName());
+    ExportsMDList.emplace_back(MDNode::get(Ctx, MDVals));
+  }
+
+  if (ExportsMDList.size() != 0) {
+    NamedMDNode *ExportsNamedMD = M.getOrInsertNamedMetadata("dx.exports");
+    for (auto *ExpMD : ExportsMDList)
+      ExportsNamedMD->addOperand(ExpMD);
+  }
+}
diff --git a/llvm/lib/Target/DirectX/DXILMetadata.h b/llvm/lib/Target/DirectX/DXILMetadata.h
index e05db8d5370db..cee05661c81ca 100644
--- a/llvm/lib/Target/DirectX/DXILMetadata.h
+++ b/llvm/lib/Target/DirectX/DXILMetadata.h
@@ -36,6 +36,7 @@ class ValidatorVersionMD {
 void createShaderModelMD(Module &M);
 void createDXILVersionMD(Module &M);
 void createEntryMD(Module &M, const uint64_t ShaderFlags);
+void createExportsMD(Module &M);
 
 } // namespace dxil
 } // namespace llvm
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 583bce0f50e70..54eebac6a95d1 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -57,6 +57,7 @@ bool DXILTranslateMetadata::runOnModule(Module &M) {
   const uint64_t Flags = static_cast<uint64_t>(
       getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags());
   dxil::createEntryMD(M, Flags);
+  dxil::createExportsMD(M);
 
   return false;
 }



More information about the cfe-commits mailing list