All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alice Ryhl <aliceryhl@google.com>
To: Timur Tabi <ttabi@nvidia.com>
Cc: Miguel Ojeda <ojeda@kernel.org>,
	lossin@kernel.org, Danilo Krummrich <dakr@kernel.org>,
	 rust-for-linux@vger.kernel.org
Subject: Re: [PATCH] [v2] rust: introduce sfile macro for succinct code tracing
Date: Wed, 4 Jun 2025 09:00:20 +0000	[thread overview]
Message-ID: <aEALJCHeJ6GLnaxo@google.com> (raw)
In-Reply-To: <20250603195426.2360773-1-ttabi@nvidia.com>

On Tue, Jun 03, 2025 at 02:54:26PM -0500, Timur Tabi wrote:
> Introduce the sfile (short file) macro that returns the stem of
> the current source file filename.
> 
> Rust provides a file!() macro that is similar to C's __FILE__ predefined
> macro.  Unlike __FILE__, however, file!() returns a full path, which is
> klunky when used for debug traces such as
> 
> 	pr_info!("{}:{}\n", file!(), line!());
> 
> sfile!() can be used in situations instead, to provide a more compact
> print.  For example, if file!() returns "rust/kernel/print.rs", sfile!()
> returns just "print".
> 
> The macro avoids str::rfind() because currently, that function is not
> const.  The compiler emits a call to memrchr, even when called on string
> literals.  Instead, the macro implements its own versions of rfind(),
> allowing the compiler to generate the slice at compile time.
> 
> The macro also uses some unsafe functions in order to avoid indexing
> into a str, which apparently is not completely a const operation.
> 
> Signed-off-by: Timur Tabi <ttabi@nvidia.com>

What is the use-case for this macro?

>  rust/kernel/print.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
> 
> diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
> index cf4714242e14..1fd1497af887 100644
> --- a/rust/kernel/print.rs
> +++ b/rust/kernel/print.rs
> @@ -414,3 +414,66 @@ macro_rules! pr_cont (
>          $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
>      )
>  );
> +
> +/// Returns just the base filename of the current file.  This differs from the
> +/// built-in file!() macro, which returns the full path of the current file.
> +/// Using the base filename gives you more succinct logging prints.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// pr_err!("{}:{}\n", sfile!(), line!());
> +/// ```
> +#[macro_export]
> +macro_rules! sfile {
> +    () => {{
> +        const FILE: &str = file!();
> +        assert!(FILE.is_ascii()); // .as_bytes() does not support non-ascii filenames
> +
> +        // Return the index of the last occurrence of `needle` in `haystack`,
> +        // or zero if not found.  We can't use rfind() because it's not const (yet).
> +        // Avoiding rfind() allows this macro to be evaluated at compile time.
> +        const fn find_last_or_zero(haystack: &str, needle: char) -> usize {
> +            let bytes = haystack.as_bytes();
> +            let mut i = haystack.len();
> +            while i > 0 {
> +                i -= 1;
> +                if bytes[i] == needle as u8 {
> +                    return i;
> +                }
> +            }
> +            0
> +        }
> +
> +        // Return the index of the last occurrence of `needle` in `haystack`,
> +        // or the length of the string if not found.
> +        const fn find_last_or_len(haystack: &str, needle: char) -> usize {
> +            let len = haystack.len();
> +            let bytes = haystack.as_bytes();
> +            let mut i = len;
> +            while i > 0 {
> +                i -= 1;
> +                if bytes[i] == needle as u8 {
> +                    return i;
> +                }
> +            }
> +            len
> +        }
> +        let start = find_last_or_zero(FILE, '/') + 1;

Is plus one really correct when this returns zero?

> +        let end = find_last_or_len(FILE, '.');

I'm thinking that you should only have one method here returning Option,
and that the two calls should match on the Option.

let start = match find_last(FILE, '/') {
    Some(slash) => slash + 1,
    None => 0,
};
let end = match find_last(FILE, '.') {
    Some(dot) => dot,
    None => FILE.len(),
};

> +
> +        // We use these unsafe functions because apparently indexing into
> +        // a string using normal Rust methods is not completely const operation.
> +
> +        let base_ptr: *const u8 = FILE.as_ptr();
> +        // SAFETY: We know that `start` is <= the length of FILE, because FILE
> +        // never ends in a slash.
> +        let ptr: *const u8 = unsafe { base_ptr.add(start) };
> +        // SAFETY: We also know that `end` < the length of FILE.
> +        // If `end` < `start`, this will generate a compiler error.
> +        let slice = unsafe { core::slice::from_raw_parts(ptr, end - start) };
> +        // SAFETY: We know that the slice is valid UTF-8, because we checked
> +        // that FILE is ASCII (via is_ascii() above).
> +        unsafe { core::str::from_utf8_unchecked(slice) }

Instead of this, I'm thinking you could have a const str slicing method.
You can use is_char_boundary() asserts to get rid of the ASCII check.

Alice

  parent reply	other threads:[~2025-06-04  9:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-03 19:54 [PATCH] [v2] rust: introduce sfile macro for succinct code tracing Timur Tabi
2025-06-03 22:53 ` Miguel Ojeda
2025-06-06 22:11   ` Timur Tabi
2025-06-07  0:13     ` John Hubbard
2025-06-07 10:17     ` Miguel Ojeda
2025-06-04  9:00 ` Alice Ryhl [this message]
2025-06-04 20:43   ` Timur Tabi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aEALJCHeJ6GLnaxo@google.com \
    --to=aliceryhl@google.com \
    --cc=dakr@kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=ttabi@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.