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

dirEntries gives link errors (works with dmd, fails with ldmd2) #454

Closed
timotheecour opened this issue Aug 25, 2013 · 5 comments · Fixed by #507
Closed

dirEntries gives link errors (works with dmd, fails with ldmd2) #454

timotheecour opened this issue Aug 25, 2013 · 5 comments · Fixed by #507

Comments

@timotheecour
Copy link

import std.file;
void main(){
    auto a=dirEntries("","",SpanMode.depth);
}

ldmd2 main.d:

Undefined symbols for architecture x86_64:
"__D3std8typecons86__T10RefCountedTS3std4file15DirIteratorImplVE3std8typecons24RefCountedAutoInitialize0Z10RefCounted10__postblitMFZv", referenced from:
__D123TypeInfo_S3std8typecons86__T10RefCountedTS3std4file15DirIteratorImplVE3std8typecons24RefCountedAutoInitialize0Z10RefCounted6__initZ in main.o
ld: symbol(s) not found for architecture x86_64

@redstar
Copy link
Member

redstar commented Aug 30, 2013

Confirmed. Happens on Gentoo with ldc2, too.

@nomad-software
Copy link

I think i'm experiencing the same issue explained here: http://forum.dlang.org/thread/wzzfsnshgdjdoypanamp@forum.dlang.org#post-qrftnizdsbuimxicolov:40forum.dlang.org

Debian7, llvm-3.4, ldc2

@dnadlinger
Copy link
Member

@nomad-software: Yes, this is very likely the same issue.

To fix, we might need to change quite a few things: The basic problem is that we are emitting the definitions for the return type of dirEntries to the module that calls it, as it is a template, but we shouldn't (the functions are guaranteed to be available from std.file because dirEntries itself is a regular function).

The undefined symbol comes from the fact that attribute inference hasn't properly been run on the template yet and thus the mangled name of the function in question doesn't match the one in the std.file object file. I'm not sure whether this is a problem in and of itself, but assuming that the only reasonable fix in the short term is to match DMD's template emission behavior, we got a problem with the current design:

When deciding whether to "define" the struct type, we have no way of determining that we are analyzing it in the context of a return type. I think the proper fix would be to do away with the mustDefineSymbol -> emitSymbol logic in the default path for IrType construction (e.g. DtoType) and add a IrType::defineType method that would be called in places where you need to be sure to emit the type if needed (in this case, when actually defining std.file.dirEntries during std.file compilation).

This could have quite a lot of consequences all over the code base, though. I think I'll implement something like this, but only transition as much code as required for fixing this issue before the release. Later, we can clean up the situation (and might also be able to remove some of the LDC-only fields tracking template instantiation origin).

@nomad-software
Copy link

Here's a simple test case, save as file.d

    import std.stdio;
    import std.file;

    void main()
    {
            auto entries = dirEntries(".", "*", SpanMode.shallow, false);

            writeln("crashes before this compiles");
    }

Compile with: rdmd --compiler=ldc2 file.d

Error:

/tmp/.rdmd-1001/rdmd-test.d-E715299626833E7BD89AAECC25A35A6B/test.o:(.rodata._D123TypeInfo_S3std8typecons86__T10RefCountedTS3std4file15DirIteratorImplVE3std8typecons24RefCountedAutoInitialize0Z10RefCounted6__initZ[_D123TypeInfo_S3std8typecons86__T10RefCountedTS3std4file15DirIteratorImplVE3std8typecons24RefCountedAutoInitialize0Z10RefCounted6__initZ]+0x60): undefined reference to `_D3std8typecons86__T10RefCountedTS3std4file15DirIteratorImplVE3std8typecons24RefCountedAutoInitialize0Z10RefCounted10__postblitMFZv'
collect2: error: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1

@dnadlinger
Copy link
Member

I'm knee-deep into a rewrite of the way the symbol definition process works that will fix the issue.

The idea is to follow the DMD way of simply emitting everything in Module::members instead of trying to use mustDefineSymbol and friends (the functions are to go away entirely) to guess whether to emit the a declaration when looking at it in isolation (which isn't always possible, e.g. in the case discussed in this bug report).

Needless to say, the whole thing is a big change to the internal structure and unlikely to go without problems…

dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.
dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.

GitHub: Fixes ldc-developers#454.
dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.

GitHub: Fixes ldc-developers#454.
dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.

GitHub: Fixes ldc-developers#454.
dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.

GitHub: Fixes ldc-developers#454.
dnadlinger added a commit to dnadlinger/ldc that referenced this issue Oct 13, 2013
This commit fundamentally changes the way symbol emission in
LDC works: Previously, whenever a declaration was used in some
way, the compiler would check whether it actually needs to be
defined in the currently processed module, based only on the
symbol itself. This lack of contextual information proved to
be a major problem in correctly handling emission of templates
(see e.g. ldc-developers#454).

Now, the DtoResolve…() family of functions and similar only
ever declare the symbols, and definition is handled by doing
a single pass over Module::members for the root module. This
is the same strategy that DMD uses as well, which should
also reduce the maintainance burden down the road (which is
important as during the last few releases, there was pretty
much always a symbol emission related problem slowing us
down).

Our old approach might have been a bit better tuned w.r.t.
avoiding emission of unneeded template instances, but 2.064
will bring improvements here (DMD: FuncDeclaration::toObjFile).
Barring such issues, the change shoud also marginally improve
compile times because of declarations no longer being emitted
when they are not needed.

In the future, we should also consider refactoring the code
so that it no longer directly accesses Dsymbol::ir but uses
wrapper functions that ensure that the appropriate
DtoResolve…() function has been called.

GitHub: Fixes ldc-developers#454.
redstar pushed a commit that referenced this issue Sep 27, 2014
Mark the floating-point environment as __gshared
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants