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

fastffi attribute is sometimes ignored or incorrectly assigned #6660

Closed
nikomatsakis opened this issue May 21, 2013 · 5 comments
Closed

fastffi attribute is sometimes ignored or incorrectly assigned #6660

nikomatsakis opened this issue May 21, 2013 · 5 comments
Labels
A-codegen Area: Code generation A-FFI Area: Foreign function interface (FFI) I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.

Comments

@nikomatsakis
Copy link
Contributor

The following test, originally written for #3678, results in a segfault because insufficient stack is allocated (at least it does on the branch I plan to land that fixes #3678).

// Test what happens when we link to the same function name with
// different types. This situation can easily arise when linking two
// crates that make use of the same C library, for example.

mod A {
    pub struct TwoU32s {
        one: u32, two: u32
    }
    extern {
        pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
    }
}

mod B {
    pub struct TwoU32s {
        one: u32, two: u32
    }
    extern {
        pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
    }
}

fn wrapper() {
}

fn main() {
    unsafe {
        let a = A::rust_dbg_extern_return_TwoU32s();
        // println(fmt!("%?", a));
        // assert_eq!(a.one, 10);
        // assert_eq!(a.two, 20);
    }

    unsafe {
        let b = B::rust_dbg_extern_return_TwoU32s();
        // println(fmt!("%?", b));
        // assert_eq!(b.one, 10);
        // assert_eq!(b.two, 20);
    }
}

Paging @pcwalton, maybe you could take a look (once the PR for #3678 lands?)

@graydon
Copy link
Contributor

graydon commented Aug 15, 2013

I'm not entirely clear what's going on here. Both functions appear to have the same type but the testcase says it's testing them being different. Can you clarify?

@nikomatsakis
Copy link
Contributor Author

Woah, I forgot about this bug. This is an interesting test case. It has nothing to do with fastffi. In fact, i'm not sure why it crashes, it kind of .. looks like an LLVM bug? But something fishy is definitely going on. Here is an updated test:

// Test what happens when we link to the same function name with
// different types. This situation can easily arise when linking two
// crates that make use of the same C library, for example.

mod A {
    pub struct TwoU32s {
        one: u32, two: u32
    }
    extern {
        pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
    }
}

mod B {
    pub struct TwoU32s {
        one: u32, two: u32
    }
    extern {
        pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
    }
}

fn wrapper() {
}

#[fixed_stack_segment]
fn main() {
    unsafe {
        let a = A::rust_dbg_extern_return_TwoU32s();
    }

    unsafe {
        let b = B::rust_dbg_extern_return_TwoU32s();
    }
}

On my branch for #8535, this code crashes when main tries to return to an invalid address. This only happens if BOTH calls are present. The assembly code shows that between the two calls, there is a subtract of $esp which misaligns the stack frame (look for // XXX):

    subl    $36, %esp
.Ltmp12:
    .cfi_offset %ebx, -12
    calll   .L1$pb
.L1$pb:
    popl    %eax
.Ltmp13:
    addl    $_GLOBAL_OFFSET_TABLE_+(.Ltmp13-.L1$pb), %eax
    leal    -16(%ebp), %ecx
    movl    %ecx, (%esp)
    movl    %eax, %ebx
    movl    %eax, -28(%ebp)
    calll   rust_dbg_extern_return_TwoU32s@PLT
    subl    $4, %esp // XXX
    leal    -24(%ebp), %eax
    movl    %eax, (%esp)
    movl    -28(%ebp), %ebx
    calll   rust_dbg_extern_return_TwoU32s@PLT
    addl    $36, %esp
    popl    %ebx
    popl    %ebp
    ret

However, when I dump the LLVM output with --emit-llvm -S, I get nonsense:


; Function Attrs: fixedstacksegment noinline uwtable
define void @"_ZN4main16_cd92990fc38403c7_0$x2e0E"({ i32, %tydesc*, i8*, i8*, i8 }*) #1 {
"function top level":
  %a = alloca %"struct.A::TwoU32s"
  %b = alloca %"struct.B::TwoU32s"
  call void @rust_dbg_extern_return_TwoU32s(%"struct.A::TwoU32s"* %a)
  call void bitcast (void (%"struct.A::TwoU32s"*)* @rust_dbg_extern_return_TwoU32s to void (%"struct.B::TwoU32s"*)*)(%"struct.B::TwoU32s"* %b)
  ret void
}

There is only one call here at all?

Anyway, an interesting bug. (note that I am running on 32 bit linux, btw, which may be relevant)

@luqmana
Copy link
Member

luqmana commented Aug 16, 2013

Should it be casting the whole function as opposed to just the argument in the second call?

@nikomatsakis
Copy link
Contributor Author

Oh, wait, you're right, I misread that LLVM code, there are in fact two calls. I'd say it... looks about right, actually. Yes, it should be casting the function.

@thestinger
Copy link
Contributor

This is no longer used.

flip1995 pushed a commit to flip1995/rust that referenced this issue Feb 11, 2021
Cleanup path-to-local checks

changelog: none

It seemed like too much ceremony going on to check if an expression matches a variable. So I created two util functions `path_to_local(Expr) -> Option<HirId>` and `path_to_local_id(Expr, HirId) -> bool` to make this easier, and used them wherever applicable.

I changed logic in a few places to use `HirId` instead of `Symbol` where it was easy to do so. I believe this is more correct and may even fix some bugs.

I also removed some calls to `qpath_res`. This is not needed if you are only looking for a `Res::Local`.

As a note, I wanted to name the util functions in a way that encourages understanding of the HIR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-FFI Area: Foreign function interface (FFI) I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.
Projects
None yet
Development

No branches or pull requests

4 participants