Skip to content

asm.rs assumes that multiple global_asm statements are concatenated #321

@jannic

Description

@jannic

In https://github.com/rust-embedded/riscv/blob/master/riscv-rt/src/asm.rs there are multiple global_asm! macro calls (generated from multiple cfg_global_asm! macro calls`) with code that only make sense if the generated machine code is a single contiguous block.

However, as far as I can tell, rust doesn't guarantee that.

To the contrary, https://dirname.github.io/rust-std-doc/unstable-book/library-features/global-asm.html contains the following language: "However, you should not rely on assembler state (e.g. assembler macros) defined in one global_asm! to be available in another one. It is implementation-defined whether the multiple usages are concatenated into one or assembled separately."

(Of course, even if assembled separately, the generated code could still be contiguous. I just didn't find any guarantee that it will.)

In the rust-embedded matrix channel, @Dirbaio suggested to use a single cfg_global_asm! block. To avoid unwieldy repetitive cfg statements, the cfg_global_asm! macro could be extended to allow for nested blocks:


/// Parse cfg attributes inside a global_asm call.
macro_rules! cfg_global_asm {
    {@inner, [$($x:tt)*], } => {
        global_asm!{$($x)*}
    };
    (@inner, [$($x:tt)*], #[cfg($meta:meta)] { $($y:tt)* } $($rest:tt)*) => {
        #[cfg($meta)]
        cfg_global_asm!{@inner, [$($x)*], $($y)* $($rest)*}
        #[cfg(not($meta))]
        cfg_global_asm!{@inner, [$($x)*], $($rest)*}
    };
    (@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => {
        #[cfg($meta)]
        cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
        #[cfg(not($meta))]
        cfg_global_asm!{@inner, [$($x)*], $($rest)*}
    };
    {@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => {
        cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*}
    };
    {$($asms:tt)*} => {
        cfg_global_asm!{@inner, [], $($asms)*}
    };
}

untested, could be used like this:

cfg_global_asm!(
    "blah",
    #[cfg(foo)]
    "blah",
    #[cfg(bar)] {
        "blah",
        #[cfg(foo)]
        "blah",
    }
)

(https://libera.catirclogs.org/rust-embedded/2025-07-01#38366632)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions