This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: solving c++ Linkage/binary compatibility problems


> Date: Fri, 15 Dec 2000 12:12:34 +0100
> From: Uwe Pachler <uwe.pachler@jk.uni-linz.ac.at>
> To: gcc@gcc.gnu.org

> I know that these problems are 'solved' using a copy of the library
> for each version (where ldconfig creates symlinks appropriately),
> but is this really the best solution?

> Wouldn't it be better to introduce a better runtime linkage mechanism
> that resolves method names directly, rather than using indices into a
> virtual table that is created upon compile time?

> The mechinism would have following features:
> (when I say link time I mean linkage to a dynamic library)
> * Resolve all method calls on link time.
> * Calculate Object sizes (for objects created on the stack, i.e as local
> variable) on link time.
> * Build vtable on link time (for classes defined in the application that
> are derived from classes in the library)

The short answer is `speed and efficiency' or `abi stability', pick
any one.  In C++, we have chosen the first, you seem to want the
second.  It is hard to just change C++, as then it would be much
slower, and quite a lot of people would probably not want this.

In C++, one can get all the abi stability one wants, for a certain
cost through the use of specific coding conventions.  For example, if
one would write:

object.h:
struct A {
      int i;
} a;
int foo(A &a);

main program:
#include <object.h>

int main() {
    A a1;
    print(a.i);
    foo(a1);
}

one can instead write:

object.h:
#include <Integer.h>
struct A {
private:
      Integer i;
public:
      static A* make_A();
      static A* get_global_a();
      Integer get_i();
} a;
int foo(A &a);

main program:
#include <object.h>

int main() {
    A *pa1 =  A::make_A();
    print(A::get_global_a()->get_i());
    foo(*pa1);
}

Notice how the use of ``A'' no longer constrains the actual
implementation of A to be a certain size.  But, this comes at a
certain cost, heap allocation instead of stack allocation, extra calls
into the library, three extra functions in the executable and so on.
Also, notice that the problem of running out of bits in i goes away.
Maybe i was used to count dollars, and the economy grew and we needed
more than 2 billion.

Notice how one can get the abi stability within the confines of C++,
it just happens to come with a certain cost.  In the above short
snippet, of code, we went from a complexity of 9 to a complexity of
17, or about twice the cost in terms of just the use of the library.
In time, we may in fact add features to the compiler, to allow for
greater abi portability, while preserving most of the speed...  this
will be considerable work.

Also, take a look at the SGI C++ STL library.  It has few abi
problems, as there aren't any object files.  The cost is that every
use of it has to see the full source code of it, all the time.
However, it does delay creating a binary, until you do your
application compile.  If all such libraries in a system used that
method, then the abi would only be set when the final app was
compiled.  The cost of this technique, would be that there would be no
sharing of compiled library code between applications, redundant
compilation of the same code, over and over again and so on.  It is
this sharing that causes the abi breakage, if you will, so by
eliminating the sharing, you eliminate the problems.

So, you can get it, but it'll cost you, one way or another.  In the
longer term, you have a language that is flexible enough so that you
can get the semantic simplicity in a natual fashion (the first code
sequence), but will have the semantics more like the second code
sequence, and the optimizer, as late as run time, will notice you need
this code to run fast and will on demand get you the short instruction
sequences of the first code sequence.  In time, just now right now.

And some time after that, you'll have library code that will rewrite
the parts of your application that used an older version of it, so
that the use of it is more correct, or better, or faster, or more
maintainable.  You can start to see this feature in things like the
warnings GNU ld will spit out for gets.  The library tries to get the
person that does the link to rewrite the application that uses gets,
to not use it.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]