From 0c6079a84eedd52123d6f9e12dfb3375b8efe580 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Mon, 27 Oct 2025 10:22:16 -0700 Subject: [PATCH 1/5] [DirectX] Use an allow-list on module metadata --- .../Target/DirectX/DXILTranslateMetadata.cpp | 35 +++++---- llvm/test/CodeGen/DirectX/strip-module-md.ll | 75 +++++++++++++++++++ 2 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/strip-module-md.ll diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 1e4797bbd05aa..f7051efe6eb69 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -364,6 +364,16 @@ static void cleanModuleFlags(Module &M) { M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val); } +using GlobalMDList = std::array; + +// The following are compatible with DXIL but not emit with clang, they can +// be added when applicable: +// dx.typeAnnotations, dx.viewIDState, dx.dxrPayloadAnnotations +static GlobalMDList CompatibleNamedModuleMDs = { + "llvm.ident", "llvm.module.flags", "dx.resources", "dx.valver", + "dx.shaderModel", "dx.version", "dx.entryPoints", +}; + static void translateGlobalMetadata(Module &M, DXILResourceMap &DRM, DXILResourceTypeMap &DRTM, const ModuleShaderFlags &ShaderFlags, @@ -426,19 +436,18 @@ static void translateGlobalMetadata(Module &M, DXILResourceMap &DRM, cleanModuleFlags(M); - // dx.rootsignatures will have been parsed from its metadata form as its - // binary form as part of the RootSignatureAnalysisWrapper, so safely - // remove it as it is not recognized in DXIL - if (NamedMDNode *RootSignature = M.getNamedMetadata("dx.rootsignatures")) - RootSignature->eraseFromParent(); - - // llvm.errno.tbaa was recently added but is not supported in LLVM 3.7 and - // causes all tests using the DXIL Validator to fail. - // - // This is a temporary fix and should be replaced with a allowlist once - // we have determined all metadata that the DXIL Validator allows - if (NamedMDNode *ErrNo = M.getNamedMetadata("llvm.errno.tbaa")) - ErrNo->eraseFromParent(); + // Finally, strip all module metadata that is not explicitly specified in the + // allow-list + SmallVector ToStrip; + + for (NamedMDNode &NamedMD : M.named_metadata()) { + if (!NamedMD.getName().starts_with("llvm.dbg.") && + !llvm::is_contained(CompatibleNamedModuleMDs, NamedMD.getName())) + ToStrip.push_back(&NamedMD); + } + + for (NamedMDNode *NamedMD : ToStrip) + NamedMD->eraseFromParent(); } PreservedAnalyses DXILTranslateMetadata::run(Module &M, diff --git a/llvm/test/CodeGen/DirectX/strip-module-md.ll b/llvm/test/CodeGen/DirectX/strip-module-md.ll new file mode 100644 index 0000000000000..4d8b9ec935f6b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/strip-module-md.ll @@ -0,0 +1,75 @@ +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s + +; Ensures that only metadata explictly specified on the allow list, or debug +; related, metadata is emitted + +target triple = "dxil-unknown-shadermodel6.0-compute" + +; CHECK-NOT: !dx.rootsignatures +; CHECK-NOT: !llvm.errno.tbaa + +; CHECK-DAG: !llvm.dbg.cu + +; CHECK-DAG: !llvm.module.flags = !{![[#DWARF_VER:]], ![[#DEBUG_VER:]]} +; CHECK-DAG: !llvm.ident = !{![[#IDENT:]]} + +; CHECK-DAG: !dx.shaderModel +; CHECK-DAG: !dx.version +; CHECK-DAG: !dx.entryPoints +; CHECK-DAG: !dx.valver +; CHECK-DAG: !dx.resources + +; CHECK-NOT: !dx.rootsignatures +; CHECK-NOT: !llvm.errno.tbaa + +; Check allowed llvm metadata structure to ensure it is still DXIL compatible +; If this fails, please ensure that the updated form is DXIL compatible before +; updating the test. + +; CHECK-DAG: ![[#IDENT]] = !{!"clang 22.0.0"} +; CHECK-DAG: ![[#DWARF_VER]] = !{i32 2, !"Dwarf Version", i32 2} +; CHECK-DAG: ![[#DEBUG_VER]] = !{i32 2, !"Debug Info Version", i32 3} + +; CHECK-NOT: !dx.rootsignatures +; CHECK-NOT: !llvm.errno.tbaa + +@BufA.str = private unnamed_addr constant [5 x i8] c"BufA\00", align 1 + +define void @main () #0 { +entry: + %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0( + i32 3, i32 5, i32 1, i32 0, ptr @BufA.str) + ret void +} + +attributes #0 = { noinline nounwind "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } + +; Incompatible +!dx.rootsignatures = !{!2} +!llvm.errno.tbaa = !{!5} + +; Compatible +!llvm.dbg.cu = !{!8} +!llvm.module.flags = !{!11, !12} +!llvm.ident = !{!13} +!dx.valver = !{!14} + +!2 = !{ ptr @main, !3, i32 2 } +!3 = !{ !4 } +!4 = !{ !"RootFlags", i32 1 } + +!5 = !{!6, !6, i64 0} +!6 = !{!"omnipotent char", !7} +!7 = !{!"Simple C/C++ TBAA"} + +!8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !9, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !10, splitDebugInlining: false, nameTableKind: None) +!9 = !DIFile(filename: "hlsl.hlsl", directory: "/some-path") +!10 = !{} + +!11 = !{i32 2, !"Dwarf Version", i32 2} +!12 = !{i32 2, !"Debug Info Version", i32 3} + +!13 = !{!"clang 22.0.0"} + +!14 = !{i32 1, i32 1} From c7814967cbfe9df20bd1e59258e344a41f5a4132 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Mon, 27 Oct 2025 11:19:38 -0700 Subject: [PATCH 2/5] style-guide --- llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index f7051efe6eb69..be31da15581a3 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -440,11 +440,10 @@ static void translateGlobalMetadata(Module &M, DXILResourceMap &DRM, // allow-list SmallVector ToStrip; - for (NamedMDNode &NamedMD : M.named_metadata()) { + for (NamedMDNode &NamedMD : M.named_metadata()) if (!NamedMD.getName().starts_with("llvm.dbg.") && !llvm::is_contained(CompatibleNamedModuleMDs, NamedMD.getName())) ToStrip.push_back(&NamedMD); - } for (NamedMDNode *NamedMD : ToStrip) NamedMD->eraseFromParent(); From 34d6d6137c74fcbcf74f8e9b8f67e4d8e865c478 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Wed, 29 Oct 2025 11:56:59 -0700 Subject: [PATCH 3/5] update md-manystrings to use DXIL compatible metadata this test checks that we can embed lots of string as metadata into DXIL bitcode and retrieve it again renaming the metadata to llvm.ident retains the testing with a DXIL compatible metadata node --- llvm/test/tools/dxil-dis/md-manystrings.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/tools/dxil-dis/md-manystrings.ll b/llvm/test/tools/dxil-dis/md-manystrings.ll index 938e2dd5114da..a7dd595f09d94 100644 --- a/llvm/test/tools/dxil-dis/md-manystrings.ll +++ b/llvm/test/tools/dxil-dis/md-manystrings.ll @@ -4,7 +4,7 @@ target triple = "dxil-unknown-shadermodel6.7-library" -!llvm.too_many_strings = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31} +!llvm.ident = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31} !0 = !{!"String 0"} !1 = !{!"String 1"} @@ -39,7 +39,7 @@ target triple = "dxil-unknown-shadermodel6.7-library" !30 = !{!"String 30"} !31 = !{!"String 31"} -; CHECK: !llvm.too_many_strings = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31} +; CHECK: !llvm.ident = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31} ; CHECK: !0 = !{!"String 0"} ; CHECK: !1 = !{!"String 1"} ; CHECK: !2 = !{!"String 2"} From 0019e625b8da6d418d33bd828a530e21c2665a20 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Wed, 29 Oct 2025 11:58:36 -0700 Subject: [PATCH 4/5] update di-subprogram to only use DXIL compatible metadata the intent of this test is to ensure that the metadata written with the DXIL bitcode writer is correctly read back from being embedded in the DXIL removing the unrecognized metadata retains the test purpose --- llvm/test/tools/dxil-dis/di-subprogram.ll | 37 ----------------------- 1 file changed, 37 deletions(-) diff --git a/llvm/test/tools/dxil-dis/di-subprogram.ll b/llvm/test/tools/dxil-dis/di-subprogram.ll index 8255d396dd55d..912421fb28ae5 100644 --- a/llvm/test/tools/dxil-dis/di-subprogram.ll +++ b/llvm/test/tools/dxil-dis/di-subprogram.ll @@ -3,8 +3,6 @@ target triple = "dxil-unknown-shadermodel6.7-library" !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!3, !4} -!llvm.used = !{!5} -!llvm.lines = !{!13, !14, !15, !16} ; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2) !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) @@ -16,38 +14,3 @@ target triple = "dxil-unknown-shadermodel6.7-library" !3 = !{i32 2, !"Dwarf Version", i32 4} ; CHECK: !4 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 2, !"Debug Info Version", i32 3} - -; CHECK: !5 = distinct !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: !0, variables: !9) -!5 = distinct !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !9) - -; CHECK: !6 = !DISubroutineType(types: !7) -!6 = !DISubroutineType(types: !7) - -; CHECK: !7 = !{!8, !8, !8, !8} -!7 = !{!8, !8, !8, !8} - -; CHECK: !8 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) -!8 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) - -; CHECK: !9 = !{!10, !11, !12} -!9 = !{!10, !11, !12} - -; CHECK: !10 = !DILocalVariable(tag: DW_TAG_variable, name: "x", arg: 1, scope: !5, file: !1, line: 1, type: !8) -!10 = !DILocalVariable(name: "x", arg: 1, scope: !5, file: !1, line: 1, type: !8) - -; CHECK: !11 = !DILocalVariable(tag: DW_TAG_variable, name: "y", arg: 2, scope: !5, file: !1, line: 1, type: !8) -!11 = !DILocalVariable(name: "y", arg: 2, scope: !5, file: !1, line: 1, type: !8) - -; CHECK: !12 = !DILocalVariable(tag: DW_TAG_variable, name: "z", arg: 3, scope: !5, file: !1, line: 1, type: !8) -!12 = !DILocalVariable(name: "z", arg: 3, scope: !5, file: !1, line: 1, type: !8) - - -; CHECK: !13 = !DILocation(line: 0, scope: !5) -; CHECK: !14 = !DILocation(line: 2, column: 12, scope: !5) -; CHECK: !15 = !DILocation(line: 2, column: 16, scope: !5) -; CHECK: !16 = !DILocation(line: 2, column: 3, scope: !5) - -!13 = !DILocation(line: 0, scope: !5) -!14 = !DILocation(line: 2, column: 12, scope: !5) -!15 = !DILocation(line: 2, column: 16, scope: !5) -!16 = !DILocation(line: 2, column: 3, scope: !5) From 7966dad2e665a6044c9063eaff5b5f474830fa95 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Wed, 29 Oct 2025 12:03:34 -0700 Subject: [PATCH 5/5] remove di-subrotine this test is redundant with respect to di-subprogram, so we can remove it without reducing test coverage --- llvm/test/tools/dxil-dis/di-subrotine.ll | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 llvm/test/tools/dxil-dis/di-subrotine.ll diff --git a/llvm/test/tools/dxil-dis/di-subrotine.ll b/llvm/test/tools/dxil-dis/di-subrotine.ll deleted file mode 100644 index 285e319b74056..0000000000000 --- a/llvm/test/tools/dxil-dis/di-subrotine.ll +++ /dev/null @@ -1,12 +0,0 @@ -; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s -target triple = "dxil-unknown-shadermodel6.7-library" - -!llvm.used = !{!0} - -!0 = !DISubroutineType(types: !1) -!1 = !{!2, !2, !2, !2} -!2 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) - -; CHECK: !0 = !DISubroutineType(types: !1) -; CHECK: !1 = !{!2, !2, !2, !2} -; CHECK: !2 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)