[llvm] [DirectX] Make DISubprogram writing LLVM 3.7-compatible (PR #194418)
Harald van Dijk via llvm-commits
llvm-commits at lists.llvm.org
Fri May 8 18:38:06 PDT 2026
https://github.com/hvdijk updated https://github.com/llvm/llvm-project/pull/194418
>From 3b1583eb41f0a5b41f7a6b478f7c216b5b1e6b3f Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Thu, 5 Mar 2026 19:23:42 +0000
Subject: [PATCH 1/2] [DirectX] Fixes for generation of DISubprogram
* Reverse the links between DICompileUnit and DISubprogram
* Do not write DISubprogram as distinct
* Do not write DISubprogram metadata on function declarations
* Drop invalid flags for DISubprogram
---
.../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 12 +++--
.../DirectX/DirectXIRPasses/DXILDebugInfo.cpp | 26 ++++++++++
llvm/test/tools/dxil-dis/debug-info.ll | 20 ++++----
llvm/test/tools/dxil-dis/di-subprogram.ll | 48 ++++++++++++++++---
4 files changed, 86 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 15eb886574e6e..b0f66894348d2 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -1544,7 +1544,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
Record.push_back(N->getEmissionKind());
Record.push_back(VE.getMetadataOrNullID(N->getEnumTypes().get()));
Record.push_back(VE.getMetadataOrNullID(N->getRetainedTypes().get()));
- Record.push_back(/* subprograms */ 0);
+ Record.push_back(VE.getMetadataOrNullID(DebugInfo.MDExtra.lookup(N)));
Record.push_back(VE.getMetadataOrNullID(N->getGlobalVariables().get()));
Record.push_back(VE.getMetadataOrNullID(N->getImportedEntities().get()));
Record.push_back(N->getDWOId());
@@ -1556,7 +1556,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
void DXILBitcodeWriter::writeDISubprogram(const DISubprogram *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
- Record.push_back(N->isDistinct());
+ Record.push_back(/*Distinct*/ false);
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
Record.push_back(VE.getMetadataOrNullID(N->getRawLinkageName()));
@@ -1569,9 +1569,9 @@ void DXILBitcodeWriter::writeDISubprogram(const DISubprogram *N,
Record.push_back(VE.getMetadataOrNullID(N->getContainingType()));
Record.push_back(N->getVirtuality());
Record.push_back(N->getVirtualIndex());
- Record.push_back(N->getFlags());
+ Record.push_back(N->getFlags() & 0x7fff);
Record.push_back(N->isOptimized());
- Record.push_back(VE.getMetadataOrNullID(N->getRawUnit()));
+ Record.push_back(VE.getMetadataOrNullID(DebugInfo.MDExtra.lookup(N)));
Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
Record.push_back(VE.getMetadataOrNullID(N->getDeclaration()));
Record.push_back(VE.getMetadataOrNullID(N->getRetainedNodes().get()));
@@ -1888,9 +1888,13 @@ void DXILBitcodeWriter::writeFunctionMetadataAttachment(const Function &F) {
F.getAllMetadata(MDs);
if (!MDs.empty()) {
for (const auto &I : MDs) {
+ if (I.first == LLVMContext::MD_dbg)
+ continue;
Record.push_back(I.first);
Record.push_back(VE.getMetadataID(I.second));
}
+ }
+ if (!Record.empty()) {
Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
Record.clear();
}
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
index 650338949d19a..0034aa1247fe7 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
@@ -10,6 +10,8 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Module.h"
+#include <map>
+
#define DEBUG_TYPE "dx-debug-info"
using namespace llvm;
@@ -20,5 +22,29 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
DebugInfoFinder DIF;
DIF.processModule(M);
+ std::multimap<const DICompileUnit *, const Metadata *> CUSubprograms;
+
+ for (const Function &F : M) {
+ if (const DISubprogram *SP = F.getSubprogram()) {
+ auto *FunctionMD = ConstantAsMetadata::get(const_cast<Function *>(&F));
+ Res.MDExtra.insert({SP, FunctionMD});
+ }
+ }
+
+ for (const DISubprogram *SP : DIF.subprograms())
+ if (SP->getUnit())
+ CUSubprograms.insert({SP->getUnit(), SP});
+
+ for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
+ auto *CU = It->first;
+ auto CUEnd = CUSubprograms.upper_bound(CU);
+ SmallVector<Metadata *, 16> Subprograms;
+ do
+ Subprograms.push_back(const_cast<Metadata *>(It->second));
+ while (++It != CUEnd);
+ auto *SubprogramMD = MDTuple::get(M.getContext(), Subprograms);
+ Res.MDExtra.insert({CU, SubprogramMD});
+ }
+
return Res;
}
diff --git a/llvm/test/tools/dxil-dis/debug-info.ll b/llvm/test/tools/dxil-dis/debug-info.ll
index 420078a54dd3a..3f2d0ba835251 100644
--- a/llvm/test/tools/dxil-dis/debug-info.ll
+++ b/llvm/test/tools/dxil-dis/debug-info.ll
@@ -3,7 +3,7 @@
target triple = "dxil-unknown-shadermodel6.7-library"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
-; CHECK: define float @fma(float, float, float) unnamed_addr #0 !dbg [[Fn:[!][0-9]+]]
+; CHECK: define float @fma(float, float, float) unnamed_addr #0
define dso_local float @fma(float %0, float %1, float %2) local_unnamed_addr #0 !dbg !6 {
; CHECK-NEXT: call void @llvm.dbg.value(metadata float %0, metadata [[VarX:[!][0-9]+]], metadata [[Expr:[!][0-9]+]]), !dbg [[Line1:[!][0-9]+]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata float %1, metadata [[VarY:[!][0-9]+]], metadata [[Expr]]), !dbg [[Line1]]
@@ -32,15 +32,15 @@ attributes #0 = { norecurse nounwind readnone willreturn "hlsl.export" }
; CHECK: !0 = distinct !DICompileUnit
; CHECK-NEXT: !1 = !DIFile(filename:
-; CHECK: [[Fn]] = distinct !DISubprogram(name: "fma",
-; CHECK: [[VarX]] = !DILocalVariable(tag: DW_TAG_arg_variable
-; CHECK: [[VarY]] = !DILocalVariable(tag: DW_TAG_arg_variable
-; CHECK: [[VarZ]] = !DILocalVariable(tag: DW_TAG_arg_variable
-; CHECK-NEXT: [[Expr]] = !DIExpression()
-; CHECK-NEXT: [[Line1]] = !DILocation(line:
-; CHECK-NEXT: [[Line2]] = !DILocation(line:
-; CHECK-NEXT: [[Line3]] = !DILocation(line:
-; CHECK-NEXT: {{[!][0-9]+}} = !DILocation(line:
+; CHECK: [[Fn:[!][0-9]+]] = !DISubprogram(name: "fma",
+; CHECK: [[VarX]] = !DILocalVariable(tag:
+; CHECK: [[VarY]] = !DILocalVariable(tag:
+; CHECK: [[VarZ]] = !DILocalVariable(tag:
+; CHECK: [[Expr]] = !DIExpression()
+; CHECK: [[Line1]] = !DILocation(line:
+; CHECK: [[Line2]] = !DILocation(line:
+; CHECK: [[Line3]] = !DILocation(line:
+; CHECK: {{[!][0-9]+}} = !DILocation(line:
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "in.c", directory: "dir")
diff --git a/llvm/test/tools/dxil-dis/di-subprogram.ll b/llvm/test/tools/dxil-dis/di-subprogram.ll
index 912421fb28ae5..78fe96ec3adc3 100644
--- a/llvm/test/tools/dxil-dis/di-subprogram.ll
+++ b/llvm/test/tools/dxil-dis/di-subprogram.ll
@@ -1,16 +1,52 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"
+define float @fmaf(float %x, float %y, float %z) !dbg !4 {
+ unreachable
+}
+
+declare !dbg !14 double @fma(double %x, double %y, double %z)
+
!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4}
+!llvm.module.flags = !{!12, !13}
+!llvm.used = !{!5}
-; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2)
+; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
; CHECK: !1 = !DIFile(filename: "some-source", directory: "some-path")
!1 = !DIFile(filename: "some-source", directory: "some-path")
!2 = !{}
-; CHECK: !3 = !{i32 2, !"Dwarf Version", i32 4}
-!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: !4 = !DISubprogram(name: "fmaf", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: float (float, float, float)* @fmaf, variables: !8)
+!4 = distinct !DISubprogram(name: "fmaf", scope: !1, file: !1, line: 1, type: !5, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+
+; CHECK: !5 = !DISubroutineType(types: !6)
+!5 = !DISubroutineType(types: !6)
+
+; CHECK: !6 = !{!7, !7, !7, !7}
+!6 = !{!7, !7, !7, !7}
+
+; CHECK: !7 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!7 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+
+; CHECK: !8 = !{!9, !10, !11}
+!8 = !{!9, !10, !11}
+
+; CHECK: !9 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !7)
+!9 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !7)
+
+; CHECK: !10 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "y", arg: 2, scope: !4, file: !1, line: 1, type: !7)
+!10 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !1, line: 1, type: !7)
+
+; CHECK: !11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "z", arg: 3, scope: !4, file: !1, line: 1, type: !7)
+!11 = !DILocalVariable(name: "z", arg: 3, scope: !4, file: !1, line: 1, type: !7)
+
+; CHECK: !12 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Dwarf Version", i32 4}
+; CHECK: !13 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+
+!14 = !DISubprogram(name: "fma", scope: !1, file: !1, line: 1, type: !15, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!15 = !DISubroutineType(types: !16)
+!16 = !{!17, !17, !17, !17}
+!17 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
>From 3f198fc7faf1e3f77b8c076cd36016102dd3a274 Mon Sep 17 00:00:00 2001
From: Harald van Dijk <hdijk at accesssoftek.com>
Date: Wed, 6 May 2026 22:50:00 +0100
Subject: [PATCH 2/2] Move logic into DXILDebugInfoPass instead
---
.../DirectX/DXILWriter/DXILBitcodeWriter.cpp | 4 +-
.../DirectX/DirectXIRPasses/DXILDebugInfo.cpp | 53 +++++++++++++++----
2 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index b0f66894348d2..0489e75817fbe 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -1556,7 +1556,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
void DXILBitcodeWriter::writeDISubprogram(const DISubprogram *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
- Record.push_back(/*Distinct*/ false);
+ Record.push_back(N->isDistinct());
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
Record.push_back(VE.getMetadataOrNullID(N->getRawLinkageName()));
@@ -1569,7 +1569,7 @@ void DXILBitcodeWriter::writeDISubprogram(const DISubprogram *N,
Record.push_back(VE.getMetadataOrNullID(N->getContainingType()));
Record.push_back(N->getVirtuality());
Record.push_back(N->getVirtualIndex());
- Record.push_back(N->getFlags() & 0x7fff);
+ Record.push_back(N->getFlags());
Record.push_back(N->isOptimized());
Record.push_back(VE.getMetadataOrNullID(DebugInfo.MDExtra.lookup(N)));
Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
diff --git a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
index 0034aa1247fe7..fe1614dbe1879 100644
--- a/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXIRPasses/DXILDebugInfo.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "DXILDebugInfo.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Module.h"
@@ -22,7 +23,7 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
DebugInfoFinder DIF;
DIF.processModule(M);
- std::multimap<const DICompileUnit *, const Metadata *> CUSubprograms;
+ std::vector<std::pair<const DICompileUnit *, const Metadata *>> CUSubprograms;
for (const Function &F : M) {
if (const DISubprogram *SP = F.getSubprogram()) {
@@ -31,19 +32,53 @@ DXILDebugInfoMap DXILDebugInfoPass::run(Module &M) {
}
}
- for (const DISubprogram *SP : DIF.subprograms())
+ for (const DISubprogram *SP : DIF.subprograms()) {
+ const DISubprogram *NewSP = SP;
+
+ static constexpr auto SupportedDIFlags =
+ static_cast<DISubprogram::DIFlags>(DISubprogram::FlagExportSymbols - 1);
+ static constexpr auto SupportedDISPFlags =
+ static_cast<DISubprogram::DISPFlags>(DISubprogram::SPFlagPure - 1);
+ if (SP->isDistinct() || SP->getFlags() & ~SupportedDIFlags ||
+ SP->getSPFlags() & ~SupportedDISPFlags) {
+ NewSP = DISubprogram::get(
+ M.getContext(), SP->getScope(), SP->getName(), SP->getLinkageName(),
+ SP->getFile(), SP->getLine(), SP->getType(), SP->getScopeLine(),
+ SP->getContainingType(), SP->getVirtualIndex(),
+ SP->getThisAdjustment(), SP->getFlags() & SupportedDIFlags,
+ SP->getSPFlags() & SupportedDISPFlags, SP->getUnit(),
+ SP->getTemplateParams(), SP->getDeclaration(), SP->getRetainedNodes(),
+ SP->getThrownTypes(), SP->getAnnotations(), SP->getTargetFuncName(),
+ SP->getKeyInstructionsEnabled());
+
+ Res.MDReplace.insert({SP, NewSP});
+
+ if (auto It = Res.MDExtra.find(SP); It != Res.MDExtra.end()) {
+ auto *FunctionMD = It->second;
+ Res.MDExtra.erase(It);
+ Res.MDExtra.insert({NewSP, FunctionMD});
+ }
+ }
+
if (SP->getUnit())
- CUSubprograms.insert({SP->getUnit(), SP});
+ CUSubprograms.push_back(
+ {SP->getUnit(), static_cast<const Metadata *>(SP)});
+ }
+ std::stable_sort(
+ CUSubprograms.begin(), CUSubprograms.end(), [](auto &&A, auto &&B) {
+ return std::less<const DICompileUnit *>()(A.first, B.first);
+ });
for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
- auto *CU = It->first;
- auto CUEnd = CUSubprograms.upper_bound(CU);
+ const DICompileUnit *CU = It->first;
+ const DICompileUnit *NewCU =
+ cast<DICompileUnit>(Res.MDReplace.lookup_or(CU, CU));
SmallVector<Metadata *, 16> Subprograms;
- do
+ do {
Subprograms.push_back(const_cast<Metadata *>(It->second));
- while (++It != CUEnd);
- auto *SubprogramMD = MDTuple::get(M.getContext(), Subprograms);
- Res.MDExtra.insert({CU, SubprogramMD});
+ } while (++It != End && It->first == CU);
+ const auto *SubprogramsMD = MDTuple::get(M.getContext(), Subprograms);
+ Res.MDExtra.insert({NewCU, SubprogramsMD});
}
return Res;
More information about the llvm-commits
mailing list