Skip to content

Can't designate registers in asm! macro #11300

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

Closed
edwardw opened this issue Jan 4, 2014 · 5 comments
Closed

Can't designate registers in asm! macro #11300

edwardw opened this issue Jan 4, 2014 · 5 comments

Comments

@edwardw
Copy link
Contributor

edwardw commented Jan 4, 2014

The x86 instruction in requires specific registers as its operands, i.e. input in dx and output to ax.

#[crate_type="staticlib"];
#[feature(asm)];

#[no_mangle]
pub fn inb(port: u16) -> u8 {
  let data: u8;
  unsafe { asm!("inb $1,$0" : "=a" (data) : "d" (port) :: "volatile"); }
  data
}

But it seems that rustc can't allocate these registers for it:

$ rustc --version
rustc 0.9-pre
host: x86_64-apple-darwin
$ rustc -c asm.rs
error: couldn't allocate output register for constraint 'a'

Trying to relax the register allocation constraints simply leads to invalid assembly:

$ cat asm.rs
...
unsafe { asm!("inb $1,$0" : "=q" (data) : "q" (port) :: "volatile"); }
...
$ rustc -c asm.rs
<inline asm>:1:6: error: invalid operand for instruction
    inb %ax,%cl
LLVM ERROR: Error parsing inline asm

Why is it so? Is it a bug in rustc or in llvm? Any suggestion of where in the rust source code to look into would also be appreciated.

@alexcrichton
Copy link
Member

Closing, because sadly this is more relevant to LLVM than rust (we just pass things through to LLVM)

I've gotten inb to work before with a function like this (unsure of how correct it actually is)

pub unsafe fn inb(port: u16) -> u8 {                                              
    let ret;                                                                      
    asm!("inb $1, $0" : "={ax}"(ret) : "{dx}"(port) :: "(eax),(edx)" : "volatile")
    return ret;                                                                   
}                                                                                 

@alexcrichton
Copy link
Member

The best resource I've found so far for learning inline assembly is looking at the relevant tests inside of LLVM sadly, otherwise I know of no other good documentation for all the syntax.

@edwardw
Copy link
Contributor Author

edwardw commented Jan 4, 2014

Thanks, Alex. This is good enough for me.

@edwardw
Copy link
Contributor Author

edwardw commented Jan 6, 2014

Oh, it definitely works correctly. There's a boot-loader written in rust with inb / outb: https://github.com/edwardw/rumos/tree/master/boot

@carlpaten
Copy link

Alex: do you suggest looking at any tests in particular? There are quite a few.

flip1995 pushed a commit to flip1995/rust that referenced this issue Sep 25, 2023
[`useless_conversion`]: don't lint if type parameter has unsatisfiable bounds for `.into_iter()` receiver

Fixes rust-lang#11300.

Before this PR, clippy assumed that if it sees a `f(x.into_iter())` call and the type at that argument position is generic over any `IntoIterator`, then the `.into_iter()` call must be useless because `x` already implements `IntoIterator`, *however* this assumption is not right if the generic parameter has more than just the `IntoIterator` bound (because other traits can be implemented for the IntoIterator target type but not the IntoIterator implementor, as can be seen in the linked issue: `<[i32; 3] as IntoIterator>::IntoIter` satisfies `ExactSizeIterator`, but `[i32; 3]` does not).

So, this PR makes it check that the type parameter only has a single `IntoIterator` bound. It *might* be possible to check if the type of `x` in `f(x.into_iter())` satisfies all the bounds on the generic type parameter as defined on the function (which would allow removing the `.into_iter()` call even with multiple bounds), however I'm not sure how to do that, and the current fix should always work.

**Edit:** This PR has been changed to check if any of the bounds don't hold for the type of the `.into_iter()` receiver, so we can still lint in some cases.

changelog: [`useless_conversion`]: don't lint `.into_iter()` if type parameter has multiple bounds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants