Skip to content
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

Support for pointers with asm_const #128464

Open
Darksonn opened this issue Jul 31, 2024 · 10 comments
Open

Support for pointers with asm_const #128464

Darksonn opened this issue Jul 31, 2024 · 10 comments
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-rust-for-linux Relevant for the Rust-for-Linux project C-feature-request Category: A feature request, i.e: not implemented / a PR. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. F-asm `#![feature(asm)]` (not `llvm_asm`) I-lang-nominated Nominated for discussion during a lang team meeting. P-low Low priority T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@Darksonn
Copy link
Contributor

Inline assembly supports an unstable feature called asm_const with tracking issue #93332 that lets you pass constants to inline assembly. However, it only supports integer types. This issue is a feature request to support raw pointers with asm_const.

This would enable code such as the following:

#![feature(const_refs_to_static)]
#![feature(asm_const)]
use core::arch::asm;
use core::ptr::addr_of;
use core::ffi::c_void;

trait Helper {
    const MY_PTR: *const c_void;
}

fn my_asm_wrapper<T: Helper>() {
    unsafe { asm!("mov {},eax", const T::MY_PTR) };
}


extern "C" {
    static FOO: usize;
}

struct HelperForPassingPointerAsConstGeneric {}
impl Helper for HelperForPassingPointerAsConstGeneric {
    const MY_PTR: *const c_void = addr_of!(FOO).cast();
}

fn main() {
    my_asm_wrapper::<HelperForPassingPointerAsConstGeneric>();
}

Currently, the above code would require you to convert my_asm_wrapper into a macro_rules! so that you can write out the path to the global using the sym operand. Supporting this would be useful for the Rust for Linux project, as implementing support for static keys requires a long list of workarounds at the moment.

cc @Amanieu @oli-obk

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 31, 2024
@oli-obk oli-obk added A-const-eval Area: constant evaluation (mir interpretation) F-asm `#![feature(asm)]` (not `llvm_asm`) E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. P-low Low priority C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language 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 Aug 1, 2024
@folkertdev
Copy link
Contributor

I think this is at least blocked on #125558 right now (which is done but runs into an error message ordering difference between CI and local that we don't know how to fix).

@Amanieu
Copy link
Member

Amanieu commented Aug 1, 2024

First of all, it doesn't make sense to pass a pointer as a const because... it's not actually a constant. What the assembly code would expect to receive is a symbol which points to the same address that the pointer is pointing to. So it would make more sense to support this for sym operands.

Secondly, what you are actually proposing is a generalization of sym, where rather than only supporting static and fn, it supports any arbitrary pointer and rustc will figure out a symbol expression that resolves to that address. This is probably possible but would require a new specification of exactly what kinds of expressions sym now accepts. It is also somewhat a breaking change for existing usage of sym for static since you would now need to take the address of a static instead of just naming it directly.

@Darksonn
Copy link
Contributor Author

Darksonn commented Aug 1, 2024

I understand that const <integer> and const <pointer> would need two different implementations, but I still think it is a reasonable UX to accept pointers with the const operand. Yes, there will be overlap with the things you can do with the sym operand, but is that really a problem? Making const accept it avoids changing the syntax of sym.

@Darksonn
Copy link
Contributor Author

Darksonn commented Aug 1, 2024

where rather than only supporting static and fn, it supports any arbitrary pointer and rustc will figure out a symbol expression that resolves to that address.

Indeed. Note that in my real use-case sym is actually not enough, because I need the address of a field in the static. So right now I'm combining a sym operand with a const ::core::mem::offset_of!(...) and adding them together.

@RalfJung
Copy link
Member

RalfJung commented Aug 2, 2024

First of all, it doesn't make sense to pass a pointer as a const because... it's not actually a constant.

Everywhere else in the language, we do support pointers as "constants", and our backends do the right thing. You can use pointers as initial values for static and const and we'll generate code with appropriate relocations etc. So why would inline assembly not follow suit?

@nikic
Copy link
Contributor

nikic commented Aug 5, 2024

First of all, it doesn't make sense to pass a pointer as a const because... it's not actually a constant.

Everywhere else in the language, we do support pointers as "constants", and our backends do the right thing. You can use pointers as initial values for static and const and we'll generate code with appropriate relocations etc. So why would inline assembly not follow suit?

That may indicate that const asm operands are misnamed. The defining semantic for these operands is:

The value of the expression is formatted as a string and substituted directly into the asm template string.

Which doesn't really make sense for relocatable constants. The whole point of const here is that it does not reach the backend and does not get treated as an actual input operand constraint.

It's really more of a str or literal operand than a const operand.

@RalfJung
Copy link
Member

RalfJung commented Aug 5, 2024 via email

@joshtriplett joshtriplett added the I-lang-nominated Nominated for discussion during a lang team meeting. label Aug 14, 2024
@ojeda
Copy link
Contributor

ojeda commented Aug 14, 2024

@rustbot label A-rust-for-linux

@rustbot rustbot added the A-rust-for-linux Relevant for the Rust-for-Linux project label Aug 14, 2024
@joshtriplett
Copy link
Member

Nominating this for lang to discuss the question of whether we should support use of const in asm! for things that can't just be textually substituted, or whether we should give that a different name.

@Amanieu, any input you'd like to provide would be helpful.

@Amanieu
Copy link
Member

Amanieu commented Aug 15, 2024

After thinking about it a bit, I think it's probably fine to add this functionality to const. I'm a bit bothered about the duplication with sym, which is already stable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-rust-for-linux Relevant for the Rust-for-Linux project C-feature-request Category: A feature request, i.e: not implemented / a PR. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. F-asm `#![feature(asm)]` (not `llvm_asm`) I-lang-nominated Nominated for discussion during a lang team meeting. P-low Low priority 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

9 participants