| 
12 | 12 | //===----------------------------------------------------------------------===//  | 
13 | 13 | 
 
  | 
14 | 14 | #include "llvm-objdump.h"  | 
 | 15 | +#include "llvm/BinaryFormat/DXContainer.h"  | 
15 | 16 | #include "llvm/Object/DXContainer.h"  | 
 | 17 | +#include "llvm/Support/ScopedPrinter.h"  | 
16 | 18 | 
 
  | 
17 | 19 | 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 | +}  | 
18 | 51 | 
 
  | 
19 | 52 | namespace {  | 
20 | 53 | class DXContainerDumper : public objdump::Dumper {  | 
 | 54 | +  const DXContainerObjectFile &Obj;  | 
 | 55 | + | 
21 | 56 | 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);  | 
24 | 62 | };  | 
 | 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 | +}  | 
25 | 150 | } // namespace  | 
26 | 151 | 
 
  | 
27 | 152 | std::unique_ptr<objdump::Dumper> llvm::objdump::createDXContainerDumper(  | 
 | 
0 commit comments