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

Duplicate definitions of vtables/interface info with a templated class #535

Closed
SiegeLord opened this issue Oct 31, 2013 · 14 comments
Closed

Comments

@SiegeLord
Copy link
Contributor

Consider these three files:

test1.d

import test3;

alias C!(char) C1;

test2.d

import test3;

alias C!(char) C1;

test3.d

interface A {}

class C(T) : A {}

void main() {}

Running these commands produces errors:

ldc2 -c test1.d
ldc2 -c test2.d
ldc2 -c test3.d
ldc2 test1.o test2.o test3.o
test2.o:(.rodata+0x20): multiple definition of `_D5test38__T1CTaZ1C11__interface5test31A6__vtblZ'
test1.o:(.rodata+0x20): first defined here
test2.o:(.rodata+0x0): multiple definition of `_D5test38__T1CTaZ1C16__interfaceInfosZ'
test1.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1

The equivalent calls with dmd work fine. LDC revision: 8408afc . DMD version: 2.063.2

@SiegeLord
Copy link
Contributor Author

Using git-bisect I determined that this bug was introduced by commit: 787c147

@redstar
Copy link
Member

redstar commented Nov 2, 2013

@SiegeLord Thanks for working this out. I will start working on this bug soon. I think this causes at least one unit test failure in the 2.064 merge branch.

redstar added a commit to redstar/ldc that referenced this issue Nov 3, 2013
The symbols must have weak_odr linkage if they result from a template instantiation.
redstar added a commit to redstar/ldc that referenced this issue Nov 4, 2013
The symbols must have weak_odr linkage if they result from a template instantiation.
@redstar
Copy link
Member

redstar commented Nov 4, 2013

@SiegeLord Should be fixed now. Please check if it solves your problem.

@SiegeLord
Copy link
Contributor Author

This particular issue is fixed, although I'm still having problems with slightly different error messages. Once I make a test case, I'll submit a new bug.

Thanks!

EDIT: Actually, nevermind. The rest were an issue of my own build system... looks like I'm all set! Thanks again for the rapid turnaround.

@vova616
Copy link

vova616 commented Dec 6, 2013

I got similar issue, should this be in a separate issue?
ldc 0.12.1 mingw 86x windows 7 64 bit

Error: Linking globals named '_D1b1B11__interface1b1A6__vtblZ': symbol multiply
defined!
a.d:

import b;
void main() {
    new C();
}
class C {
    B t = new B();
}

b.d:

module b;
class B : A { }
interface A { }

this crashes ldc

void main() {
    new C();
}
class C {
    B t = new B();
}
class B : A { }
interface A { }

@redstar redstar reopened this Dec 7, 2013
@redstar
Copy link
Member

redstar commented Dec 7, 2013

I re-opened the issue because I think it has the same root cause.

@smolt
Copy link
Member

smolt commented Apr 4, 2014

I see something similar using ldc2 on osx and iOS. Appears that some 16__interfaceInfosZ symbols for instantiated interfaces end up (__DATA,__datacoal_nt) weak external, but for some reason, occasionally one will end up in section (__DATA,__const) external.

Here is one way to see the issue. Build format and type cons unit tests separately and then link together.

$ ldc2 -unittest -c ../ldc-git/runtime/phobos/std/format.d
$ ldc2 -unittest -c ../ldc-git/runtime/phobos/std/typecons.d
Warning: AutoImplement!(C_6) ignored variadic arguments to the constructor C_6(...)
$ ldc2 -of tester -main format.o typecons.o
duplicate symbol __D3std5range20__T12ForwardRangeTiZ12ForwardRange16__interfaceInfosZo in:
    format.o
    typecons.o
duplicate symbol __D3std5range26__T18BidirectionalRangeTiZ18BidirectionalRange16__interfaceInfosZ in:
    format.o
    typecons.o
duplicate symbol __D3std5range26__T18RandomAccessFiniteTiZ18RandomAccessFinite16__interfaceInfosZ in:
    format.o
    typecons.o
ld: 3 duplicate symbols for architecture x86_64
collect2: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1
$ ldc2 -version
LDC - the LLVM D compiler (0.13.0-alpha1):
  based on DMD v2.064 and LLVM 3.4
  Default target: x86_64-apple-darwin12.5.0
  Host CPU: corei7-avx
  http://dlang.org - http://wiki.dlang.org/LDC

  Registered Targets:
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64
$ nm -m typecons.o|grep 16__interfaceInfosZ | head -4
0000000000081d00 (__DATA,__const) external __D3std5range20__T12ForwardRangeTiZ12ForwardRange16__interfaceInfosZ
0000000000081d20 (__DATA,__const) external __D3std5range26__T18BidirectionalRangeTiZ18BidirectionalRange16__interfaceInfosZ
0000000000081d40 (__DATA,__const) external __D3std5range26__T18RandomAccessFiniteTiZ18RandomAccessFinite16__interfaceInfosZ
0000000000088570 (__DATA,__datacoal_nt) weak external __D3std5range68__T16InputRangeObjectTS3std5range15__T4iotaTiTiTiZ4iotaFiiiZ6ResultZ16InputRangeObject16__interfaceInfosZ

@dnadlinger
Copy link
Member

I don't really have a good idea what could be going on here, unfortunately. To track this down, I'd probably check what is going on at the IR level, and if it's indeed a case of a global being emitted as a constant, just add a breakpoint to the emission code (with a condition on the name of the affected symbol).

@smolt
Copy link
Member

smolt commented Apr 5, 2014

Good idea. I'll try that.

@smolt
Copy link
Member

smolt commented Apr 6, 2014

I spent some time in gdb today. The issue seems to happen when there is a interface inheritance chain consisting of templates. The code in IrAggr::addFieldInitializers() iterates through the immediate vtbInterfaces and calls getInterfaceVtbl() for each, changing the linkage to weak. However, all the super interfaces are not visited and the linkage is not changed from ExternalLinkage. I feel like there should be a recursive call somewhere in there, but don't know my way around ldc code well enough to attempt yet.

@dnadlinger
Copy link
Member

@smolt: Good catch! Just to be sure, the problematic interfaces are actually templates, i.e. are supposed to be emitted as weak data, right?

@smolt
Copy link
Member

smolt commented Apr 6, 2014

Yes. Here is a small sample.

module a;  // a.d
interface Apple {}

interface Banana(T) : Apple
{
    // my virtual interface InfosZ array is not weak (bummber)
}

class Cranberry(T) : Banana!T
{
    // my virtual interface InfosZ array is weak (yeah)
}

Cranberry!int x;

$ ldc2 -c a.d
$ nm -m a.o | grep InfosZ
0000000000000330 (__DATA,__const) external __D1a13__T6BananaTiZ6Banana16__interfaceInfosZ
0000000000000040 (__DATA,__datacoal_nt) weak external __D1a16__T9CranberryTiZ9Cranberry16__interfaceInfosZ

@smolt
Copy link
Member

smolt commented Apr 6, 2014

Oops. Need to learn markdown ;-)

@dnadlinger
Copy link
Member

I took the liberty to add code tags. Not that hard. ;P

redstar pushed a commit that referenced this issue Sep 27, 2014
Add types and constants for Linux/PPC64.
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

5 participants