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

'undefined reference to __morestack' when compiling with -O #15108

Closed
ebfe opened this issue Jun 23, 2014 · 1 comment
Closed

'undefined reference to __morestack' when compiling with -O #15108

ebfe opened this issue Jun 23, 2014 · 1 comment

Comments

@ebfe
Copy link
Contributor

ebfe commented Jun 23, 2014

fn main() {}
$ rustc t.rs
$ rustc -O t.rs
error: linking with `cc` failed: exit code: 1
note: cc '-m64' '-L' '/usr/lib64/rustlib/x86_64-unknown-linux-gnu/lib' '-o' 't' 't.o' '-lmorestack' '-nodefaultlibs' '-Wl,--gc-sections' '-Wl,--as-needed' '-Wl,-O1' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-59beb4f7-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libsync-305341d2-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustrt-d8560cb2-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-2ea8f361-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-d412c0c4-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-1085c790-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-c5ed6fb4-0.11.0-pre.rlib' '/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4f9a876d-0.11.0-pre.rlib' '-L' '/home/mg/.rust' '-L' '/home/mg' '-Wl,-Bdynamic' '-ldl' '-lpthread' '-lgcc_s' '-lpthread' '-lc' '-lm' '-Wl,-rpath,$ORIGIN/../../usr/lib/rustlib/x86_64-unknown-linux-gnu/lib' '-Wl,-rpath,/usr/lib64/rustlib/x86_64-unknown-linux-gnu/lib' '-lcompiler-rt'
note: /usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o): In function `io::helper_thread::imp::new::h69049da469566067Aga::v0.11.0.pre':
(.text._ZN2io13helper_thread3imp3new20h69049da469566067Aga11v0.11.0.preE+0x20): undefined reference to `__morestack'
/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o): In function `io::helper_thread::imp::signal::h13cdde7c153bbf21Vga::v0.11.0.pre':
(.text._ZN2io13helper_thread3imp6signal20h13cdde7c153bbf21Vga11v0.11.0.preE+0x20): undefined reference to `__morestack'
/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o): In function `io::file::FileDesc::inner_write::h2c415f6b9c18fc02zuc::v0.11.0.pre':
(.text._ZN2io4file8FileDesc11inner_write20h2c415f6b9c18fc02zuc11v0.11.0.preE+0x20): undefined reference to `__morestack'
/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o): In function `io::file::FileDesc::new::h56aff56801c246e39sc::v0.11.0.pre':
(.text._ZN2io4file8FileDesc3new20h56aff56801c246e39sc11v0.11.0.preE+0x20): undefined reference to `__morestack'
/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o): In function `io..file..FileDesc::glue_drop.4662::h71b0d96b8d3b9466':
(.text._ZN18io..file..FileDesc14glue_drop.466217h71b0d96b8d3b9466E+0x20): undefined reference to `__morestack'
/usr/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-1fb5e2c0-0.11.0-pre.rlib(native.o):(.text._ZN2io8addrinfo18GetAddrInfoRequest3run20h8447a365fad4be72Kha11v0.11.0.preE+0x28): more undefined references to `__morestack' follow
collect2: error: ld returned 1 exit status

error: aborting due to previous error
@alexcrichton
Copy link
Member

Interesting! It turns out that LLVM got real smart recently (or it always has been!)

$ rustc foo.rs -O --emit=ir -o - 
; ModuleID = '-.rs'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind readnone uwtable
define internal void @_ZN4main20hbfcbec594e62aee2eaa4v0.0E() unnamed_addr #0 {
entry-block:
  ret void
}

define i64 @main(i64, i8**) unnamed_addr #1 {
top:
  %2 = tail call i64 @_ZN10lang_start20h53a1e3fe8c23b585vme11v0.11.0.preE(i8* bitcast (void ()* @_ZN4main20hbfcbec594e62aee2eaa4v0.0E to i8*), i64 %0, i8** %1)
  ret i64 %2
}

declare i64 @_ZN10lang_start20h53a1e3fe8c23b585vme11v0.11.0.preE(i8*, i64, i8**) unnamed_addr #1

attributes #0 = { nounwind readnone uwtable "split-stack" }
attributes #1 = { "split-stack" }
$ objdump -S foo.o

foo.o:     file format elf64-x86-64


Disassembly of section .text._ZN4main20h22fc21a23bd4f614eaa4v0.0E:

0000000000000000 <_ZN4main20h22fc21a23bd4f614eaa4v0.0E>:
   0:   c3                      retq   

Disassembly of section .text.main:

0000000000000000 <main>:
  10:   48 89 f0                mov    %rax,%rdx
  13:   48 89 f9 48 8d          jmpq   18 <main+0x8>
  18:   Address 0x0000000000000018 is out of bounds.

Basically, this comment is not quite accurate.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Jun 23, 2014
It was previously assumed that the object file generated by LLVM would always
require the __morestack function, but that assumption appears to be incorrect,
as outlined in rust-lang#15108. This commit forcibly tells the linker to include the
entire archive, regardless of whether it's currently necessary or not.

Closes rust-lang#15108
lnicola pushed a commit to lnicola/rust that referenced this issue Jan 3, 2024
…r=Veykril

fix: rewrite code_action `generate_delegate_trait`

I've made substantial enhancements to the "generate delegate trait" code action in rust-analyzer. Here's a summary of the changes:

#### Resolved the "Can’t find [email protected] in AstIdMap" error

Fix rust-lang#15804, fix rust-lang#15968, fix rust-lang#15108

The issue stemmed from an incorrect application of PathTransform in the original code. Previously, a new 'impl' was generated first and then transformed, causing PathTransform to fail in locating the correct AST node, resulting in an error. I rectified this by performing the transformation before generating the new 'impl' (using make::impl_trait), ensuring a step-by-step transformation of associated items.

#### Rectified generation of `Self` type

`generate_delegate_trait` is unable to properly handle trait with `Self` type.

Let's take the following code as an example:

```rust
trait Trait {
    fn f() -> Self;
}

struct B {}
impl Trait for B {
    fn f() -> B { B{} }
}

struct S {
    b: B,
}
```

Here, if we implement `Trait` for `S`, the type of `f` should be `() -> Self`, i.e. `() -> S`. However we cannot automatically generate a function that constructs `S`.

To ensure that the code action doesn't generate delegate traits for traits with Self types, I add a function named `has_self_type` to handle it.

#### Extended support for generics in structs and fields within this code action

The former version of `generate_delegate_trait` cannot handle structs with generics properly. Here's an example:

```rust
struct B<T> {
    a: T
}

trait Trait<T> {
    fn f(a: T);
}

impl<T1, T2> Trait<T1> for B<T2> {
    fn f(a: T1) -> T2 { self.a }
}

struct A {}
struct S {
    b$0 : B<A>,
}
```

The former version  will generates improper code:

```rust
impl<T1, T2> Trait<T1, T2> for S {
    fn f(&self, a: T1) -> T1 {
        <B as Trait<T1, T2>>::f( &self.b , a)
    }
}
```

The rewritten version can handle generics properly:

```rust
impl<T1> Trait<T1> for S {
    fn f(&self, a: T1) -> T1 {
        <B<A> as Trait<T1>>::f(&self.b, a)
    }
}
```

See more examples in added unit tests.

I enabled support for generic structs in `generate_delegate_trait` through the following steps (using the code example provided):

1. Initially, to prevent conflicts between the generic parameters in struct `S` and the ones in the impl of `B`, I renamed the generic parameters of `S`.
2. Then, since `B`'s parameters are instantiated within `S`, the original generic parameters of `B` needed removal within `S` (to avoid errors from redundant parameters). An important consideration here arises when Trait and B share parameters in `B`'s impl. In such cases, these shared generic parameters cannot be removed.
3. Next, I addressed the matching of types between `B`'s type in `S` and its type in the impl. Given that some generic parameters in the impl are instantiated in `B`, I replaced these parameters with their instantiated results using PathTransform. For instance, in the example provided, matching `B<A>` and `B<T2>`, where `T2` is instantiated as `A`, I replaced all occurrences of `T2` in the impl with `A` (i.e. apply the instantiated generic arguments to the params).
4. Finally, I performed transformations on each assoc item (also to prevent the initial issue) and handled redundant where clauses.

For a more detailed explanation, please refer to the code and comments. I welcome suggestions and any further questions!
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

Successfully merging a pull request may close this issue.

2 participants