nir: Stop using instructions for debug info
Annotating ssa defs without affecting compilation is impossible with debug info instructions since referencing a nir_def from the debug info instr will add uses. The old approach also stops worrking if passes reorder instructions. This patch proposes a solution which should not regress performance just like the old approach. The difference is that this one allocates a bit more space for debug info instead of adding a new instruction for it. Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33141>
This commit is contained in:

committed by
Marge Bot

parent
e73c4ce7c5
commit
60a20bcf3d
@@ -9947,22 +9947,17 @@ visit_jump(isel_context* ctx, nir_jump_instr* instr)
|
||||
}
|
||||
|
||||
void
|
||||
visit_debug_info(isel_context* ctx, nir_debug_info_instr* instr)
|
||||
visit_debug_info(isel_context* ctx, nir_instr_debug_info* instr_info)
|
||||
{
|
||||
ac_shader_debug_info info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
switch (instr->type) {
|
||||
case nir_debug_info_src_loc:
|
||||
info.type = ac_shader_debug_info_src_loc;
|
||||
info.src_loc.file = strdup(nir_src_as_string(instr->src_loc.filename));
|
||||
info.src_loc.line = instr->src_loc.line;
|
||||
info.src_loc.column = instr->src_loc.column;
|
||||
info.src_loc.spirv_offset = instr->src_loc.spirv_offset;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
info.type = ac_shader_debug_info_src_loc;
|
||||
if (instr_info->filename)
|
||||
info.src_loc.file = strdup(instr_info->filename);
|
||||
info.src_loc.line = instr_info->line;
|
||||
info.src_loc.column = instr_info->column;
|
||||
info.src_loc.spirv_offset = instr_info->spirv_offset;
|
||||
|
||||
Builder bld(ctx->program, ctx->block);
|
||||
bld.pseudo(aco_opcode::p_debug_info, Operand::c32(ctx->program->debug_info.size()));
|
||||
@@ -9990,6 +9985,9 @@ visit_block(isel_context* ctx, nir_block* block)
|
||||
ctx->block->instructions.reserve(ctx->block->instructions.size() +
|
||||
exec_list_length(&block->instr_list) * 2);
|
||||
nir_foreach_instr (instr, block) {
|
||||
if (ctx->shader->has_debug_info)
|
||||
visit_debug_info(ctx, nir_instr_get_debug_info(instr));
|
||||
|
||||
switch (instr->type) {
|
||||
case nir_instr_type_alu: visit_alu_instr(ctx, nir_instr_as_alu(instr)); break;
|
||||
case nir_instr_type_load_const: visit_load_const(ctx, nir_instr_as_load_const(instr)); break;
|
||||
@@ -9999,7 +9997,6 @@ visit_block(isel_context* ctx, nir_block* block)
|
||||
case nir_instr_type_undef: visit_undef(ctx, nir_instr_as_undef(instr)); break;
|
||||
case nir_instr_type_deref: break;
|
||||
case nir_instr_type_jump: visit_jump(ctx, nir_instr_as_jump(instr)); break;
|
||||
case nir_instr_type_debug_info: visit_debug_info(ctx, nir_instr_as_debug_info(instr)); break;
|
||||
default: isel_err(instr, "Unknown NIR instr type");
|
||||
}
|
||||
}
|
||||
|
@@ -375,6 +375,7 @@ radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_st
|
||||
.force_ssbo_non_uniform = pdev->cache_key.ssbo_non_uniform,
|
||||
.lower_terminate_to_discard = pdev->cache_key.lower_terminate_to_discard,
|
||||
.emit_debug_break = !!device->trap_handler_shader,
|
||||
.debug_info = !!(instance->debug_flags & RADV_DEBUG_NIR_DEBUG_INFO),
|
||||
};
|
||||
nir = spirv_to_nir(spirv, stage->spirv.size / 4, spec_entries, num_spec_entries, stage->stage, stage->entrypoint,
|
||||
&spirv_options, &pdev->nir_options[stage->stage]);
|
||||
|
@@ -1316,9 +1316,6 @@ v3d_instr_delay_cb(nir_instr *instr, void *data)
|
||||
|
||||
case nir_instr_type_tex:
|
||||
return 5;
|
||||
|
||||
case nir_instr_type_debug_info:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -663,12 +663,24 @@ nir_loop_create(nir_shader *shader)
|
||||
return loop;
|
||||
}
|
||||
|
||||
static void
|
||||
instr_init(nir_instr *instr, nir_instr_type type)
|
||||
static void *
|
||||
nir_instr_create(nir_shader *shader, nir_instr_type type, uint32_t size)
|
||||
{
|
||||
nir_instr *instr;
|
||||
if (shader->has_debug_info) {
|
||||
nir_instr_debug_info *debug_info =
|
||||
gc_zalloc_size(shader->gctx, offsetof(nir_instr_debug_info, instr) + size, 8);
|
||||
instr = &debug_info->instr;
|
||||
instr->has_debug_info = true;
|
||||
} else {
|
||||
instr = gc_zalloc_size(shader->gctx, size, 8);
|
||||
}
|
||||
|
||||
instr->type = type;
|
||||
instr->block = NULL;
|
||||
exec_node_init(&instr->node);
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -683,9 +695,10 @@ nir_alu_instr *
|
||||
nir_alu_instr_create(nir_shader *shader, nir_op op)
|
||||
{
|
||||
unsigned num_srcs = nir_op_infos[op].num_inputs;
|
||||
nir_alu_instr *instr = gc_zalloc_zla(shader->gctx, nir_alu_instr, nir_alu_src, num_srcs);
|
||||
nir_alu_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_alu,
|
||||
sizeof(nir_alu_instr) + sizeof(nir_alu_src) * num_srcs);
|
||||
|
||||
instr_init(&instr->instr, nir_instr_type_alu);
|
||||
instr->op = op;
|
||||
for (unsigned i = 0; i < num_srcs; i++)
|
||||
alu_src_init(&instr->src[i]);
|
||||
@@ -696,9 +709,8 @@ nir_alu_instr_create(nir_shader *shader, nir_op op)
|
||||
nir_deref_instr *
|
||||
nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type)
|
||||
{
|
||||
nir_deref_instr *instr = gc_zalloc(shader->gctx, nir_deref_instr, 1);
|
||||
|
||||
instr_init(&instr->instr, nir_instr_type_deref);
|
||||
nir_deref_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_deref, sizeof(nir_deref_instr));
|
||||
|
||||
instr->deref_type = deref_type;
|
||||
if (deref_type != nir_deref_type_var)
|
||||
@@ -714,8 +726,9 @@ nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type)
|
||||
nir_jump_instr *
|
||||
nir_jump_instr_create(nir_shader *shader, nir_jump_type type)
|
||||
{
|
||||
nir_jump_instr *instr = gc_alloc(shader->gctx, nir_jump_instr, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_jump);
|
||||
nir_jump_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_jump, sizeof(nir_jump_instr));
|
||||
|
||||
src_init(&instr->condition);
|
||||
instr->type = type;
|
||||
instr->target = NULL;
|
||||
@@ -729,8 +742,8 @@ nir_load_const_instr_create(nir_shader *shader, unsigned num_components,
|
||||
unsigned bit_size)
|
||||
{
|
||||
nir_load_const_instr *instr =
|
||||
gc_zalloc_zla(shader->gctx, nir_load_const_instr, nir_const_value, num_components);
|
||||
instr_init(&instr->instr, nir_instr_type_load_const);
|
||||
nir_instr_create(shader, nir_instr_type_load_const,
|
||||
sizeof(nir_load_const_instr) + sizeof(nir_const_value) * num_components);
|
||||
|
||||
nir_def_init(&instr->instr, &instr->def, num_components, bit_size);
|
||||
|
||||
@@ -742,9 +755,9 @@ nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op)
|
||||
{
|
||||
unsigned num_srcs = nir_intrinsic_infos[op].num_srcs;
|
||||
nir_intrinsic_instr *instr =
|
||||
gc_zalloc_zla(shader->gctx, nir_intrinsic_instr, nir_src, num_srcs);
|
||||
nir_instr_create(shader, nir_instr_type_intrinsic,
|
||||
sizeof(nir_intrinsic_instr) + sizeof(nir_src) * num_srcs);
|
||||
|
||||
instr_init(&instr->instr, nir_instr_type_intrinsic);
|
||||
instr->intrinsic = op;
|
||||
|
||||
for (unsigned i = 0; i < num_srcs; i++)
|
||||
@@ -758,9 +771,9 @@ nir_call_instr_create(nir_shader *shader, nir_function *callee)
|
||||
{
|
||||
const unsigned num_params = callee->num_params;
|
||||
nir_call_instr *instr =
|
||||
gc_zalloc_zla(shader->gctx, nir_call_instr, nir_src, num_params);
|
||||
nir_instr_create(shader, nir_instr_type_call,
|
||||
sizeof(nir_call_instr) + sizeof(nir_src) * num_params);
|
||||
|
||||
instr_init(&instr->instr, nir_instr_type_call);
|
||||
instr->callee = callee;
|
||||
instr->num_params = num_params;
|
||||
for (unsigned i = 0; i < num_params; i++)
|
||||
@@ -779,8 +792,8 @@ static int8_t default_tg4_offsets[4][2] = {
|
||||
nir_tex_instr *
|
||||
nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
|
||||
{
|
||||
nir_tex_instr *instr = gc_zalloc(shader->gctx, nir_tex_instr, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_tex);
|
||||
nir_tex_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_tex, sizeof(nir_tex_instr));
|
||||
|
||||
instr->num_srcs = num_srcs;
|
||||
instr->src = gc_alloc(shader->gctx, nir_tex_src, num_srcs);
|
||||
@@ -794,12 +807,28 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
|
||||
return instr;
|
||||
}
|
||||
|
||||
static void *
|
||||
nir_instr_get_gc_pointer(nir_instr *instr)
|
||||
{
|
||||
if (unlikely(instr->has_debug_info))
|
||||
return nir_instr_get_debug_info(instr);
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
static gc_ctx *
|
||||
nir_instr_get_gc_context(nir_instr *instr)
|
||||
{
|
||||
return gc_get_context(nir_instr_get_gc_pointer(instr));
|
||||
}
|
||||
|
||||
void
|
||||
nir_tex_instr_add_src(nir_tex_instr *tex,
|
||||
nir_tex_src_type src_type,
|
||||
nir_def *src)
|
||||
{
|
||||
nir_tex_src *new_srcs = gc_zalloc(gc_get_context(tex), nir_tex_src, tex->num_srcs + 1);
|
||||
nir_tex_src *new_srcs = gc_zalloc(nir_instr_get_gc_context(&tex->instr),
|
||||
nir_tex_src, tex->num_srcs + 1);
|
||||
|
||||
for (unsigned i = 0; i < tex->num_srcs; i++) {
|
||||
new_srcs[i].src_type = tex->src[i].src_type;
|
||||
@@ -843,8 +872,8 @@ nir_tex_instr_has_explicit_tg4_offsets(nir_tex_instr *tex)
|
||||
nir_phi_instr *
|
||||
nir_phi_instr_create(nir_shader *shader)
|
||||
{
|
||||
nir_phi_instr *instr = gc_alloc(shader->gctx, nir_phi_instr, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_phi);
|
||||
nir_phi_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_phi, sizeof(nir_phi_instr));
|
||||
|
||||
exec_list_make_empty(&instr->srcs);
|
||||
|
||||
@@ -864,7 +893,8 @@ nir_phi_instr_add_src(nir_phi_instr *instr, nir_block *pred, nir_def *src)
|
||||
{
|
||||
nir_phi_src *phi_src;
|
||||
|
||||
phi_src = gc_zalloc(gc_get_context(instr), nir_phi_src, 1);
|
||||
phi_src = gc_zalloc(nir_instr_get_gc_context(&instr->instr),
|
||||
nir_phi_src, 1);
|
||||
phi_src->pred = pred;
|
||||
phi_src->src = nir_src_for_ssa(src);
|
||||
nir_src_set_parent_instr(&phi_src->src, &instr->instr);
|
||||
@@ -876,41 +906,21 @@ nir_phi_instr_add_src(nir_phi_instr *instr, nir_block *pred, nir_def *src)
|
||||
nir_parallel_copy_instr *
|
||||
nir_parallel_copy_instr_create(nir_shader *shader)
|
||||
{
|
||||
nir_parallel_copy_instr *instr = gc_alloc(shader->gctx, nir_parallel_copy_instr, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_parallel_copy);
|
||||
nir_parallel_copy_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_parallel_copy, sizeof(nir_parallel_copy_instr));
|
||||
|
||||
exec_list_make_empty(&instr->entries);
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
nir_debug_info_instr *
|
||||
nir_debug_info_instr_create(nir_shader *shader, nir_debug_info_type type,
|
||||
uint32_t string_length)
|
||||
{
|
||||
uint32_t additional_size = 0;
|
||||
if (type == nir_debug_info_string)
|
||||
additional_size = string_length + 1;
|
||||
|
||||
nir_debug_info_instr *instr = gc_zalloc_size(
|
||||
shader->gctx, sizeof(nir_debug_info_instr) + additional_size, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_debug_info);
|
||||
|
||||
instr->type = type;
|
||||
|
||||
if (type == nir_debug_info_string)
|
||||
instr->string_length = string_length;
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
nir_undef_instr *
|
||||
nir_undef_instr_create(nir_shader *shader,
|
||||
unsigned num_components,
|
||||
unsigned bit_size)
|
||||
{
|
||||
nir_undef_instr *instr = gc_alloc(shader->gctx, nir_undef_instr, 1);
|
||||
instr_init(&instr->instr, nir_instr_type_undef);
|
||||
nir_undef_instr *instr =
|
||||
nir_instr_create(shader, nir_instr_type_undef, sizeof(nir_undef_instr));
|
||||
|
||||
nir_def_init(&instr->instr, &instr->def, num_components, bit_size);
|
||||
|
||||
@@ -1228,7 +1238,7 @@ nir_instr_free(nir_instr *instr)
|
||||
break;
|
||||
}
|
||||
|
||||
gc_free(instr);
|
||||
gc_free(nir_instr_get_gc_pointer(instr));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1367,9 +1377,6 @@ nir_instr_def(nir_instr *instr)
|
||||
case nir_instr_type_undef:
|
||||
return &nir_instr_as_undef(instr)->def;
|
||||
|
||||
case nir_instr_type_debug_info:
|
||||
return &nir_instr_as_debug_info(instr)->def;
|
||||
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
return NULL;
|
||||
@@ -1442,16 +1449,6 @@ nir_src_as_const_value(nir_src src)
|
||||
return load->value;
|
||||
}
|
||||
|
||||
const char *
|
||||
nir_src_as_string(nir_src src)
|
||||
{
|
||||
nir_debug_info_instr *di = nir_src_as_debug_info(src);
|
||||
if (di && di->type == nir_debug_info_string)
|
||||
return di->string;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the source is known to be always uniform. Otherwise it
|
||||
* returns false which means it may or may not be uniform but it can't be
|
||||
|
@@ -990,7 +990,6 @@ typedef enum ENUM_PACKED {
|
||||
nir_instr_type_undef,
|
||||
nir_instr_type_phi,
|
||||
nir_instr_type_parallel_copy,
|
||||
nir_instr_type_debug_info,
|
||||
} nir_instr_type;
|
||||
|
||||
typedef struct nir_instr {
|
||||
@@ -1003,6 +1002,12 @@ typedef struct nir_instr {
|
||||
*/
|
||||
uint8_t pass_flags;
|
||||
|
||||
/* Equal to nir_shader::has_debug_info and intended to be used by
|
||||
* functions that deal with debug information but do not have access to
|
||||
* the nir_shader.
|
||||
*/
|
||||
bool has_debug_info;
|
||||
|
||||
/** generic instruction index. */
|
||||
uint32_t index;
|
||||
} nir_instr;
|
||||
@@ -2722,40 +2727,34 @@ typedef struct {
|
||||
struct exec_list entries;
|
||||
} nir_parallel_copy_instr;
|
||||
|
||||
typedef enum nir_debug_info_type {
|
||||
nir_debug_info_src_loc,
|
||||
nir_debug_info_string,
|
||||
} nir_debug_info_type;
|
||||
/* This struct contains metadata for correlating the final nir shader
|
||||
* (after many lowering and optimization passes) with the source spir-v
|
||||
* or glsl. To avoid adding unnecessary overhead when the driver does not
|
||||
* preserve non-semantic information (which is the common case), debug
|
||||
* information is allocated before the instruction:
|
||||
*
|
||||
* +-------------------+-----------+--------------------------------+
|
||||
* | Debug information | nir_instr | Instruction type specific data |
|
||||
* +-------------------+-----------+--------------------------------+
|
||||
*
|
||||
* This is only allocated if nir_shader::has_debug_info is set. Accesses
|
||||
* to nir_instr_debug_info should therefore check nir_shader::has_debug_info
|
||||
* or nir_instr::has_debug_info.
|
||||
*/
|
||||
typedef struct nir_instr_debug_info {
|
||||
/* Path to the source file this instruction originates from. */
|
||||
char *filename;
|
||||
/* 0 if uninitialized. */
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
uint32_t spirv_offset;
|
||||
|
||||
typedef enum nir_debug_info_source {
|
||||
nir_debug_info_spirv,
|
||||
nir_debug_info_nir,
|
||||
} nir_debug_info_source;
|
||||
/* Line in the output of nir_print_shader. 0 if uninitialized. */
|
||||
uint32_t nir_line;
|
||||
|
||||
typedef struct nir_debug_info_instr {
|
||||
/* The nir_instr has to be the last field since it has a varying size. */
|
||||
nir_instr instr;
|
||||
|
||||
nir_debug_info_type type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
nir_src filename;
|
||||
/* 0 if only the spirv_offset is available. */
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
|
||||
uint32_t spirv_offset;
|
||||
|
||||
nir_debug_info_source source;
|
||||
} src_loc;
|
||||
|
||||
uint16_t string_length;
|
||||
};
|
||||
|
||||
nir_def def;
|
||||
|
||||
char string[];
|
||||
} nir_debug_info_instr;
|
||||
} nir_instr_debug_info;
|
||||
|
||||
NIR_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr,
|
||||
type, nir_instr_type_alu)
|
||||
@@ -2778,9 +2777,6 @@ NIR_DEFINE_CAST(nir_instr_as_phi, nir_instr, nir_phi_instr, instr,
|
||||
NIR_DEFINE_CAST(nir_instr_as_parallel_copy, nir_instr,
|
||||
nir_parallel_copy_instr, instr,
|
||||
type, nir_instr_type_parallel_copy)
|
||||
NIR_DEFINE_CAST(nir_instr_as_debug_info, nir_instr,
|
||||
nir_debug_info_instr, instr,
|
||||
type, nir_instr_type_debug_info)
|
||||
|
||||
#define NIR_DEFINE_SRC_AS_CONST(type, suffix) \
|
||||
static inline type \
|
||||
@@ -4516,6 +4512,8 @@ typedef struct nir_shader {
|
||||
|
||||
unsigned printf_info_count;
|
||||
u_printf_info *printf_info;
|
||||
|
||||
bool has_debug_info;
|
||||
} nir_shader;
|
||||
|
||||
#define nir_foreach_function(func, shader) \
|
||||
@@ -4740,10 +4738,6 @@ nir_phi_src *nir_phi_instr_add_src(nir_phi_instr *instr,
|
||||
|
||||
nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader);
|
||||
|
||||
nir_debug_info_instr *nir_debug_info_instr_create(nir_shader *shader,
|
||||
nir_debug_info_type type,
|
||||
uint32_t string_length);
|
||||
|
||||
nir_undef_instr *nir_undef_instr_create(nir_shader *shader,
|
||||
unsigned num_components,
|
||||
unsigned bit_size);
|
||||
@@ -5031,6 +5025,16 @@ nir_cursor nir_instr_free_and_dce(nir_instr *instr);
|
||||
|
||||
nir_def *nir_instr_def(nir_instr *instr);
|
||||
|
||||
/* Return the debug information associated with this instruction,
|
||||
* assuming the parent shader has debug info.
|
||||
*/
|
||||
static ALWAYS_INLINE nir_instr_debug_info *
|
||||
nir_instr_get_debug_info(nir_instr *instr)
|
||||
{
|
||||
assert(instr->has_debug_info);
|
||||
return container_of(instr, nir_instr_debug_info, instr);
|
||||
}
|
||||
|
||||
typedef bool (*nir_foreach_def_cb)(nir_def *def, void *state);
|
||||
typedef bool (*nir_foreach_src_cb)(nir_src *src, void *state);
|
||||
static inline bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state);
|
||||
@@ -5053,7 +5057,6 @@ NIR_SRC_AS_(alu_instr, nir_alu_instr, nir_instr_type_alu, nir_instr_as_alu)
|
||||
NIR_SRC_AS_(intrinsic, nir_intrinsic_instr,
|
||||
nir_instr_type_intrinsic, nir_instr_as_intrinsic)
|
||||
NIR_SRC_AS_(deref, nir_deref_instr, nir_instr_type_deref, nir_instr_as_deref)
|
||||
NIR_SRC_AS_(debug_info, nir_debug_info_instr, nir_instr_type_debug_info, nir_instr_as_debug_info)
|
||||
|
||||
const char *nir_src_as_string(nir_src src);
|
||||
|
||||
|
@@ -312,17 +312,6 @@ nir_build_tex_deref_instr(nir_builder *build, nir_texop op,
|
||||
return &tex->def;
|
||||
}
|
||||
|
||||
nir_def *
|
||||
nir_build_string(nir_builder *build, const char *value)
|
||||
{
|
||||
nir_debug_info_instr *instr =
|
||||
nir_debug_info_instr_create(build->shader, nir_debug_info_string, strlen(value));
|
||||
memcpy(instr->string, value, instr->string_length);
|
||||
nir_def_init(&instr->instr, &instr->def, 1, nir_get_ptr_bitsize(build->shader));
|
||||
nir_builder_instr_insert(build, &instr->instr);
|
||||
return &instr->def;
|
||||
}
|
||||
|
||||
nir_def *
|
||||
nir_vec_scalars(nir_builder *build, nir_scalar *comp, unsigned num_components)
|
||||
{
|
||||
@@ -385,6 +374,23 @@ nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
|
||||
{
|
||||
nir_instr_insert(build->cursor, instr);
|
||||
|
||||
if (unlikely(build->shader->has_debug_info &&
|
||||
(build->cursor.option == nir_cursor_before_instr ||
|
||||
build->cursor.option == nir_cursor_after_instr))) {
|
||||
nir_instr_debug_info *cursor_info = nir_instr_get_debug_info(build->cursor.instr);
|
||||
nir_instr_debug_info *instr_info = nir_instr_get_debug_info(instr);
|
||||
|
||||
if (!instr_info->line)
|
||||
instr_info->line = cursor_info->line;
|
||||
if (!instr_info->column)
|
||||
instr_info->column = cursor_info->column;
|
||||
if (!instr_info->spirv_offset)
|
||||
instr_info->spirv_offset = cursor_info->spirv_offset;
|
||||
if (!instr_info->filename)
|
||||
instr_info->filename = cursor_info->filename;
|
||||
}
|
||||
|
||||
|
||||
/* Move the cursor forward. */
|
||||
build->cursor = nir_after_instr(instr);
|
||||
}
|
||||
|
@@ -218,10 +218,49 @@ __clone_def(clone_state *state, nir_instr *ninstr,
|
||||
add_remap(state, ndef, def);
|
||||
}
|
||||
|
||||
/* Returns a copy of the argument string that is owned by the new shader.
|
||||
* Uses remap_table avoid allocating multiple copies of the same string.
|
||||
*/
|
||||
static char *
|
||||
clone_string(clone_state *state, const char *string)
|
||||
{
|
||||
if (!string)
|
||||
return NULL;
|
||||
|
||||
if (!state->remap_table)
|
||||
return ralloc_strdup(state->ns, string);
|
||||
|
||||
struct hash_entry *entry = _mesa_hash_table_search(state->remap_table, string);
|
||||
if (entry)
|
||||
return entry->data;
|
||||
|
||||
char *cloned = ralloc_strdup(state->ns, string);
|
||||
_mesa_hash_table_insert(state->remap_table, string, cloned);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
static void
|
||||
clone_debug_info(clone_state *state, nir_instr *ninstr, const nir_instr *instr)
|
||||
{
|
||||
if (likely(!state->ns->has_debug_info || !instr->has_debug_info))
|
||||
return;
|
||||
|
||||
nir_instr_debug_info *ndebug_info = nir_instr_get_debug_info(ninstr);
|
||||
const nir_instr_debug_info *debug_info = nir_instr_get_debug_info((void *)instr);
|
||||
|
||||
ndebug_info->filename = clone_string(state, debug_info->filename);
|
||||
|
||||
ndebug_info->line = debug_info->line;
|
||||
ndebug_info->column = debug_info->column;
|
||||
ndebug_info->spirv_offset = debug_info->spirv_offset;
|
||||
ndebug_info->nir_line = debug_info->nir_line;
|
||||
}
|
||||
|
||||
static nir_alu_instr *
|
||||
clone_alu(clone_state *state, const nir_alu_instr *alu)
|
||||
{
|
||||
nir_alu_instr *nalu = nir_alu_instr_create(state->ns, alu->op);
|
||||
clone_debug_info(state, &nalu->instr, &alu->instr);
|
||||
nalu->exact = alu->exact;
|
||||
nalu->fp_fast_math = alu->fp_fast_math;
|
||||
nalu->no_signed_wrap = alu->no_signed_wrap;
|
||||
@@ -253,6 +292,7 @@ clone_deref_instr(clone_state *state, const nir_deref_instr *deref)
|
||||
{
|
||||
nir_deref_instr *nderef =
|
||||
nir_deref_instr_create(state->ns, deref->deref_type);
|
||||
clone_debug_info(state, &nderef->instr, &deref->instr);
|
||||
|
||||
__clone_def(state, &nderef->instr, &nderef->def, &deref->def);
|
||||
|
||||
@@ -300,6 +340,7 @@ clone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr)
|
||||
{
|
||||
nir_intrinsic_instr *nitr =
|
||||
nir_intrinsic_instr_create(state->ns, itr->intrinsic);
|
||||
clone_debug_info(state, &nitr->instr, &itr->instr);
|
||||
|
||||
unsigned num_srcs = nir_intrinsic_infos[itr->intrinsic].num_srcs;
|
||||
|
||||
@@ -322,6 +363,7 @@ clone_load_const(clone_state *state, const nir_load_const_instr *lc)
|
||||
nir_load_const_instr *nlc =
|
||||
nir_load_const_instr_create(state->ns, lc->def.num_components,
|
||||
lc->def.bit_size);
|
||||
clone_debug_info(state, &nlc->instr, &lc->instr);
|
||||
|
||||
memcpy(&nlc->value, &lc->value, sizeof(*nlc->value) * lc->def.num_components);
|
||||
|
||||
@@ -337,6 +379,7 @@ clone_ssa_undef(clone_state *state, const nir_undef_instr *sa)
|
||||
nir_undef_instr *nsa =
|
||||
nir_undef_instr_create(state->ns, sa->def.num_components,
|
||||
sa->def.bit_size);
|
||||
clone_debug_info(state, &nsa->instr, &sa->instr);
|
||||
|
||||
if (likely(state->remap_table))
|
||||
add_remap(state, &nsa->def, &sa->def);
|
||||
@@ -348,6 +391,7 @@ static nir_tex_instr *
|
||||
clone_tex(clone_state *state, const nir_tex_instr *tex)
|
||||
{
|
||||
nir_tex_instr *ntex = nir_tex_instr_create(state->ns, tex->num_srcs);
|
||||
clone_debug_info(state, &ntex->instr, &tex->instr);
|
||||
|
||||
ntex->sampler_dim = tex->sampler_dim;
|
||||
ntex->dest_type = tex->dest_type;
|
||||
@@ -381,6 +425,7 @@ static nir_phi_instr *
|
||||
clone_phi(clone_state *state, const nir_phi_instr *phi, nir_block *nblk)
|
||||
{
|
||||
nir_phi_instr *nphi = nir_phi_instr_create(state->ns);
|
||||
clone_debug_info(state, &nphi->instr, &phi->instr);
|
||||
|
||||
__clone_def(state, &nphi->instr, &nphi->def, &phi->def);
|
||||
|
||||
@@ -417,6 +462,7 @@ clone_jump(clone_state *state, const nir_jump_instr *jmp)
|
||||
assert(jmp->type != nir_jump_goto && jmp->type != nir_jump_goto_if);
|
||||
|
||||
nir_jump_instr *njmp = nir_jump_instr_create(state->ns, jmp->type);
|
||||
clone_debug_info(state, &njmp->instr, &jmp->instr);
|
||||
|
||||
return njmp;
|
||||
}
|
||||
@@ -426,6 +472,7 @@ clone_call(clone_state *state, const nir_call_instr *call)
|
||||
{
|
||||
nir_function *ncallee = remap_global(state, call->callee);
|
||||
nir_call_instr *ncall = nir_call_instr_create(state->ns, ncallee);
|
||||
clone_debug_info(state, &ncall->instr, &call->instr);
|
||||
|
||||
for (unsigned i = 0; i < ncall->num_params; i++)
|
||||
__clone_src(state, ncall, &ncall->params[i], &call->params[i]);
|
||||
@@ -433,30 +480,6 @@ clone_call(clone_state *state, const nir_call_instr *call)
|
||||
return ncall;
|
||||
}
|
||||
|
||||
static nir_debug_info_instr *
|
||||
clone_debug_info(clone_state *state, nir_debug_info_instr *di)
|
||||
{
|
||||
nir_debug_info_instr *instr =
|
||||
nir_debug_info_instr_create(state->ns, di->type, di->string_length);
|
||||
|
||||
switch (di->type) {
|
||||
case nir_debug_info_src_loc:
|
||||
if (di->src_loc.line)
|
||||
__clone_src(state, instr, &instr->src_loc.filename, &di->src_loc.filename);
|
||||
instr->src_loc.line = di->src_loc.line;
|
||||
instr->src_loc.column = di->src_loc.column;
|
||||
instr->src_loc.spirv_offset = di->src_loc.spirv_offset;
|
||||
instr->src_loc.source = di->src_loc.source;
|
||||
return instr;
|
||||
case nir_debug_info_string:
|
||||
memcpy(instr->string, di->string, di->string_length);
|
||||
__clone_def(state, &instr->instr, &instr->def, &di->def);
|
||||
return instr;
|
||||
}
|
||||
|
||||
unreachable("Unimplemented nir_debug_info_type");
|
||||
}
|
||||
|
||||
static nir_instr *
|
||||
clone_instr(clone_state *state, const nir_instr *instr)
|
||||
{
|
||||
@@ -479,8 +502,6 @@ clone_instr(clone_state *state, const nir_instr *instr)
|
||||
return &clone_jump(state, nir_instr_as_jump(instr))->instr;
|
||||
case nir_instr_type_call:
|
||||
return &clone_call(state, nir_instr_as_call(instr))->instr;
|
||||
case nir_instr_type_debug_info:
|
||||
return &clone_debug_info(state, nir_instr_as_debug_info(instr))->instr;
|
||||
case nir_instr_type_parallel_copy:
|
||||
unreachable("Cannot clone parallel copies");
|
||||
default:
|
||||
@@ -783,6 +804,8 @@ nir_shader_clone(void *mem_ctx, const nir_shader *s)
|
||||
nir_shader *ns = nir_shader_create(mem_ctx, s->info.stage, s->options, NULL);
|
||||
state.ns = ns;
|
||||
|
||||
ns->has_debug_info = s->has_debug_info;
|
||||
|
||||
clone_var_list(&state, &ns->variables, &s->variables);
|
||||
|
||||
/* Go through and clone functions */
|
||||
|
@@ -1110,7 +1110,6 @@ instr_is_loop_invariant(nir_instr *instr, struct divergence_state *state)
|
||||
switch (instr->type) {
|
||||
case nir_instr_type_load_const:
|
||||
case nir_instr_type_undef:
|
||||
case nir_instr_type_debug_info:
|
||||
case nir_instr_type_jump:
|
||||
return true;
|
||||
case nir_instr_type_intrinsic:
|
||||
@@ -1146,8 +1145,6 @@ update_instr_divergence(nir_instr *instr, struct divergence_state *state)
|
||||
return visit_def(&nir_instr_as_undef(instr)->def, state);
|
||||
case nir_instr_type_deref:
|
||||
return visit_deref(state->shader, nir_instr_as_deref(instr), state);
|
||||
case nir_instr_type_debug_info:
|
||||
return false;
|
||||
case nir_instr_type_call:
|
||||
return false;
|
||||
case nir_instr_type_jump:
|
||||
|
@@ -32,13 +32,6 @@ _nir_foreach_def(nir_instr *instr, nir_foreach_def_cb cb, void *state)
|
||||
case nir_instr_type_undef:
|
||||
return cb(&nir_instr_as_undef(instr)->def, state);
|
||||
|
||||
case nir_instr_type_debug_info: {
|
||||
nir_debug_info_instr *di = nir_instr_as_debug_info(instr);
|
||||
if (di->type == nir_debug_info_string)
|
||||
return cb(&di->def, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
return true;
|
||||
@@ -141,15 +134,6 @@ nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_instr_type_debug_info: {
|
||||
nir_debug_info_instr *di = nir_instr_as_debug_info(instr);
|
||||
if (di->type == nir_debug_info_src_loc && di->src_loc.line) {
|
||||
if (!_nir_visit_src(&di->src_loc.filename, cb, state))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case nir_instr_type_load_const:
|
||||
case nir_instr_type_undef:
|
||||
return true;
|
||||
|
@@ -70,8 +70,6 @@ instr_can_rewrite(const nir_instr *instr)
|
||||
return nir_intrinsic_can_reorder(intr);
|
||||
}
|
||||
}
|
||||
case nir_instr_type_debug_info:
|
||||
return nir_instr_as_debug_info(instr)->type == nir_debug_info_string;
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
case nir_instr_type_undef:
|
||||
@@ -275,13 +273,6 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr)
|
||||
return hash;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hash_debug_info(uint32_t hash, const nir_debug_info_instr *instr)
|
||||
{
|
||||
assert(instr->type == nir_debug_info_string);
|
||||
return XXH32(instr->string, instr->string_length, hash);
|
||||
}
|
||||
|
||||
/* Computes a hash of an instruction for use in a hash table. Note that this
|
||||
* will only work for instructions where instr_can_rewrite() returns true, and
|
||||
* it should return identical hashes for two instructions that are the same
|
||||
@@ -313,9 +304,6 @@ hash_instr(const void *data)
|
||||
case nir_instr_type_tex:
|
||||
hash = hash_tex(hash, nir_instr_as_tex(instr));
|
||||
break;
|
||||
case nir_instr_type_debug_info:
|
||||
hash = hash_debug_info(hash, nir_instr_as_debug_info(instr));
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid instruction type");
|
||||
}
|
||||
@@ -739,16 +727,6 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
|
||||
|
||||
return true;
|
||||
}
|
||||
case nir_instr_type_debug_info: {
|
||||
nir_debug_info_instr *di1 = nir_instr_as_debug_info(instr1);
|
||||
nir_debug_info_instr *di2 = nir_instr_as_debug_info(instr2);
|
||||
|
||||
assert(di1->type == nir_debug_info_string);
|
||||
assert(di2->type == nir_debug_info_string);
|
||||
|
||||
return di1->string_length == di2->string_length &&
|
||||
!memcmp(di1->string, di2->string, di1->string_length);
|
||||
}
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
case nir_instr_type_undef:
|
||||
|
@@ -96,16 +96,6 @@ is_live(BITSET_WORD *defs_live, nir_instr *instr)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case nir_instr_type_debug_info: {
|
||||
nir_debug_info_instr *di = nir_instr_as_debug_info(instr);
|
||||
if (di->type == nir_debug_info_src_loc) {
|
||||
nir_instr *next = nir_instr_next(instr);
|
||||
return !next || next->type != nir_instr_type_debug_info;
|
||||
} else if (di->type == nir_debug_info_string) {
|
||||
return is_def_live(&di->def, defs_live);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
unreachable("unexpected instr type");
|
||||
}
|
||||
|
@@ -248,7 +248,6 @@ opt_move_discards_to_top_impl(nir_function_impl *impl)
|
||||
case nir_instr_type_load_const:
|
||||
case nir_instr_type_undef:
|
||||
case nir_instr_type_phi:
|
||||
case nir_instr_type_debug_info:
|
||||
/* These are all safe */
|
||||
continue;
|
||||
|
||||
|
@@ -73,7 +73,6 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count,
|
||||
case nir_instr_type_phi:
|
||||
case nir_instr_type_undef:
|
||||
case nir_instr_type_tex:
|
||||
case nir_instr_type_debug_info:
|
||||
break;
|
||||
|
||||
case nir_instr_type_intrinsic: {
|
||||
@@ -273,9 +272,6 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count,
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_instr_type_debug_info:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@@ -80,7 +80,9 @@ typedef struct {
|
||||
*/
|
||||
unsigned padding_for_no_dest;
|
||||
|
||||
nir_debug_info_instr **debug_info;
|
||||
bool gather_debug_info;
|
||||
|
||||
nir_instr_debug_info last_debug_info;
|
||||
} print_state;
|
||||
|
||||
static void
|
||||
@@ -2009,33 +2011,37 @@ print_parallel_copy_instr(nir_parallel_copy_instr *instr, print_state *state)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_debug_info_instr(nir_debug_info_instr *instr, print_state *state)
|
||||
{
|
||||
FILE *fp = state->fp;
|
||||
|
||||
switch (instr->type) {
|
||||
case nir_debug_info_src_loc:
|
||||
fprintf(fp, "// 0x%x", instr->src_loc.spirv_offset);
|
||||
if (instr->src_loc.line)
|
||||
fprintf(fp, " %s:%u:%u", nir_src_as_string(instr->src_loc.filename), instr->src_loc.line, instr->src_loc.column);
|
||||
return;
|
||||
case nir_debug_info_string:
|
||||
return; /* Strings are printed for their uses. */
|
||||
}
|
||||
|
||||
unreachable("Unimplemented nir_debug_info_type");
|
||||
}
|
||||
|
||||
static void
|
||||
print_instr(const nir_instr *instr, print_state *state, unsigned tabs)
|
||||
{
|
||||
FILE *fp = state->fp;
|
||||
|
||||
if (state->debug_info) {
|
||||
nir_debug_info_instr *di = state->debug_info[instr->index];
|
||||
if (di)
|
||||
di->src_loc.column = (uint32_t)ftell(fp);
|
||||
if (state->gather_debug_info) {
|
||||
nir_instr_debug_info *debug_info = nir_instr_get_debug_info((nir_instr *)instr);
|
||||
debug_info->nir_line = (uint32_t)ftell(fp);
|
||||
}
|
||||
|
||||
if (state->shader->has_debug_info) {
|
||||
nir_instr_debug_info *debug_info = nir_instr_get_debug_info((nir_instr *)instr);
|
||||
|
||||
bool changed = state->last_debug_info.spirv_offset != debug_info->spirv_offset;
|
||||
changed |= state->last_debug_info.nir_line != debug_info->nir_line;
|
||||
|
||||
if (changed && debug_info->spirv_offset) {
|
||||
print_indentation(tabs, fp);
|
||||
|
||||
fprintf(fp, "// 0x%x", debug_info->spirv_offset);
|
||||
|
||||
if (debug_info->filename)
|
||||
fprintf(fp, " %s:%u:%u", debug_info->filename, debug_info->line, debug_info->column);
|
||||
|
||||
if (debug_info->nir_line)
|
||||
fprintf(fp, " nir:%u", debug_info->nir_line);
|
||||
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
state->last_debug_info = *debug_info;
|
||||
}
|
||||
|
||||
print_indentation(tabs, fp);
|
||||
@@ -2081,10 +2087,6 @@ print_instr(const nir_instr *instr, print_state *state, unsigned tabs)
|
||||
print_parallel_copy_instr(nir_instr_as_parallel_copy(instr), state);
|
||||
break;
|
||||
|
||||
case nir_instr_type_debug_info:
|
||||
print_debug_info_instr(nir_instr_as_debug_info(instr), state);
|
||||
break;
|
||||
|
||||
default:
|
||||
unreachable("Invalid instruction type");
|
||||
break;
|
||||
@@ -2120,7 +2122,6 @@ block_has_instruction_with_dest(nir_block *block)
|
||||
|
||||
case nir_instr_type_jump:
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_debug_info:
|
||||
/* Doesn't define a new value. */
|
||||
break;
|
||||
}
|
||||
@@ -2730,13 +2731,13 @@ print_shader_info(const struct shader_info *info, FILE *fp)
|
||||
static void
|
||||
_nir_print_shader_annotated(nir_shader *shader, FILE *fp,
|
||||
struct hash_table *annotations,
|
||||
nir_debug_info_instr **debug_info)
|
||||
bool gather_debug_info)
|
||||
{
|
||||
print_state state;
|
||||
init_print_state(&state, shader, fp);
|
||||
state.def_prefix = debug_info ? "ssa_" : "%";
|
||||
state.def_prefix = gather_debug_info ? "ssa_" : "%";
|
||||
state.annotations = annotations;
|
||||
state.debug_info = debug_info;
|
||||
state.gather_debug_info = gather_debug_info;
|
||||
|
||||
print_shader_info(&shader->info, fp);
|
||||
|
||||
@@ -2781,7 +2782,7 @@ void
|
||||
nir_print_shader_annotated(nir_shader *shader, FILE *fp,
|
||||
struct hash_table *annotations)
|
||||
{
|
||||
_nir_print_shader_annotated(shader, fp, annotations, NULL);
|
||||
_nir_print_shader_annotated(shader, fp, annotations, false);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2793,14 +2794,14 @@ nir_print_shader(nir_shader *shader, FILE *fp)
|
||||
|
||||
static char *
|
||||
_nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx,
|
||||
nir_debug_info_instr **debug_info)
|
||||
bool gather_debug_info)
|
||||
{
|
||||
char *stream_data = NULL;
|
||||
size_t stream_size = 0;
|
||||
struct u_memstream mem;
|
||||
if (u_memstream_open(&mem, &stream_data, &stream_size)) {
|
||||
FILE *const stream = u_memstream_get(&mem);
|
||||
_nir_print_shader_annotated(nir, stream, annotations, debug_info);
|
||||
_nir_print_shader_annotated(nir, stream, annotations, gather_debug_info);
|
||||
u_memstream_close(&mem);
|
||||
}
|
||||
|
||||
@@ -2816,7 +2817,7 @@ _nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, vo
|
||||
char *
|
||||
nir_shader_as_str_annotated(nir_shader *nir, struct hash_table *annotations, void *mem_ctx)
|
||||
{
|
||||
return _nir_shader_as_str_annotated(nir, annotations, mem_ctx, NULL);
|
||||
return _nir_shader_as_str_annotated(nir, annotations, mem_ctx, false);
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -2883,67 +2884,25 @@ nir_log_shader_annotated_tagged(enum mesa_log_level level, const char *tag,
|
||||
char *
|
||||
nir_shader_gather_debug_info(nir_shader *shader, const char *filename, uint32_t first_line)
|
||||
{
|
||||
uint32_t instr_count = 0;
|
||||
nir_foreach_function_impl(impl, shader) {
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr(instr, block) {
|
||||
instr->index = instr_count;
|
||||
instr_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
char *str = _nir_shader_as_str_annotated(shader, NULL, NULL, shader->has_debug_info);
|
||||
|
||||
if (!instr_count)
|
||||
return nir_shader_as_str(shader, NULL);
|
||||
|
||||
nir_debug_info_instr **debug_info = rzalloc_array(shader, nir_debug_info_instr *, instr_count);
|
||||
|
||||
instr_count = 0;
|
||||
nir_foreach_function_impl(impl, shader) {
|
||||
nir_builder b = nir_builder_at(nir_before_cf_list(&impl->body));
|
||||
nir_def *filename_def = nir_build_string(&b, filename);
|
||||
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
if (instr->type == nir_instr_type_debug_info ||
|
||||
instr->type == nir_instr_type_phi)
|
||||
continue;
|
||||
|
||||
nir_debug_info_instr *di = nir_debug_info_instr_create(shader, nir_debug_info_src_loc, 0);
|
||||
di->src_loc.filename = nir_src_for_ssa(filename_def);
|
||||
di->src_loc.source = nir_debug_info_nir;
|
||||
debug_info[instr_count++] = di;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *str = _nir_shader_as_str_annotated(shader, NULL, NULL, debug_info);
|
||||
if (!shader->has_debug_info)
|
||||
return str;
|
||||
|
||||
uint32_t line = first_line;
|
||||
uint32_t character_index = 0;
|
||||
|
||||
for (uint32_t i = 0; i < instr_count; i++) {
|
||||
nir_debug_info_instr *di = debug_info[i];
|
||||
if (!di)
|
||||
continue;
|
||||
|
||||
while (character_index < di->src_loc.column) {
|
||||
if (str[character_index] == '\n')
|
||||
line++;
|
||||
character_index++;
|
||||
}
|
||||
|
||||
di->src_loc.line = line;
|
||||
di->src_loc.column = 0;
|
||||
}
|
||||
|
||||
instr_count = 0;
|
||||
nir_foreach_function_impl(impl, shader) {
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
if (instr->type != nir_instr_type_debug_info &&
|
||||
instr->type != nir_instr_type_phi)
|
||||
nir_instr_insert_before(instr, &debug_info[instr_count++]->instr);
|
||||
nir_instr_debug_info *di = nir_instr_get_debug_info(instr);
|
||||
while (character_index < di->nir_line) {
|
||||
if (str[character_index] == '\n')
|
||||
line++;
|
||||
character_index++;
|
||||
}
|
||||
|
||||
di->nir_line = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -126,7 +126,6 @@ propagate_invariant_instr(nir_instr *instr, struct set *invariants)
|
||||
case nir_instr_type_jump:
|
||||
case nir_instr_type_undef:
|
||||
case nir_instr_type_load_const:
|
||||
case nir_instr_type_debug_info:
|
||||
break; /* Nothing to do */
|
||||
|
||||
case nir_instr_type_phi: {
|
||||
|
@@ -462,7 +462,6 @@ nir_schedule_calculate_deps(nir_deps_state *state, nir_schedule_node *n)
|
||||
case nir_instr_type_load_const:
|
||||
case nir_instr_type_alu:
|
||||
case nir_instr_type_deref:
|
||||
case nir_instr_type_debug_info:
|
||||
break;
|
||||
|
||||
case nir_instr_type_tex:
|
||||
@@ -1096,7 +1095,6 @@ nir_schedule_get_delay(nir_schedule_scoreboard *scoreboard, nir_instr *instr)
|
||||
case nir_instr_type_parallel_copy:
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_phi:
|
||||
case nir_instr_type_debug_info:
|
||||
return 1;
|
||||
|
||||
case nir_instr_type_intrinsic:
|
||||
|
@@ -64,6 +64,7 @@ typedef struct {
|
||||
|
||||
/* Don't write optional data such as variable names. */
|
||||
bool strip;
|
||||
bool debug_info;
|
||||
} write_ctx;
|
||||
|
||||
typedef struct {
|
||||
@@ -87,6 +88,8 @@ typedef struct {
|
||||
const struct glsl_type *last_type;
|
||||
const struct glsl_type *last_interface_type;
|
||||
struct nir_variable_data last_var_data;
|
||||
|
||||
struct hash_table *strings;
|
||||
} read_ctx;
|
||||
|
||||
static void
|
||||
@@ -615,7 +618,7 @@ write_def(write_ctx *ctx, const nir_def *def, union packed_instr header,
|
||||
* instruction that is also ALU. If it is, we don't have to write
|
||||
* the current header. This is a typical occurence after scalarization.
|
||||
*/
|
||||
if (instr_type == nir_instr_type_alu) {
|
||||
if (instr_type == nir_instr_type_alu && likely(!ctx->debug_info)) {
|
||||
bool equal_header = false;
|
||||
|
||||
if (ctx->last_instr_type == nir_instr_type_alu) {
|
||||
@@ -1603,60 +1606,44 @@ read_call(read_ctx *ctx)
|
||||
}
|
||||
|
||||
static void
|
||||
write_debug_info(write_ctx *ctx, const nir_debug_info_instr *di)
|
||||
write_debug_info(write_ctx *ctx, const nir_instr *instr)
|
||||
{
|
||||
union packed_instr header;
|
||||
header.u32 = 0;
|
||||
nir_instr_debug_info *debug_info = nir_instr_get_debug_info((void *)instr);
|
||||
|
||||
header.debug_info.instr_type = nir_instr_type_debug_info;
|
||||
header.debug_info.type = di->type;
|
||||
header.debug_info.string_length = di->string_length;
|
||||
blob_write_uint32(ctx->blob, debug_info->line);
|
||||
blob_write_uint32(ctx->blob, debug_info->column);
|
||||
blob_write_uint32(ctx->blob, debug_info->spirv_offset);
|
||||
|
||||
switch (di->type) {
|
||||
case nir_debug_info_src_loc:
|
||||
blob_write_uint32(ctx->blob, header.u32);
|
||||
blob_write_uint32(ctx->blob, di->src_loc.line);
|
||||
blob_write_uint32(ctx->blob, di->src_loc.column);
|
||||
blob_write_uint32(ctx->blob, di->src_loc.spirv_offset);
|
||||
blob_write_uint8(ctx->blob, di->src_loc.source);
|
||||
if (di->src_loc.line)
|
||||
write_src(ctx, &di->src_loc.filename);
|
||||
return;
|
||||
case nir_debug_info_string:
|
||||
write_def(ctx, &di->def, header, di->instr.type);
|
||||
blob_write_bytes(ctx->blob, di->string, di->string_length);
|
||||
return;
|
||||
}
|
||||
blob_write_uint32(ctx->blob, debug_info->nir_line);
|
||||
|
||||
unreachable("Unimplemented nir_debug_info_type");
|
||||
blob_write_uint8(ctx->blob, !!debug_info->filename);
|
||||
if (debug_info->filename)
|
||||
blob_write_string(ctx->blob, debug_info->filename);
|
||||
}
|
||||
|
||||
static nir_debug_info_instr *
|
||||
read_debug_info(read_ctx *ctx, union packed_instr header)
|
||||
static void
|
||||
read_debug_info(read_ctx *ctx, nir_instr_debug_info *debug_info)
|
||||
{
|
||||
nir_debug_info_type type = header.debug_info.type;
|
||||
memset(debug_info, 0, sizeof(*debug_info));
|
||||
|
||||
switch (type) {
|
||||
case nir_debug_info_src_loc: {
|
||||
nir_debug_info_instr *di = nir_debug_info_instr_create(ctx->nir, type, 0);
|
||||
di->src_loc.line = blob_read_uint32(ctx->blob);
|
||||
di->src_loc.column = blob_read_uint32(ctx->blob);
|
||||
di->src_loc.spirv_offset = blob_read_uint32(ctx->blob);
|
||||
di->src_loc.source = blob_read_uint8(ctx->blob);
|
||||
if (di->src_loc.line)
|
||||
read_src(ctx, &di->src_loc.filename);
|
||||
return di;
|
||||
}
|
||||
case nir_debug_info_string: {
|
||||
nir_debug_info_instr *di =
|
||||
nir_debug_info_instr_create(ctx->nir, type, header.debug_info.string_length);
|
||||
read_def(ctx, &di->def, &di->instr, header);
|
||||
memcpy(di->string, blob_read_bytes(ctx->blob, di->string_length), di->string_length);
|
||||
return di;
|
||||
}
|
||||
}
|
||||
debug_info->line = blob_read_uint32(ctx->blob);
|
||||
debug_info->column = blob_read_uint32(ctx->blob);
|
||||
debug_info->spirv_offset = blob_read_uint32(ctx->blob);
|
||||
|
||||
unreachable("Unimplemented nir_debug_info_type");
|
||||
debug_info->nir_line = blob_read_uint32(ctx->blob);
|
||||
|
||||
bool has_filename = blob_read_uint8(ctx->blob);
|
||||
if (has_filename) {
|
||||
const char *filename = blob_read_string(ctx->blob);
|
||||
|
||||
struct hash_entry *entry = _mesa_hash_table_search(ctx->strings, filename);
|
||||
if (entry) {
|
||||
debug_info->filename = entry->data;
|
||||
} else {
|
||||
debug_info->filename = ralloc_strdup(ctx->nir, filename);
|
||||
_mesa_hash_table_insert(ctx->strings, filename, debug_info->filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1665,6 +1652,9 @@ write_instr(write_ctx *ctx, const nir_instr *instr)
|
||||
/* We have only 4 bits for the instruction type. */
|
||||
assert(instr->type < 16);
|
||||
|
||||
if (unlikely(ctx->debug_info))
|
||||
write_debug_info(ctx, instr);
|
||||
|
||||
switch (instr->type) {
|
||||
case nir_instr_type_alu:
|
||||
write_alu(ctx, nir_instr_as_alu(instr));
|
||||
@@ -1694,9 +1684,6 @@ write_instr(write_ctx *ctx, const nir_instr *instr)
|
||||
blob_write_uint32(ctx->blob, instr->type);
|
||||
write_call(ctx, nir_instr_as_call(instr));
|
||||
break;
|
||||
case nir_instr_type_debug_info:
|
||||
write_debug_info(ctx, nir_instr_as_debug_info(instr));
|
||||
break;
|
||||
case nir_instr_type_parallel_copy:
|
||||
unreachable("Cannot write parallel copies");
|
||||
default:
|
||||
@@ -1708,6 +1695,10 @@ write_instr(write_ctx *ctx, const nir_instr *instr)
|
||||
static unsigned
|
||||
read_instr(read_ctx *ctx, nir_block *block)
|
||||
{
|
||||
nir_instr_debug_info debug_info;
|
||||
if (unlikely(ctx->nir->has_debug_info))
|
||||
read_debug_info(ctx, &debug_info);
|
||||
|
||||
STATIC_ASSERT(sizeof(union packed_instr) == 4);
|
||||
union packed_instr header;
|
||||
header.u32 = blob_read_uint32(ctx->blob);
|
||||
@@ -1747,15 +1738,17 @@ read_instr(read_ctx *ctx, nir_block *block)
|
||||
case nir_instr_type_call:
|
||||
instr = &read_call(ctx)->instr;
|
||||
break;
|
||||
case nir_instr_type_debug_info:
|
||||
instr = &read_debug_info(ctx, header)->instr;
|
||||
break;
|
||||
case nir_instr_type_parallel_copy:
|
||||
unreachable("Cannot read parallel copies");
|
||||
default:
|
||||
unreachable("bad instr type");
|
||||
}
|
||||
|
||||
if (unlikely(ctx->nir->has_debug_info)) {
|
||||
nir_instr_debug_info *dst = nir_instr_get_debug_info(instr);
|
||||
memcpy(dst, &debug_info, offsetof(nir_instr_debug_info, instr));
|
||||
}
|
||||
|
||||
nir_instr_insert_after_block(block, instr);
|
||||
return 1;
|
||||
}
|
||||
@@ -2101,6 +2094,12 @@ read_xfb_info(read_ctx *ctx)
|
||||
return xfb;
|
||||
}
|
||||
|
||||
enum nir_serialize_shader_flags {
|
||||
NIR_SERIALIZE_SHADER_NAME = 1 << 0,
|
||||
NIR_SERIALIZE_SHADER_LABEL = 1 << 1,
|
||||
NIR_SERIALIZE_DEBUG_INFO = 1 << 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize NIR into a binary blob.
|
||||
*
|
||||
@@ -2116,17 +2115,22 @@ nir_serialize(struct blob *blob, const nir_shader *nir, bool strip)
|
||||
ctx.blob = blob;
|
||||
ctx.nir = nir;
|
||||
ctx.strip = strip;
|
||||
ctx.debug_info = nir->has_debug_info && !strip;
|
||||
util_dynarray_init(&ctx.phi_fixups, NULL);
|
||||
|
||||
size_t idx_size_offset = blob_reserve_uint32(blob);
|
||||
|
||||
struct shader_info info = nir->info;
|
||||
uint32_t strings = 0;
|
||||
|
||||
enum nir_serialize_shader_flags flags = 0;
|
||||
if (!strip && info.name)
|
||||
strings |= 0x1;
|
||||
flags |= NIR_SERIALIZE_SHADER_NAME;
|
||||
if (!strip && info.label)
|
||||
strings |= 0x2;
|
||||
blob_write_uint32(blob, strings);
|
||||
flags |= NIR_SERIALIZE_SHADER_LABEL;
|
||||
if (ctx.debug_info)
|
||||
flags |= NIR_SERIALIZE_DEBUG_INFO;
|
||||
blob_write_uint32(blob, flags);
|
||||
|
||||
if (!strip && info.name)
|
||||
blob_write_string(blob, info.name);
|
||||
if (!strip && info.label)
|
||||
@@ -2176,15 +2180,19 @@ nir_deserialize(void *mem_ctx,
|
||||
ctx.idx_table_len = blob_read_uint32(blob);
|
||||
ctx.idx_table = calloc(ctx.idx_table_len, sizeof(uintptr_t));
|
||||
|
||||
uint32_t strings = blob_read_uint32(blob);
|
||||
char *name = (strings & 0x1) ? blob_read_string(blob) : NULL;
|
||||
char *label = (strings & 0x2) ? blob_read_string(blob) : NULL;
|
||||
enum nir_serialize_shader_flags flags = blob_read_uint32(blob);
|
||||
char *name = (flags & NIR_SERIALIZE_SHADER_NAME) ? blob_read_string(blob) : NULL;
|
||||
char *label = (flags & NIR_SERIALIZE_SHADER_LABEL) ? blob_read_string(blob) : NULL;
|
||||
|
||||
struct shader_info info;
|
||||
blob_copy_bytes(blob, (uint8_t *)&info, sizeof(info));
|
||||
|
||||
ctx.nir = nir_shader_create(mem_ctx, info.stage, options, NULL);
|
||||
|
||||
ctx.nir->has_debug_info = !!(flags & NIR_SERIALIZE_DEBUG_INFO);
|
||||
if (ctx.nir->has_debug_info)
|
||||
ctx.strings = _mesa_hash_table_create(NULL, _mesa_hash_string, _mesa_key_string_equal);
|
||||
|
||||
info.name = name ? ralloc_strdup(ctx.nir, name) : NULL;
|
||||
info.label = label ? ralloc_strdup(ctx.nir, label) : NULL;
|
||||
|
||||
@@ -2223,6 +2231,7 @@ nir_deserialize(void *mem_ctx,
|
||||
}
|
||||
|
||||
free(ctx.idx_table);
|
||||
_mesa_hash_table_destroy(ctx.strings, NULL);
|
||||
|
||||
nir_validate_shader(ctx.nir, "after deserialize");
|
||||
|
||||
|
@@ -1156,9 +1156,6 @@ validate_instr(nir_instr *instr, validate_state *state)
|
||||
validate_jump_instr(nir_instr_as_jump(instr), state);
|
||||
break;
|
||||
|
||||
case nir_instr_type_debug_info:
|
||||
break;
|
||||
|
||||
default:
|
||||
validate_assert(state, !"Invalid ALU instruction type");
|
||||
break;
|
||||
|
@@ -6119,31 +6119,27 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
|
||||
const uint32_t *w, unsigned count)
|
||||
{
|
||||
if (b->options->debug_info) {
|
||||
nir_debug_info_instr *instr =
|
||||
nir_debug_info_instr_create(b->shader, nir_debug_info_src_loc, 0);
|
||||
instr->src_loc.spirv_offset = b->spirv_offset;
|
||||
instr->src_loc.source = nir_debug_info_spirv;
|
||||
/* Insert a nop to attach debug info to the cursor of the builder.
|
||||
* This should not affect compilation since the nop will be eliminated
|
||||
* in spirv_to_nir.
|
||||
*/
|
||||
nir_intrinsic_instr *nop = nir_nop(&b->nb);
|
||||
|
||||
nir_instr_debug_info *info = nir_instr_get_debug_info(&nop->instr);
|
||||
info->spirv_offset = b->spirv_offset;
|
||||
|
||||
if (b->file) {
|
||||
nir_def *filename;
|
||||
struct hash_entry *he = _mesa_hash_table_search(b->strings, b->file);
|
||||
if (he) {
|
||||
filename = he->data;
|
||||
info->filename = he->data;
|
||||
} else {
|
||||
nir_builder _b = nir_builder_at(nir_before_cf_list(&b->nb.impl->body));
|
||||
filename = nir_build_string(&_b, b->file);
|
||||
_mesa_hash_table_insert(b->strings, b->file, filename);
|
||||
info->filename = ralloc_strdup(b->shader, b->file);
|
||||
_mesa_hash_table_insert(b->strings, b->file, info->filename);
|
||||
}
|
||||
|
||||
instr->src_loc.filename = nir_src_for_ssa(filename);
|
||||
/* Make sure line is at least 1 since 0 is reserved for spirv_offset-only
|
||||
* source locations.
|
||||
*/
|
||||
instr->src_loc.line = MAX2(b->line, 1);
|
||||
instr->src_loc.column = b->col;
|
||||
info->line = b->line;
|
||||
info->column = b->col;
|
||||
}
|
||||
|
||||
nir_builder_instr_insert(&b->nb, &instr->instr);
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
@@ -6929,6 +6925,7 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
|
||||
b->shader->info.subgroup_size = options->subgroup_size;
|
||||
b->shader->info.float_controls_execution_mode = options->float_controls_execution_mode;
|
||||
b->shader->info.cs.shader_index = options->shader_index;
|
||||
b->shader->has_debug_info = options->debug_info;
|
||||
_mesa_blake3_compute(words, word_count * sizeof(uint32_t), b->shader->info.source_blake3);
|
||||
|
||||
/* Skip the SPIR-V header, handled at vtn_create_builder */
|
||||
@@ -7167,6 +7164,9 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
|
||||
nir_shader *shader = b->shader;
|
||||
ralloc_free(b);
|
||||
|
||||
if (shader->has_debug_info)
|
||||
nir_print_shader(shader, stdout);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@@ -4286,7 +4286,6 @@ emit_instr(struct ir3_context *ctx, nir_instr *instr)
|
||||
break;
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_parallel_copy:
|
||||
case nir_instr_type_debug_info:
|
||||
ir3_context_error(ctx, "Unhandled NIR instruction type: %d\n",
|
||||
instr->type);
|
||||
break;
|
||||
@@ -4463,7 +4462,6 @@ instr_can_be_predicated(nir_instr *instr)
|
||||
return true;
|
||||
case nir_instr_type_call:
|
||||
case nir_instr_type_jump:
|
||||
case nir_instr_type_debug_info:
|
||||
return false;
|
||||
case nir_instr_type_intrinsic: {
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
|
@@ -4173,9 +4173,6 @@ emit_block(struct ntv_context *ctx, struct nir_block *block)
|
||||
case nir_instr_type_deref:
|
||||
emit_deref(ctx, nir_instr_as_deref(instr));
|
||||
break;
|
||||
case nir_instr_type_debug_info:
|
||||
unreachable("nir_instr_type_debug_info not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user