Skip to content

Commit 729fccb

Browse files
committed
[DirectX][objdump] Add support for printing signatures
This adds support for printing the signature sections as part of the `-p` flag for printing private headers. The formatting aims to roughly match the formatting used by DXC's `/dumpbin` flag. Resolves #152380.
1 parent 44fbeb3 commit 729fccb

File tree

3 files changed

+293
-2
lines changed

3 files changed

+293
-2
lines changed

llvm/include/llvm/Object/DXContainer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,10 @@ class LLVM_ABI DXContainerObjectFile : public ObjectFile {
603603
}
604604

605605
public:
606+
const DXContainer &getDXContainer() const {
607+
return Container;
608+
}
609+
606610
static bool classof(const Binary *v) { return v->isDXContainer(); }
607611

608612
Expected<StringRef> getSymbolName(DataRefImpl) const override;
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-objdump -p %t | FileCheck %s
3+
--- !dxcontainer
4+
Header:
5+
Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
6+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
7+
Version:
8+
Major: 1
9+
Minor: 0
10+
FileSize: 630
11+
PartCount: 3
12+
PartOffsets: [ 64, 124, 184 ]
13+
Parts:
14+
- Name: ISG1
15+
Size: 52
16+
Signature:
17+
Parameters:
18+
- Stream: 0
19+
Name: AAA_HSFoo
20+
Index: 4391238 # This value forces the index column to widen
21+
SystemValue: Undefined
22+
CompType: Float32
23+
Register: 0
24+
Mask: 7
25+
ExclusiveMask: 2
26+
MinPrecision: Default
27+
- Name: OSG1
28+
Size: 52
29+
Signature:
30+
Parameters:
31+
- Stream: 0
32+
Name: SV_Position
33+
Index: 0
34+
SystemValue: Position
35+
CompType: Float32
36+
Register: 2147483647 # This value forces the register column to widen
37+
Mask: 15
38+
ExclusiveMask: 0
39+
MinPrecision: Default
40+
- Name: PSG1
41+
Size: 402
42+
Signature:
43+
Parameters:
44+
- Stream: 0
45+
Name: SV_TessFactor
46+
Index: 0
47+
SystemValue: FinalQuadEdgeTessfactor # The tessfactor forces the SysVal column to widen
48+
CompType: Float32
49+
Register: 0
50+
Mask: 8
51+
ExclusiveMask: 8
52+
MinPrecision: Default
53+
- Stream: 0
54+
Name: BBB
55+
Index: 0
56+
SystemValue: Undefined
57+
CompType: Float32
58+
Register: 0
59+
Mask: 7
60+
ExclusiveMask: 0
61+
MinPrecision: Default
62+
- Stream: 0
63+
Name: SV_TessFactor
64+
Index: 1
65+
SystemValue: FinalQuadEdgeTessfactor
66+
CompType: Float32
67+
Register: 1
68+
Mask: 8
69+
ExclusiveMask: 8
70+
MinPrecision: Default
71+
- Stream: 0
72+
Name: BBB
73+
Index: 1
74+
SystemValue: Undefined
75+
CompType: Float32
76+
Register: 1
77+
Mask: 7
78+
ExclusiveMask: 0
79+
MinPrecision: Default
80+
- Stream: 0
81+
Name: SV_TessFactor
82+
Index: 2
83+
SystemValue: FinalQuadEdgeTessfactor
84+
CompType: Float32
85+
Register: 2
86+
Mask: 8
87+
ExclusiveMask: 8
88+
MinPrecision: Default
89+
- Stream: 0
90+
Name: BBB
91+
Index: 2
92+
SystemValue: Undefined
93+
CompType: Float32
94+
Register: 2
95+
Mask: 7
96+
ExclusiveMask: 0
97+
MinPrecision: Default
98+
- Stream: 0
99+
Name: SV_TessFactor
100+
Index: 3
101+
SystemValue: FinalQuadEdgeTessfactor
102+
CompType: Float32
103+
Register: 3
104+
Mask: 8
105+
ExclusiveMask: 8
106+
MinPrecision: Default
107+
- Stream: 0
108+
Name: SV_InsideTessFactor
109+
Index: 0
110+
SystemValue: FinalQuadInsideTessfactor
111+
CompType: Float32
112+
Register: 4
113+
Mask: 8
114+
ExclusiveMask: 0
115+
MinPrecision: Default
116+
- Stream: 0
117+
Name: SV_InsideTessFactor
118+
Index: 1
119+
SystemValue: FinalQuadInsideTessfactor
120+
CompType: Float32
121+
Register: 5
122+
Mask: 8
123+
ExclusiveMask: 0
124+
MinPrecision: Default
125+
- Stream: 0
126+
Name: AVeryLongStringThatWillForceWidening # This value forces name column to widen
127+
Index: 0
128+
SystemValue: Undefined
129+
CompType: Float32
130+
Register: 6
131+
Mask: 15
132+
ExclusiveMask: 4
133+
MinPrecision: Default
134+
...
135+
136+
# CHECK: ; Input signature:
137+
# CHECK-NEXT: ;
138+
# CHECK-NEXT: ; Name Index Mask Register SysValue Format Used
139+
# CHECK-NEXT: ; ------------------------ ------- ----- -------- ---------- ------- -----
140+
# CHECK-NEXT: ; AAA_HSFoo 4391238 xyz 0 Undefined Float32 y
141+
142+
# CHECK: ; Output signature:
143+
# CHECK-NEXT: ;
144+
# CHECK-NEXT: ; Name Index Mask Register SysValue Format Used
145+
# CHECK-NEXT: ; ------------------------ ----- ----- ---------- ---------- ------- -----
146+
# CHECK-NEXT: ; SV_Position 0 xyzw 2147483647 Position Float32
147+
148+
# CHECK: ; Patch Constant signature:
149+
# CHECK-NEXT: ;
150+
# CHECK-NEXT: ; Name Index Mask Register SysValue Format Used
151+
# CHECK-NEXT: ; ------------------------------------ ----- ----- -------- ------------------------- ------- -----
152+
# CHECK-NEXT: ; SV_TessFactor 0 w 0 FinalQuadEdgeTessfactor Float32 w
153+
# CHECK-NEXT: ; BBB 0 xyz 0 Undefined Float32
154+
# CHECK-NEXT: ; SV_TessFactor 1 w 1 FinalQuadEdgeTessfactor Float32 w
155+
# CHECK-NEXT: ; BBB 1 xyz 1 Undefined Float32
156+
# CHECK-NEXT: ; SV_TessFactor 2 w 2 FinalQuadEdgeTessfactor Float32 w
157+
# CHECK-NEXT: ; BBB 2 xyz 2 Undefined Float32
158+
# CHECK-NEXT: ; SV_TessFactor 3 w 3 FinalQuadEdgeTessfactor Float32 w
159+
# CHECK-NEXT: ; SV_InsideTessFactor 0 w 4 FinalQuadInsideTessfactor Float32
160+
# CHECK-NEXT: ; SV_InsideTessFactor 1 w 5 FinalQuadInsideTessfactor Float32
161+
# CHECK-NEXT: ; AVeryLongStringThatWillForceWidening 0 xyzw 6 Undefined Float32 z

llvm/tools/llvm-objdump/DXContainerDump.cpp

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,142 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm-objdump.h"
15+
#include "llvm/BinaryFormat/DXContainer.h"
1516
#include "llvm/Object/DXContainer.h"
17+
#include "llvm/Support/ScopedPrinter.h"
1618

1719
using namespace llvm;
20+
using namespace llvm::object;
21+
22+
static llvm::SmallString<4> maskToString(uint8_t Mask) {
23+
llvm::SmallString<4> Result(" ");
24+
if (Mask & 1)
25+
Result[0] = 'x';
26+
if (Mask & 2)
27+
Result[1] = 'y';
28+
if (Mask & 4)
29+
Result[2] = 'z';
30+
if (Mask & 8)
31+
Result[3] = 'w';
32+
return Result;
33+
}
34+
35+
static void printColumnHeader(raw_ostream &OS, size_t Length) {
36+
for (size_t I = 0; I < Length; ++I)
37+
OS << "-";
38+
}
39+
40+
static void printColumnHeaders(raw_ostream &OS, ArrayRef<size_t> Lengths) {
41+
for (auto L : Lengths) {
42+
printColumnHeader(OS, L);
43+
OS << " ";
44+
}
45+
OS << "\n";
46+
}
47+
48+
static size_t digitsForNumber(size_t N) {
49+
return static_cast<size_t>(log10(static_cast<double>(N))) + 1;
50+
}
1851

1952
namespace {
2053
class DXContainerDumper : public objdump::Dumper {
54+
const DXContainerObjectFile &Obj;
55+
2156
public:
22-
DXContainerDumper(const object::DXContainerObjectFile &Obj)
23-
: objdump::Dumper(Obj) {}
57+
DXContainerDumper(const DXContainerObjectFile &O)
58+
: objdump::Dumper(O), Obj(O) {}
59+
60+
void printPrivateHeaders() override;
61+
void printSignature(const DirectX::Signature &S);
2462
};
63+
64+
void DXContainerDumper::printSignature(const DirectX::Signature &S) {
65+
// DXC prints a table like this as part of the shader disassembly:
66+
//; Name Index Mask Register SysValue Format Used
67+
//; -------------------- ----- ------ -------- -------- ------- ------
68+
//; NORMAL 0 xyz 0 NONE float xyz
69+
//; TEXCOORD 0 xy 1 NONE float xy
70+
71+
// DXC's implementation doesn't scale columns entirely completely for the
72+
// provided input, so this implementation is a bit more complicated in
73+
// formatting logic to scale with the size of the printed text.
74+
75+
// DXC gives names 21 characters for some unknown reason, I arbitrarily chose
76+
// to start at 24 so that we're not going shorter but are using a round
77+
// number.
78+
size_t LongestName = 24;
79+
size_t LongestSV = 10;
80+
size_t LongestIndex = strlen("Index");
81+
size_t LongestRegister = strlen("Register");
82+
size_t LongestFormat = strlen("Format");
83+
const size_t MaskWidth = 5;
84+
// Compute the column widths. Skip calculating the "Mask" and "Used" columns
85+
// since they both have widths of 4.
86+
for (auto El : S) {
87+
LongestName = std::max(LongestName, S.getName(El.NameOffset).size());
88+
LongestSV = std::max(
89+
LongestSV,
90+
enumToStringRef(El.SystemValue, dxbc::getD3DSystemValues()).size());
91+
LongestIndex = std::max(LongestIndex, digitsForNumber(El.Index));
92+
LongestRegister = std::max(LongestRegister, digitsForNumber(El.Register));
93+
LongestFormat = std::max(
94+
LongestFormat,
95+
enumToStringRef(El.CompType, dxbc::getSigComponentTypes()).size());
96+
}
97+
98+
// Print Column headers
99+
OS << "; ";
100+
OS << left_justify("Name", LongestName) << " ";
101+
OS << right_justify("Index", LongestIndex) << " ";
102+
OS << right_justify("Mask", MaskWidth) << " ";
103+
OS << right_justify("Register", LongestRegister) << " ";
104+
OS << right_justify("SysValue", LongestSV) << " ";
105+
OS << right_justify("Format", LongestFormat) << " ";
106+
OS << right_justify("Used", MaskWidth) << "\n";
107+
OS << "; ";
108+
printColumnHeaders(OS, {LongestName, LongestIndex, MaskWidth, LongestRegister,
109+
LongestSV, LongestFormat, MaskWidth});
110+
111+
for (auto El : S) {
112+
OS << "; " << left_justify(S.getName(El.NameOffset), LongestName) << " ";
113+
OS << right_justify(std::to_string(El.Index), LongestIndex) << " ";
114+
OS << right_justify(maskToString(El.Mask), MaskWidth) << " ";
115+
OS << right_justify(std::to_string(El.Register), LongestRegister) << " ";
116+
OS << right_justify(
117+
enumToStringRef(El.SystemValue, dxbc::getD3DSystemValues()),
118+
LongestSV)
119+
<< " ";
120+
OS << right_justify(
121+
enumToStringRef(El.CompType, dxbc::getSigComponentTypes()),
122+
LongestFormat)
123+
<< " ";
124+
OS << right_justify(maskToString(El.ExclusiveMask), MaskWidth) << "\n";
125+
}
126+
}
127+
128+
void DXContainerDumper::printPrivateHeaders() {
129+
const DXContainer &C =
130+
cast<object::DXContainerObjectFile>(Obj).getDXContainer();
131+
132+
if (!C.getInputSignature().isEmpty()) {
133+
OS << "; Input signature:\n;\n";
134+
printSignature(C.getInputSignature());
135+
OS << ";\n";
136+
}
137+
138+
if (!C.getOutputSignature().isEmpty()) {
139+
OS << "; Output signature:\n;\n";
140+
printSignature(C.getOutputSignature());
141+
OS << ";\n";
142+
}
143+
144+
if (!C.getPatchConstantSignature().isEmpty()) {
145+
OS << "; Patch Constant signature:\n;\n";
146+
printSignature(C.getPatchConstantSignature());
147+
OS << ";\n";
148+
}
149+
}
150+
25151
} // namespace
26152

27153
std::unique_ptr<objdump::Dumper> llvm::objdump::createDXContainerDumper(

0 commit comments

Comments
 (0)