| 
12 | 12 | //===----------------------------------------------------------------------===//  | 
13 | 13 | 
 
  | 
14 | 14 | #include "llvm-objdump.h"  | 
15 |  | -#include "llvm/BinaryFormat/DXContainer.h"  | 
16 | 15 | #include "llvm/Object/DXContainer.h"  | 
17 |  | -#include "llvm/Support/ScopedPrinter.h"  | 
18 | 16 | 
 
  | 
19 | 17 | 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 |  | -}  | 
51 | 18 | 
 
  | 
52 | 19 | namespace {  | 
53 | 20 | class DXContainerDumper : public objdump::Dumper {  | 
54 |  | -  const DXContainerObjectFile &Obj;  | 
55 |  | - | 
56 | 21 | public:  | 
57 |  | -  DXContainerDumper(const DXContainerObjectFile &O)  | 
58 |  | -      : objdump::Dumper(O), Obj(O) {}  | 
59 |  | - | 
60 |  | -  void printPrivateHeaders() override;  | 
61 |  | -  void printSignature(const DirectX::Signature &S);  | 
 | 22 | +  DXContainerDumper(const object::DXContainerObjectFile &Obj)  | 
 | 23 | +      : objdump::Dumper(Obj) {}  | 
62 | 24 | };  | 
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 | 25 | } // namespace  | 
151 | 26 | 
 
  | 
152 | 27 | std::unique_ptr<objdump::Dumper> llvm::objdump::createDXContainerDumper(  | 
 | 
0 commit comments