Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp909405rwb; Thu, 10 Nov 2022 08:48:51 -0800 (PST) X-Google-Smtp-Source: AMsMyM5U0s5sdsxkSLtlWvTLyKP4h5V23uXpvqvmrejMOr4wCMNbt1AZepPTAm5WmgRXhcw/PUMk X-Received: by 2002:a17:907:20db:b0:79e:5ea1:4f83 with SMTP id qq27-20020a17090720db00b0079e5ea14f83mr3002047ejb.372.1668098931130; Thu, 10 Nov 2022 08:48:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668098931; cv=none; d=google.com; s=arc-20160816; b=n3nK9kSPmlr2mYJEDgM1dpdfmvOKuspzBJeJJtL9zNRP+JfTF7G3Hmdj6m0A2Oyspt acLSUQrphapO8wu8IEsQZGnjnkGXjVRXbVr30MF2hTG3P6mr1qw9ECM15x6O0uz5DG0k KfDWZbjxw7PlkJIEXpaMe5eEM345FnYYgIj4Z+UxjjmSMM5ONDJh8SLxh/wknYclUK8S oHSg2dEMzL2RNg6A9n7VZryJZI+f9K1PmrahVh7QH1qjGGe1kUMWgBQUcJcKYQOvy7in pVRPJrJh9bHMIJxqxOdlGJOkswW0K+qB3CnxJlYkVC0hJT4PujgtM6u1wnVHdbHn2ePm QuGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=n3NKeWNbg1SBhnqHCpLlUYtmsFGWeB0jN5sgd7OvX0w=; b=q013t8OTVmL081iwm+qAgCUbRnuNM5nRdf8L9c9qYRMXkKZcoLpDqjweOrns+MjQTz AkWsrB74OVefeA2G+MFCT9VmO4EinI8SXSqtiifIjOTexZfzlMH6yn9fc+ABy8SaxIuT kLfA8KzbVTiau6fW+iNF6/8PRBqE04a/YG3NzAgIS9W57FI1snyCa25e/kVzMu8CkGTY nUWly9tnshP8/9FmpZrdXOOXGBh6OjZzQ4D7gZlW583e4PKytSumBJ+md8nz0lxSWurm eHYuaJZmzdzr3noUGBTspRefazi6/XLiLwMXFhdIu73hj92SWwCRAJCZS2DdRY6R/hyg f4hg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=XbqXHj1y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ss28-20020a170907c01c00b00787803711f9si16182534ejc.353.2022.11.10.08.48.25; Thu, 10 Nov 2022 08:48:51 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=XbqXHj1y; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229831AbiKJQo7 (ORCPT + 93 others); Thu, 10 Nov 2022 11:44:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231946AbiKJQo1 (ORCPT ); Thu, 10 Nov 2022 11:44:27 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42D2645A13; Thu, 10 Nov 2022 08:43:28 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id BE08861BCD; Thu, 10 Nov 2022 16:43:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E82D6C433D6; Thu, 10 Nov 2022 16:43:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1668098607; bh=HjvUpyGIW4BqiVc1eK1nOFEnywHRBja8WZXcNu1Xsro=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XbqXHj1y/nG8jTYpN6CQsFzBrMf2VYre1h+DDfUNBWlXn0xh9HwX4enVcuzgSwiJ9 NeAGbnqEyXVxniRTOMBS4mjA1fKpwfAtAjhcnfafgTQ+sd8cdUglLp/DvhlKS0rzqc WmKybZLQBZzLmP9e9Ajnz00QypI2TSAHtEQAmwr1LqhKeBaEJkVfEoCYeAnJGu0HLI 5Ak+5waKF0+7jn89gsYFhfog0joLVY8hjIAL/++jCFkRVGz8l9opv0l7zMQmbcgOaZ z6jr61HANdh3rBZMXd9YT+kC/LmabXebx8M7at6qcgyVL9s/FHqsSxNhzFuk8BQH0y yt50rL5E0CYPA== From: Miguel Ojeda To: Miguel Ojeda , Wedson Almeida Filho , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, Niklas Mohrin Subject: [PATCH v1 23/28] rust: std_vendor: add `dbg!` macro based on `std`'s one Date: Thu, 10 Nov 2022 17:41:35 +0100 Message-Id: <20221110164152.26136-24-ojeda@kernel.org> In-Reply-To: <20221110164152.26136-1-ojeda@kernel.org> References: <20221110164152.26136-1-ojeda@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,WEIRD_PORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Niklas Mohrin The Rust standard library has a really handy macro, `dbg!` [1,2]. It prints the source location (filename and line) along with the raw source code that is invoked with and the `Debug` representation of the given expression, e.g.: let a = 2; let b = dbg!(a * 2) + 1; // ^-- prints: [src/main.rs:2] a * 2 = 4 assert_eq!(b, 5); Port the macro over to the `kernel` crate, using `pr_info!` instead of `eprintln!`, inside a new module called `std_vendor`. Since the source code for the macro is taken from the standard library source (with only minor adjustments), the new file is licensed under `Apache 2.0 OR MIT`, just like the original [3,4]. Link: https://doc.rust-lang.org/std/macro.dbg.html [1] Link: https://github.com/rust-lang/rust/blob/master/library/std/src/macros.rs#L212 [2] Link: https://github.com/rust-lang/rust/blob/master/library/std/Cargo.toml [3] Link: https://github.com/rust-lang/rust/blob/master/COPYRIGHT [4] Signed-off-by: Niklas Mohrin [Reworded, adapted for upstream and applied latest changes] Signed-off-by: Miguel Ojeda --- rust/kernel/lib.rs | 2 + rust/kernel/prelude.rs | 2 +- rust/kernel/std_vendor.rs | 160 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/std_vendor.rs diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index ffc6626a6d29..d6371c9c8453 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -26,6 +26,8 @@ mod allocator; pub mod error; pub mod prelude; pub mod print; +#[doc(hidden)] +pub mod std_vendor; pub mod str; #[doc(hidden)] diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 89c2c9f4e7a7..345fc9075d1f 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -17,7 +17,7 @@ pub use alloc::{boxed::Box, vec::Vec}; pub use macros::{module, vtable}; -pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn}; +pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn}; pub use super::error::{code::*, Error, Result}; diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs new file mode 100644 index 000000000000..da57b4e521f4 --- /dev/null +++ b/rust/kernel/std_vendor.rs @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! The contents of this file come from the Rust standard library, hosted in +//! the repository, licensed under +//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details, +//! see . + +/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`]. +/// +/// Prints and returns the value of a given expression for quick and dirty +/// debugging. +/// +/// An example: +/// +/// ```rust +/// let a = 2; +/// # #[allow(clippy::dbg_macro)] +/// let b = dbg!(a * 2) + 1; +/// // ^-- prints: [src/main.rs:2] a * 2 = 4 +/// assert_eq!(b, 5); +/// ``` +/// +/// The macro works by using the `Debug` implementation of the type of +/// the given expression to print the value with [`printk`] along with the +/// source location of the macro invocation as well as the source code +/// of the expression. +/// +/// Invoking the macro on an expression moves and takes ownership of it +/// before returning the evaluated expression unchanged. If the type +/// of the expression does not implement `Copy` and you don't want +/// to give up ownership, you can instead borrow with `dbg!(&expr)` +/// for some expression `expr`. +/// +/// The `dbg!` macro works exactly the same in release builds. +/// This is useful when debugging issues that only occur in release +/// builds or when debugging in release mode is significantly faster. +/// +/// Note that the macro is intended as a debugging tool and therefore you +/// should avoid having uses of it in version control for long periods +/// (other than in tests and similar). +/// +/// # Stability +/// +/// The exact output printed by this macro should not be relied upon +/// and is subject to future changes. +/// +/// # Further examples +/// +/// With a method call: +/// +/// ```rust +/// # #[allow(clippy::dbg_macro)] +/// fn foo(n: usize) { +/// if dbg!(n.checked_sub(4)).is_some() { +/// // ... +/// } +/// } +/// +/// foo(3) +/// ``` +/// +/// This prints to the kernel log: +/// +/// ```text,ignore +/// [src/main.rs:4] n.checked_sub(4) = None +/// ``` +/// +/// Naive factorial implementation: +/// +/// ```rust +/// # #[allow(clippy::dbg_macro)] +/// # { +/// fn factorial(n: u32) -> u32 { +/// if dbg!(n <= 1) { +/// dbg!(1) +/// } else { +/// dbg!(n * factorial(n - 1)) +/// } +/// } +/// +/// dbg!(factorial(4)); +/// # } +/// ``` +/// +/// This prints to the kernel log: +/// +/// ```text,ignore +/// [src/main.rs:3] n <= 1 = false +/// [src/main.rs:3] n <= 1 = false +/// [src/main.rs:3] n <= 1 = false +/// [src/main.rs:3] n <= 1 = true +/// [src/main.rs:4] 1 = 1 +/// [src/main.rs:5] n * factorial(n - 1) = 2 +/// [src/main.rs:5] n * factorial(n - 1) = 6 +/// [src/main.rs:5] n * factorial(n - 1) = 24 +/// [src/main.rs:11] factorial(4) = 24 +/// ``` +/// +/// The `dbg!(..)` macro moves the input: +/// +/// ```ignore +/// /// A wrapper around `usize` which importantly is not Copyable. +/// #[derive(Debug)] +/// struct NoCopy(usize); +/// +/// let a = NoCopy(42); +/// let _ = dbg!(a); // <-- `a` is moved here. +/// let _ = dbg!(a); // <-- `a` is moved again; error! +/// ``` +/// +/// You can also use `dbg!()` without a value to just print the +/// file and line whenever it's reached. +/// +/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as +/// a tuple (and return it, too): +/// +/// ``` +/// # #[allow(clippy::dbg_macro)] +/// assert_eq!(dbg!(1usize, 2u32), (1, 2)); +/// ``` +/// +/// However, a single argument with a trailing comma will still not be treated +/// as a tuple, following the convention of ignoring trailing commas in macro +/// invocations. You can use a 1-tuple directly if you need one: +/// +/// ``` +/// # #[allow(clippy::dbg_macro)] +/// # { +/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored +/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple +/// # } +/// ``` +/// +/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html +/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html +/// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html +#[macro_export] +macro_rules! dbg { + // NOTE: We cannot use `concat!` to make a static string as a format argument + // of `pr_info!` because `file!` could contain a `{` or + // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!` + // will be malformed. + () => { + $crate::pr_info!("[{}:{}]\n", ::core::file!(), ::core::line!()) + }; + ($val:expr $(,)?) => { + // Use of `match` here is intentional because it affects the lifetimes + // of temporaries - https://stackoverflow.com/a/48732525/1063961 + match $val { + tmp => { + $crate::pr_info!("[{}:{}] {} = {:#?}\n", + ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp); + tmp + } + } + }; + ($($val:expr),+ $(,)?) => { + ($($crate::dbg!($val)),+,) + }; +} -- 2.38.1