Skip to content

Commit

Permalink
Enables shader disassembly on msvc
Browse files Browse the repository at this point in the history
  • Loading branch information
GrantComm committed Sep 26, 2024
1 parent 50c3eec commit b8f7b4d
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 72 deletions.
32 changes: 18 additions & 14 deletions dive_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,7 @@ add_dependencies(${PROJECT_NAME} freedreno_devices_header)



if (MSVC)
# freedreno_ir3 build is currently disabled on MSVC
else()
add_custom_command(
add_custom_command(
OUTPUT ${FREEDRENO_IR3_ISA_SRC_FILE} ${FREEDRENO_IR3_ISA_HDR_FILE}
COMMAND ${Python3_EXECUTABLE} ${THIRDPARTY_DIRECTORY}/mesa/src/compiler/isaspec/decode.py
"--xml"
Expand All @@ -153,9 +150,9 @@ else()
DEPENDS "${THIRDPARTY_DIRECTORY}/mesa/src/compiler/isaspec/decode.py"
"${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/isa/ir3.xml"
VERBATIM
)
)

add_library(freedreno_ir3 STATIC
add_library(freedreno_ir3 STATIC
${FREEDRENO_IR3_ISA_SRC_FILE}
"${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/ir3/disasm-a3xx.c"
"${THIRDPARTY_DIRECTORY}/mesa/src/util/half_float.c"
Expand All @@ -170,9 +167,9 @@ else()
"${THIRDPARTY_DIRECTORY}/mesa/src/util/u_debug.c"
"${THIRDPARTY_DIRECTORY}/mesa/src/util/u_printf.c"
"${THIRDPARTY_DIRECTORY}/mesa/src/util/u_process.c"
)
)

target_include_directories(freedreno_ir3 PRIVATE
target_include_directories(freedreno_ir3 PRIVATE
"${THIRDPARTY_DIRECTORY}/mesa/include"
"${THIRDPARTY_DIRECTORY}/mesa/src"
"${THIRDPARTY_DIRECTORY}/mesa/src/compiler"
Expand All @@ -181,18 +178,25 @@ else()
"${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/common"
"${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/isa"
"${THIRDPARTY_DIRECTORY}/mesa/src/util/ralloc.c"
)
target_compile_definitions(freedreno_ir3 PRIVATE
)

if(MSVC)
target_compile_definitions(freedreno_ir3 PRIVATE
-DHAVE_STRUCT_TIMESPEC
)
else()
target_compile_definitions(freedreno_ir3 PRIVATE
-DHAVE_ENDIAN_H
-DHAVE_FUNC_ATTRIBUTE_PACKED
-DHAVE_STRUCT_TIMESPEC
-DHAVE_PTHREAD
)
target_compile_options(freedreno_ir3 PRIVATE -fPIC)
add_dependencies(${PROJECT_NAME} freedreno_ir3)
target_link_libraries(${PROJECT_NAME} PRIVATE freedreno_ir3)
)
endif()

target_compile_options(freedreno_ir3 PRIVATE -fPIC)
add_dependencies(${PROJECT_NAME} freedreno_ir3)
target_link_libraries(${PROJECT_NAME} PRIVATE freedreno_ir3)


if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
target_link_libraries(${PROJECT_NAME} PRIVATE dl)
Expand Down
52 changes: 42 additions & 10 deletions dive_core/shader_disassembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
#include "dive_core/common/common.h"
#include "pm4_info.h"

#ifndef _MSC_VER
#ifdef _MSC_VER
# include <stdio.h>
# include <stdlib.h>
#endif
extern "C"
{
# include "third_party/mesa/src/freedreno/common/disasm.h"
#include "third_party/mesa/src/freedreno/common/disasm.h"
}
#endif

namespace Dive
{
Expand All @@ -40,38 +42,58 @@ bool Disassemble(const uint8_t* shader_memory,
return false;
}

// TODO(b/309801805): Shader disassembly is disabled on windows due to compiler errors.
#ifndef _MSC_VER
std::string DisassembleA3XX(const uint8_t* data,
size_t max_size,
struct shader_stats* stats,
enum debug_t debug)
{
disasm_a3xx_set_debug(debug);

#ifdef _MSC_VER
FILE* disasm_file;
errno_t err = tmpfile_s(&disasm_file);
if (err != 0)
{
DIVE_ASSERT(err != 0);
}
DIVE_ASSERT(disasm_file == NULL);
#else
char* disasm_buf = nullptr;
size_t disasm_buf_size = 0;
FILE* disasm_file = open_memstream(&disasm_buf, &disasm_buf_size);
#endif

size_t code_size = max_size / sizeof(uint32_t);
int res = disasm_a3xx_stat(reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(data)),
max_size / sizeof(uint32_t),
static_cast<int>(code_size),
0,
disasm_file,
GetGPUID(),
stats);
((void)(res)); // avoid unused variable
DIVE_ASSERT(res != -1);
#ifdef _MSC_VER
rewind(disasm_file);
std::string disasm_output;
char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), disasm_file)) > 0)
{
disasm_output.append(buffer, bytes_read);
}
fclose(disasm_file);
return disasm_output;
#else
fflush(disasm_file);
disasm_buf[disasm_buf_size] = '\0';
std::string disasm(disasm_buf);
fclose(disasm_file);
free(disasm_buf);
return disasm;
}
#endif
}

void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, ILog* log_ptr)
{
#ifndef _MSC_VER
struct shader_stats stats;
std::string disasm = DisassembleA3XX(data, max_size, &stats, PRINT_RAW);
std::istringstream disasm_istr(disasm);
Expand All @@ -82,6 +104,16 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I
int prefix_len = 0;
for (std::string line; std::getline(disasm_istr, line);)
{
#ifdef _MSC_VER
sscanf_s(line.c_str(),
" :%d:%04d:%04d[%08xx_%08xx] %n",
&opc_cat,
&n,
&cycles,
&dword1,
&dword0,
&prefix_len);
#else
sscanf(line.c_str(),
" :%d:%04d:%04d[%08xx_%08xx] %n",
&opc_cat,
Expand All @@ -90,6 +122,7 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I
&dword1,
&dword0,
&prefix_len);
#endif
std::string instr(&line[prefix_len]);
if (n >= m_instructions_text.size())
{
Expand All @@ -106,7 +139,6 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I
}
m_gpr_count = (stats.fullreg + 3) / 4;
m_listing = DisassembleA3XX(data, max_size, &stats, PRINT_STATS);
#endif
}

} // namespace Dive
7 changes: 4 additions & 3 deletions third_party/mesa/src/c11/threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,12 @@ thrd_t thrd_current(void);
int thrd_detach(thrd_t);
int thrd_equal(thrd_t, thrd_t);
#if defined(__cplusplus)
[[ noreturn ]]
[[ noreturn ]] void thrd_exit(int);
# elif defined(_MSC_VER)
__declspec(noreturn) void thrd_exit(int);
#else
_Noreturn
_Noreturn void thrd_exit(int);
#endif
void thrd_exit(int);
int thrd_join(thrd_t, int *);
int thrd_sleep(const struct timespec *, struct timespec *);
void thrd_yield(void);
Expand Down
60 changes: 34 additions & 26 deletions third_party/mesa/src/compiler/isaspec/decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,14 @@ def resolve_simple_field(self, bitset, name):
static void decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_${df.get_c_name()}(void *out, struct decode_scope *scope, uint64_t val);
% endfor
static const struct isa_field_decode decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_fields[] = {
% for df in s.decode_fields(bitset):
{
% if len(list(s.decode_fields(bitset))) > 0:
% for df in s.decode_fields(bitset):
.name = "${df.name}",
.decode = decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_${df.get_c_name()},
},
% endfor
% endfor
% else:
{ 0 }, // Dummy initializer for empty case
% endif
};
static void decode_${bitset.get_c_name()}_gen_${bitset.gen_min}(void *out, struct decode_scope *scope);
%endfor
Expand Down Expand Up @@ -194,35 +196,41 @@ def resolve_simple_field(self, bitset, name):
% if case.display is not None:
.display = "${case.display}",
% endif
.num_fields = ${len(case.fields)},
.fields = {
% for field_name, field in case.fields.items():
{ .name = "${field_name}", .low = ${field.low}, .high = ${field.high},
% if field.expr is not None:
.num_fields = ${len(case.fields)},
.fields =
% if len(case.fields) > 0:
{
% for field_name, field in case.fields.items():
{ .name = "${field_name}", .low = ${field.low}, .high = ${field.high},
% if field.expr is not None:
.expr = &${isa.expressions[field.expr].get_c_name()},
% endif
% if field.display is not None:
% endif
% if field.display is not None:
.display = "${field.display}",
% endif
% endif
.type = ${field.get_c_typename()},
% if field.get_c_typename() == 'TYPE_BITSET':
% if field.get_c_typename() == 'TYPE_BITSET':
.bitsets = ${isa.roots[field.type].get_c_name()},
% if len(field.params) > 0:
.params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()},
% endif
% endif
% if field.get_c_typename() == 'TYPE_ENUM':
% if len(field.params) > 0:
.params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()},
% endif
% endif
% if field.get_c_typename() == 'TYPE_ENUM':
.enums = &${isa.enums[field.type].get_c_name()},
% endif
% if field.get_c_typename() == 'TYPE_ASSERT':
% endif
% if field.get_c_typename() == 'TYPE_ASSERT':
.val.bitset = { ${', '.join(isa.split_bits(field.val, 32))} },
% endif
% if field.get_c_typename() == 'TYPE_BRANCH' or field.get_c_typename() == 'TYPE_ABSBRANCH':
% endif
% if field.get_c_typename() == 'TYPE_BRANCH' or field.get_c_typename() == 'TYPE_ABSBRANCH':
.call = ${str(field.call).lower()},
% endif
},
% endfor
},
% endif
},
% endfor
}
% else:
{ 0 },
% endif
};
% endfor
static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min} = {
Expand Down
61 changes: 53 additions & 8 deletions third_party/mesa/src/compiler/isaspec/isaspec_decode_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,16 @@ isa_print(struct isa_print_state *state, const char *fmt, ...)
int ret;

va_start(args, fmt);
ret = vasprintf(&buffer, fmt, args);
#ifdef _MSC_VER
va_list args_copy;
va_copy(args_copy, args);
int len = _vscprintf(fmt, args_copy);
va_end(args_copy);
buffer = (char *)malloc(len + 1);
ret = _vsprintf_p(&buffer, len + 1, fmt, args);
#else
ret = vasprintf(&buffer, fmt, args);
#endif
va_end(args);

if (ret != -1) {
Expand Down Expand Up @@ -224,7 +233,27 @@ decode_error(struct decode_state *state, const char *fmt, ...)

va_list ap;
va_start(ap, fmt);
vasprintf(&state->errors[state->num_errors++], fmt, ap);
#ifdef _MSC_VER
va_list ap_copy;
va_copy(ap_copy, ap);
int len = _vscprintf(fmt, ap_copy);
va_end(ap_copy);

if (len == -1) {
va_end(ap);
return;
}

state->errors[state->num_errors] = (char *)malloc(len + 1);
if (!state->errors[state->num_errors]) {
va_end(ap);
return;
}

_vsprintf_p(state->errors[state->num_errors++], len + 1, fmt, ap);
#else
vasprintf(&state->errors[state->num_errors++], fmt, ap);
#endif
va_end(ap);
}

Expand Down Expand Up @@ -733,9 +762,17 @@ display(struct decode_scope *scope)
e++;
}

char *field_name = strndup(p, e-p);
display_field(scope, field_name);
free(field_name);
#ifdef _MSC_VER
char *field_name = (char *)malloc(e - p + 1);
strncpy(field_name, p, e - p);
field_name[e - p] = '\0';
display_field(scope, field_name);
free(field_name);
#else
char *field_name = strndup(p, e - p);
display_field(scope, field_name);
free(field_name);
#endif

p = e;
} else {
Expand Down Expand Up @@ -913,9 +950,17 @@ decode_bitset(void *out, struct decode_scope *scope)
e++;
}

char *field_name = strndup(p, e-p);
decode_field(out, scope, field_name);
free(field_name);
#ifdef _MSC_VER
char *field_name = (char *)malloc(e - p + 1);
strncpy(field_name, p, e - p);
field_name[e - p] = '\0';
decode_field(out, scope, field_name);
free(field_name);
#else
char *field_name = strndup(p, e - p);
decode_field(out, scope, field_name);
free(field_name);
#endif

p = e;
}
Expand Down
Loading

0 comments on commit b8f7b4d

Please sign in to comment.