4 #include "llvm-c/Disassembler.h"
5 #include "ac_llvm_util.h"
7 #include <llvm/ADT/StringRef.h>
11 void print_asm(Program
*program
, std::vector
<uint32_t>& binary
,
12 unsigned exec_size
, std::ostream
& out
)
14 std::vector
<bool> referenced_blocks(program
->blocks
.size());
15 referenced_blocks
[0] = true;
16 for (Block
& block
: program
->blocks
) {
17 for (unsigned succ
: block
.linear_succs
)
18 referenced_blocks
[succ
] = true;
21 std::vector
<std::tuple
<uint64_t, llvm::StringRef
, uint8_t>> symbols
;
22 std::vector
<std::array
<char,16>> block_names
;
23 block_names
.reserve(program
->blocks
.size());
24 for (Block
& block
: program
->blocks
) {
25 if (!referenced_blocks
[block
.index
])
27 std::array
<char, 16> name
;
28 sprintf(name
.data(), "BB%u", block
.index
);
29 block_names
.push_back(name
);
30 symbols
.emplace_back(block
.offset
* 4, llvm::StringRef(block_names
[block_names
.size() - 1].data()), 0);
33 const char *features
= "";
34 if (program
->chip_class
>= GFX10
&& program
->wave_size
== 64) {
35 features
= "+wavefrontsize64";
38 LLVMDisasmContextRef disasm
= LLVMCreateDisasmCPUFeatures("amdgcn-mesa-mesa3d",
39 ac_get_llvm_processor_name(program
->family
),
41 &symbols
, 0, NULL
, NULL
);
46 unsigned next_block
= 0;
47 while (pos
< exec_size
) {
48 while (next_block
< program
->blocks
.size() && pos
== program
->blocks
[next_block
].offset
) {
49 if (referenced_blocks
[next_block
])
50 out
<< "BB" << std::dec
<< next_block
<< ":" << std::endl
;
54 size_t l
= LLVMDisasmInstruction(disasm
, (uint8_t *) &binary
[pos
],
55 (exec_size
- pos
) * sizeof(uint32_t), pos
* 4,
56 outline
, sizeof(outline
));
59 const int align_width
= 60;
60 if (program
->chip_class
== GFX9
&& !l
&& ((binary
[pos
] & 0xffff8000) == 0xd1348000)) { /* not actually an invalid instruction */
61 out
<< std::left
<< std::setw(align_width
) << std::setfill(' ') << "\tv_add_u32_e64 + clamp";
64 out
<< std::left
<< std::setw(align_width
) << std::setfill(' ') << "(invalid instruction)";
68 out
<< std::left
<< std::setw(align_width
) << std::setfill(' ') << outline
;
70 new_pos
= pos
+ l
/ 4;
75 for (; pos
< new_pos
; pos
++)
76 out
<< " " << std::setfill('0') << std::setw(8) << std::hex
<< binary
[pos
];
79 out
<< std::setfill(' ') << std::setw(0) << std::dec
;
80 assert(next_block
== program
->blocks
.size());
82 LLVMDisasmDispose(disasm
);
84 if (program
->constant_data
.size()) {
85 out
<< std::endl
<< "/* constant data */" << std::endl
;
86 for (unsigned i
= 0; i
< program
->constant_data
.size(); i
+= 32) {
87 out
<< '[' << std::setw(6) << std::setfill('0') << std::dec
<< i
<< ']';
88 unsigned line_size
= std::min
<size_t>(program
->constant_data
.size() - i
, 32);
89 for (unsigned j
= 0; j
< line_size
; j
+= 4) {
90 unsigned size
= std::min
<size_t>(program
->constant_data
.size() - (i
+ j
), 4);
92 memcpy(&v
, &program
->constant_data
[i
+ j
], size
);
93 out
<< " " << std::setw(8) << std::setfill('0') << std::hex
<< v
;
99 out
<< std::setfill(' ') << std::setw(0) << std::dec
;
102 /* Invalid instructions usually lead to GPU hangs, which can make
103 * getting the actual invalid instruction hard. Abort here so that we
104 * can find the problem.