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

Wrong calling convention on using ffi of extern mod #9055

Closed
klutzy opened this issue Sep 8, 2013 · 7 comments
Closed

Wrong calling convention on using ffi of extern mod #9055

klutzy opened this issue Sep 8, 2013 · 7 comments
Labels
A-ffi Area: Foreign Function Interface (FFI) O-windows Operating system: Windows

Comments

@klutzy
Copy link
Contributor

klutzy commented Sep 8, 2013

Here's an example on win32.

a.rs:

#[crate_type = "lib"];

pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

extern "stdcall" {
    fn MessageBoxW(hWnd: HANDLE, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: c_uint) -> c_int;
}

Build a.rs as shared library.

b.rs:

extern mod a;
use std::ptr;

#[fixed_stack_segment]
fn main() {
    unsafe { a::MessageBoxW(ptr::mut_null(), ptr::null(), ptr::null(), 0 as a::c_uint); }
}

Building b.rs I got linking failure:

note: b.o:fake:(.text+0x86): undefined reference to `MessageBoxW'

LLVM IR has some interesting point:

; Function Attrs: noinline uwtable
define void @_ZN4main16_bd1837541cdc5544v0.0E({ i32, %tydesc*, i8*, i8*, i8 }*) #4 {
  ...
  %14 = call x86_stdcallcc i32 @MessageBoxW(%"enum.std::libc::types::common::c95::c_void[#1]"* %10, i16* %11, i16* %12, i32 %13)
  ...
}
...
declare i32 @MessageBoxW(%"enum.std::libc::types::common::c95::c_void[#1]"*, i16*, i16*, i32)

so rustc generates correct call, but wrong declare (no callconv).

Frankly I don't even know if it's ok to use foreign fn from extern module. I'm also confused that there is no need to add pub at MessageBoxW declaration.

@klutzy
Copy link
Contributor Author

klutzy commented Sep 9, 2013

(The example worked on 0.7.)

@nikomatsakis
Copy link
Contributor

Interesting. cc me.

@klutzy
Copy link
Contributor Author

klutzy commented Sep 12, 2013

I tried to make a workaround by wrapping MessageBoxW in this example. However, it is still problematic for certain cases.

a.rs:

#[crate_type = "lib"];

pub use std::ptr;
pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

extern "stdcall" {
    fn MessageBoxW(hWnd: HANDLE, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: c_uint) -> c_int;
}

pub trait Dummy {}

pub trait Window {
    fn message_box(&self);
}

impl<D: Dummy> Window for D {
    fn message_box(&self) {
        #[fixed_stack_segment];
        unsafe { MessageBoxW(ptr::mut_null(), ptr::null(), ptr::null(), 0 as c_uint); }
    }
}

b.rs:

extern mod a;
use a::*;

struct D;
impl Dummy for D;

fn main() {
    let x = D;
    x.message_box();
}

which occurs same callconv issue.

@klutzy
Copy link
Contributor Author

klutzy commented Sep 14, 2013

It occurs on generic functions, not only on generic impls:

a.rs:

#[crate_type = "lib"];

use std::ptr;

pub use std::libc::*;
pub use std::libc::types::os::arch::extra::*;

extern "stdcall" {
    fn MessageBoxW(hWnd: HANDLE, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: c_uint) -> c_int;
}

pub fn g<T>() {
    #[fixed_stack_segment];
    unsafe { MessageBoxW(ptr::mut_null(), ptr::null(), ptr::null(), 0 as c_uint); }
}

b.rs:

extern mod a;

fn main() {
    a::g::<int>();
}

This means std::unstable is totally unusable on win32 because it has pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str>.
This blocks #8540. cc @cmr

@klutzy
Copy link
Contributor Author

klutzy commented Sep 14, 2013

From #8203 bors log, it is broken somewhere between 0.7 and 2246d56.
@nikomatsakis is it possible #8535 related to this?

@thestinger
Copy link
Contributor

You could narrow it down with git bisect, the window between the commits is quite large.

bors added a commit that referenced this issue Sep 16, 2013
Beforehand it was assumed that the standard cdecl abi was used for all extern
fns of extern crates, but this reads the abi of the extern fn type and declares
the function in the local crate with the appropriate type.

I was trying to think of how to write a test for this, but I was just drawing up blanks :(. Are there standard functions in libc which are not of the cdecl abi? If so we could try linking to them and make sure that the cal completes successfully.

Otherwise, I manually verified that the function was declared correctly by looking at the llvm assembly.

cc #9055 (I'm not sure if this will fix that issue)
@klutzy
Copy link
Contributor Author

klutzy commented Sep 16, 2013

#9196 fixed all three examples. closing!

@klutzy klutzy closed this as completed Sep 16, 2013
flip1995 pushed a commit to flip1995/rust that referenced this issue Jun 30, 2022
…on, r=Manishearth

update node.js version in `remark.yml`

Optional chain (`?.`) is available in `node v14`, but node version in CI is `node v12`, so CI is failed now.

ref:
https://github.com/rust-lang/rust-clippy/runs/7059529735?check_suite_focus=true

optional chain:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#browser_compatibility

Corresponding PR (maybe)
remarkjs/remark#1007

changelog: None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ffi Area: Foreign Function Interface (FFI) O-windows Operating system: Windows
Projects
None yet
Development

No branches or pull requests

3 participants