Skip to content

Support for const string interpolation into inline assembly #132083

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dingxiangfei2009 opened this issue Oct 23, 2024 · 5 comments
Open

Support for const string interpolation into inline assembly #132083

dingxiangfei2009 opened this issue Oct 23, 2024 · 5 comments
Assignees
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@dingxiangfei2009
Copy link
Contributor

dingxiangfei2009 commented Oct 23, 2024

Related to this comment.

Maybe related to #93332

This feature request targets the inline assembly macro asm! and globally scope assembly global_asm! to support direct string interpolation into the assembly template.

The semantic works very much like a format! in a narrower sense, that only constant string is supported. The proposed macro word is interpolate $expr where $expr is a const-evaluatable expression that yields a &'static str constant value.

An example of how it would work is as follows.

trait Helper {
    const SRC: &'static str;
}

fn make_it_work<H: Helper>(h: &H, x: i64) {
    asm!(
        "mov {0}, {1}",
        in(reg) x,
        interpolate H::SRC
    );
}

struct H;
impl Helper for H {
    const SRC: &'static str = "MAGIC";
}

fn invoke() {
    make_it_work(&H, 42);
}

The one and only instantiation of asm! macro, when completely expanded through codegen, might have yield the following assembly line.

    mov rcx, MAGIC
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 23, 2024
@dingxiangfei2009
Copy link
Contributor Author

dingxiangfei2009 commented Oct 23, 2024

Requests from #132012 (comment) is fulfilled.

Bonus question I guess.

Do we want in(..) and out(..) constraints to accept const values as well? I imagine that it would be helpful to additionally mark registers clobbered, for instance.

@dingxiangfei2009
Copy link
Contributor Author

@rustbot claim

@jieyouxu jieyouxu added C-enhancement Category: An issue proposing an enhancement or a PR with one. A-inline-assembly Area: Inline assembly (`asm!(…)`) T-lang Relevant to the language team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Oct 24, 2024
@Lokathor
Copy link
Contributor

I'm unclear why this is interpolate instead of sticking with const. The value is still a constant input to the asm, as far as I can tell.

@thomcc
Copy link
Member

thomcc commented Oct 25, 2024

It might be surprising to users that const on a string doesn't somehow give the assemnbly a refrerence to that constant string, rather than interpolating it directly.

@kulst
Copy link

kulst commented Jan 26, 2025

One possible use-case for a feature like this might be implementing special operations for the NVPTX target:
In the assembly of this target the type of the operands is encoded in the instruction. NVPTX also has very special instructions that to my knowledge do not really have a complementary operation in the Rust language. Therefore to use such instructions from Rust inline assembly might be necessary:

One special instruction in NVPTX is to fetch from texture memory. To fetch from texture memory that stores f32 values an inline assembly instruction looks like this:

#[inline]
pub unsafe fn _tex_1d_fetch_f32(tex_object: u64, x: i32) -> f32 {
    let mut res: f32;
    asm! {
        "tex.1d.v4.f32.s32 {{{f1}, {f2}, {f3}, {f4}}}, [{tex_object}, {{{x}}}];",
        tex_object = in(reg64) tex_object,
        x = in(reg32) x,
        f1 = out(reg32) res,
        f2 = out(reg32) _,
        f3 = out(reg32) _,
        f4 = out(reg32) _,
    }
    res
}

With the proposed solution this function could be made generic over the 32 Bit type it fetches and the 32 Bit type of the indexing variable x:

#[inline]
pub unsafe fn _tex_1d_fetch_32<T : TexDType32, U: TexCType> (tex_object: u64, x: U) -> T {
    let mut res: T;
    asm! {
        "tex.1d.v4.{dtype}.{ctype} {{{f1}, {f2}, {f3}, {f4}}}, [{tex_object}, {{{x}}}];",
        tex_object = in(reg64) tex_object,
        x = in(reg32) x,
        f1 = out(reg32) res,
        f2 = out(reg32) _,
        f3 = out(reg32) _,
        f4 = out(reg32) _,
        dtype = interpolate T::TYPE,
        ctype = interpolate U::TYPE,
    }
    res
}

(It would be benefitial to be generic over the register size as well, but this is another topic I think. Another way to implement such special operations could be using LLVM intrinsics. However, I do not know if LLVM intrinsics do exist for all special NVPTX instructions and how stable these are.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants