diff --git a/src/nouveau/compiler/meson.build b/src/nouveau/compiler/meson.build index 1b7aeb1b6b4..1960e77aa7a 100644 --- a/src/nouveau/compiler/meson.build +++ b/src/nouveau/compiler/meson.build @@ -39,6 +39,7 @@ libnak_c_files = files( 'nak_nir_lower_tex.c', 'nak_nir_lower_vtg_io.c', 'nak_nir_lower_gs_intrinsics.c', + 'nak_memstream.c', ) _libbitview_rs = static_library( diff --git a/src/nouveau/compiler/nak/from_nir.rs b/src/nouveau/compiler/nak/from_nir.rs index f89f2842bcc..3cf85f1b17f 100644 --- a/src/nouveau/compiler/nak/from_nir.rs +++ b/src/nouveau/compiler/nak/from_nir.rs @@ -6,6 +6,7 @@ use crate::cfg::CFGBuilder; use crate::ir::*; use crate::nir::*; +use crate::nir_instr_printer::NirInstrPrinter; use crate::sph::{OutputTopology, PixelImap}; use nak_bindings::*; @@ -239,6 +240,7 @@ struct ShaderFromNir<'a> { end_block_id: u32, ssa_map: HashMap>, saturated: HashSet<*const nir_def>, + nir_instr_printer: NirInstrPrinter, } impl<'a> ShaderFromNir<'a> { @@ -255,6 +257,7 @@ impl<'a> ShaderFromNir<'a> { end_block_id: 0, ssa_map: HashMap::new(), saturated: HashSet::new(), + nir_instr_printer: NirInstrPrinter::new(), } } diff --git a/src/nouveau/compiler/nak/lib.rs b/src/nouveau/compiler/nak/lib.rs index d0053679bc5..7e5a39a8526 100644 --- a/src/nouveau/compiler/nak/lib.rs +++ b/src/nouveau/compiler/nak/lib.rs @@ -16,6 +16,7 @@ mod liveness; mod lower_copy_swap; mod lower_par_copies; mod nir; +mod nir_instr_printer; mod opt_bar_prop; mod opt_copy_prop; mod opt_dce; diff --git a/src/nouveau/compiler/nak/nir_instr_printer.rs b/src/nouveau/compiler/nak/nir_instr_printer.rs new file mode 100644 index 00000000000..bfd21e778d2 --- /dev/null +++ b/src/nouveau/compiler/nak/nir_instr_printer.rs @@ -0,0 +1,50 @@ +// Copyright © 2024 Collabora, Ltd. +// SPDX-License-Identifier: MIT + +use std::pin::Pin; + +use nak_bindings::nak_clear_memstream; +use nak_bindings::nak_close_memstream; +use nak_bindings::nak_memstream; +use nak_bindings::nak_nir_asprint_instr; +use nak_bindings::nak_open_memstream; +use nak_bindings::nir_instr; + +/// A memstream that holds the printed NIR instructions. +pub struct NirInstrPrinter { + // XXX: we need this to be pinned because we've passed references to its + // fields when calling open_memstream. + stream: Pin>, +} + +impl NirInstrPrinter { + pub fn new() -> Self { + let mut stream = + Box::pin(unsafe { std::mem::zeroed::() }); + unsafe { + nak_open_memstream(stream.as_mut().get_unchecked_mut()); + } + Self { stream } + } + + /// Prints the given NIR instruction. + pub fn instr_to_string(&mut self, instr: &nir_instr) -> String { + unsafe { + let stream = self.stream.as_mut().get_unchecked_mut(); + nak_nir_asprint_instr(stream, instr); + let c_str = std::ffi::CStr::from_ptr(stream.buffer); + let string = c_str.to_string_lossy().into_owned(); + nak_clear_memstream(stream); + string + } + } +} + +impl Drop for NirInstrPrinter { + fn drop(&mut self) { + unsafe { + let stream = self.stream.as_mut().get_unchecked_mut(); + nak_close_memstream(stream) + } + } +} diff --git a/src/nouveau/compiler/nak_memstream.c b/src/nouveau/compiler/nak_memstream.c new file mode 100644 index 00000000000..b3b0b3ac9a8 --- /dev/null +++ b/src/nouveau/compiler/nak_memstream.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2024 Collabora, Ltd. + * SPDX-License-Identifier: MIT + * + * This file exposes a nice interface that can be consumed from Rust. We would + * have to have Rust libc bindings otherwise. + */ + +#include +#include +#include + +#include "nak_private.h" +#include "nir.h" + +void nak_open_memstream(struct nak_memstream *memstream) +{ + memstream->stream = open_memstream(&memstream->buffer, &memstream->written); + fflush(memstream->stream); + assert(memstream->stream); + assert(memstream->buffer); +} + +void nak_close_memstream(struct nak_memstream *memstream) +{ + fclose(memstream->stream); + free(memstream->buffer); +} + +void nak_nir_asprint_instr(struct nak_memstream *memstream, const nir_instr *instr) +{ + nir_print_instr(instr, memstream->stream); + fflush(memstream->stream); +} + +void nak_clear_memstream(struct nak_memstream *memstream) +{ + rewind(memstream->stream); +} \ No newline at end of file diff --git a/src/nouveau/compiler/nak_private.h b/src/nouveau/compiler/nak_private.h index 3c487b89223..877e875dee7 100644 --- a/src/nouveau/compiler/nak_private.h +++ b/src/nouveau/compiler/nak_private.h @@ -205,6 +205,18 @@ bool nak_nir_add_barriers(nir_shader *nir, const struct nak_compiler *nak); #define NAK_FS_OUT_COLOR(n) (NAK_FS_OUT_COLOR0 + (n) * 16) +struct nak_memstream { + FILE *stream; + char *buffer; + size_t written; +}; + +void nak_open_memstream(struct nak_memstream *memstream); +void nak_close_memstream(struct nak_memstream *memstream); +void nak_flush_memstream(struct nak_memstream *memstream); +void nak_clear_memstream(struct nak_memstream *memstream); +void nak_nir_asprint_instr(struct nak_memstream *memstream, const nir_instr *instr); + #ifdef __cplusplus } #endif