diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c index dd638c3e64c..2b0ff6ec079 100644 --- a/src/broadcom/compiler/vir.c +++ b/src/broadcom/compiler/vir.c @@ -1315,6 +1315,9 @@ 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; diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 29d1f5003fb..58a52436823 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -880,6 +880,26 @@ nir_parallel_copy_instr_create(nir_shader *shader) 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, @@ -1331,6 +1351,7 @@ nir_instr_def(nir_instr *instr) case nir_instr_type_call: case nir_instr_type_jump: + case nir_instr_type_debug_info: return NULL; } @@ -1401,6 +1422,16 @@ 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 diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 251630c9e2a..04ddfa25f4c 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -959,6 +959,7 @@ 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 { @@ -2760,6 +2761,41 @@ 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; + +typedef enum nir_debug_info_source { + nir_debug_info_spirv, + nir_debug_info_nir, +} nir_debug_info_source; + +typedef struct nir_debug_info_instr { + 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_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr, type, nir_instr_type_alu) NIR_DEFINE_CAST(nir_instr_as_deref, nir_instr, nir_deref_instr, instr, @@ -2781,6 +2817,9 @@ 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 \ @@ -4584,6 +4623,10 @@ 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); @@ -4893,6 +4936,9 @@ 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); bool nir_src_is_always_uniform(nir_src src); bool nir_srcs_equal(nir_src src1, nir_src src2); diff --git a/src/compiler/nir/nir_builder.c b/src/compiler/nir/nir_builder.c index 8a7b9d9c251..38fce33d1ca 100644 --- a/src/compiler/nir/nir_builder.c +++ b/src/compiler/nir/nir_builder.c @@ -312,6 +312,17 @@ 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) { diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 61e757023ad..90213f9dbaf 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -2262,6 +2262,9 @@ nir_discard_if(nir_builder *build, nir_def *src) nir_terminate_if(build, src); } +nir_def * +nir_build_string(nir_builder *build, const char *value); + /* * Call a given nir_function * with a variadic number of nir_def * arguments. * diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c index 493fbe20119..c41318fab56 100644 --- a/src/compiler/nir/nir_clone.c +++ b/src/compiler/nir/nir_clone.c @@ -424,6 +424,30 @@ 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) { @@ -446,6 +470,8 @@ 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: diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index c6cf2e3866c..80adef863ba 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -979,6 +979,8 @@ 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_jump: case nir_instr_type_phi: case nir_instr_type_call: diff --git a/src/compiler/nir/nir_inline_helpers.h b/src/compiler/nir/nir_inline_helpers.h index d4f0303c439..8f3994f5353 100644 --- a/src/compiler/nir/nir_inline_helpers.h +++ b/src/compiler/nir/nir_inline_helpers.h @@ -32,6 +32,13 @@ _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; @@ -132,6 +139,15 @@ 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; diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c index 994be6fbc48..c9490b13b30 100644 --- a/src/compiler/nir/nir_instr_set.c +++ b/src/compiler/nir/nir_instr_set.c @@ -62,6 +62,8 @@ 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: @@ -265,6 +267,13 @@ 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 @@ -296,6 +305,9 @@ 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"); } @@ -707,6 +719,16 @@ 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: @@ -734,6 +756,8 @@ nir_instr_get_def_def(nir_instr *instr) return &nir_instr_as_intrinsic(instr)->def; case nir_instr_type_tex: return &nir_instr_as_tex(instr)->def; + case nir_instr_type_debug_info: + return &nir_instr_as_debug_info(instr)->def; default: unreachable("We never ask for any of these"); } diff --git a/src/compiler/nir/nir_opt_dce.c b/src/compiler/nir/nir_opt_dce.c index ab2642b29fd..5b2f18c2a5c 100644 --- a/src/compiler/nir/nir_opt_dce.c +++ b/src/compiler/nir/nir_opt_dce.c @@ -96,6 +96,16 @@ 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"); } diff --git a/src/compiler/nir/nir_opt_move_discards_to_top.c b/src/compiler/nir/nir_opt_move_discards_to_top.c index f70a2807337..47906cec0f3 100644 --- a/src/compiler/nir/nir_opt_move_discards_to_top.c +++ b/src/compiler/nir/nir_opt_move_discards_to_top.c @@ -144,6 +144,7 @@ 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; diff --git a/src/compiler/nir/nir_opt_peephole_select.c b/src/compiler/nir/nir_opt_peephole_select.c index add370c4340..202f84a18ff 100644 --- a/src/compiler/nir/nir_opt_peephole_select.c +++ b/src/compiler/nir/nir_opt_peephole_select.c @@ -73,6 +73,7 @@ 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: { @@ -270,6 +271,9 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count, break; } + case nir_instr_type_debug_info: + break; + default: return false; } diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 3573b752c8b..3e4877e6f80 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -1972,6 +1972,24 @@ 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) { @@ -2019,6 +2037,10 @@ 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; @@ -2054,6 +2076,7 @@ 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; } diff --git a/src/compiler/nir/nir_propagate_invariant.c b/src/compiler/nir/nir_propagate_invariant.c index abf9e5fb664..9a6e91f9ef6 100644 --- a/src/compiler/nir/nir_propagate_invariant.c +++ b/src/compiler/nir/nir_propagate_invariant.c @@ -126,6 +126,7 @@ 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: { diff --git a/src/compiler/nir/nir_schedule.c b/src/compiler/nir/nir_schedule.c index c89099b00dd..4190a06ac29 100644 --- a/src/compiler/nir/nir_schedule.c +++ b/src/compiler/nir/nir_schedule.c @@ -460,6 +460,7 @@ 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: @@ -1093,6 +1094,7 @@ 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: diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index d574050c3c9..943c51944c0 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -587,6 +587,12 @@ union packed_instr { unsigned type : 2; unsigned _pad : 26; } jump; + struct { + unsigned instr_type : 4; + unsigned type : 4; + unsigned string_length : 16; + unsigned def : 8; + } debug_info; }; /* Write "lo24" as low 24 bits in the first uint32. */ @@ -1592,6 +1598,63 @@ read_call(read_ctx *ctx) return call; } +static void +write_debug_info(write_ctx *ctx, const nir_debug_info_instr *di) +{ + union packed_instr header; + header.u32 = 0; + + header.debug_info.instr_type = nir_instr_type_debug_info; + header.debug_info.type = di->type; + header.debug_info.string_length = di->string_length; + + 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; + } + + unreachable("Unimplemented nir_debug_info_type"); +} + +static nir_debug_info_instr * +read_debug_info(read_ctx *ctx, union packed_instr header) +{ + nir_debug_info_type type = header.debug_info.type; + + 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; + } + } + + unreachable("Unimplemented nir_debug_info_type"); +} + static void write_instr(write_ctx *ctx, const nir_instr *instr) { @@ -1627,6 +1690,9 @@ 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: @@ -1677,6 +1743,9 @@ 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: diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 93d169be39f..ee2c9cd32c4 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -1145,6 +1145,9 @@ 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; diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 3b87d9e43bd..23d54eb2a13 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -4102,6 +4102,7 @@ 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; @@ -4278,6 +4279,7 @@ 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); diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 1f7eb5dd0cd..ee93546cac3 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -4122,6 +4122,9 @@ 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; } } }