[PATCH] introduce attribute exalias

Alexandre Oliva oliva@adacore.com
Sat Aug 15 16:39:49 GMT 2020


On Aug 15, 2020, Iain Sandoe <iain@sandoe.co.uk> wrote:

>  * if the target ABI does not support symbol aliases, then this facility cannot
>    be used.

True.  I'm surprised there are modern platforms that don't.

What is it that stands in the way?  Lack of support for .set in the
assembler?  If that's the case, couldn't it possibly be worked around by
setting multiple global labels at the same spot?  I'm pretty sure
setting multiple labels at the same address is used and relied on quite
often.

>    will exclude the GCC targets without symbol aliases from Ada.

It's not so dire.  Developers for alias-deprived systems would have to
use the mangled names instead.  That would be a little painful, but not
even close to making the language unavailable.

>  * The process shifts the onus on representation to the exporter and thus there
>    can now be 3 library vendors who all thought “MY_FOO_FUNC” was the
>    best representation for an export - these will now clash in the “shorthand”
>    namespace, although their C++ mangling might well not.

Using this to disqualify the new feature would also disqualify regular
aliases, that could be used for just the same purpose of making symbols
available under chosen names:

  extern "C" typeof(foo::func)
  __attribute__((__alias__("<mangling for foo::func>")))
  MY_FOO_FUNC;

Now, this concern appears to be focused on binary-only libraries.  Since
we haven't seen vendors rush to make their library internals available
under shorter aliases, polluting the symbolic namespace, I see little
reason for concern about this possibility.

When it comes to binary-only libraries, the ABI is often set in stone,
and it's up to users to figure out the symbol names in the ABI and use
them.  If they vary across target platforms, that's inconvenient, but
nothing new.

I expect this feature to be used and useful within multi-language
projects, particularly when using, as part of their interfaces,
shorthand typedefs whose encoding varies depending on the platform.
E.g., consider a function or a template instantiation that takes a
int64_t parameter.  Depending on whether int64_t maps to long or long
long, you get different encodings, thus references using the symbol name
have to be adjusted depending on what type stdint.h maps int64_t to.

>  * it’s not universally usable without “rebuilding the world” and having access to
>    source for everything you might want to import

You mean it does not bring improvements to situations in which you can't
introduce nicknames for third-party symbols.  You then figure out and
import the mangled names and move on.

>  * what happens for templates and overloads - presumably the Ada import has
>    add the relevant (albeit abbreviated) decorations?

They don't matter to the proposed design.  The reason they come up for
you is that you have a completely different solution in mind that
requires this kind of resolution.  The one I'm proposing attaches the
extra aliases directly to the target language entity, be it one of the
overloads of a member function, be it a specialization of a template
function.

>  * One can’t have an arbitrary re-name; it has to be supported by the target
>    assembler (not that this is a new constraint, but it prevents the exported
>    name from being an exact representation of the human-readable C++ interface
>    in general).

*nod*.  It couldn't be a target for alias attributes otherwise, and I
found that a desirable property to make the new feature useful even for
standalone C++.

> —— are there other possibilites to solve the underlying issue?

>  C++ mangled names have some proven good properties:

>  * they convey all the relevant information about the interface
>  * they are standardized, and work between implementations from different
>   ‘vendors’ or OSS compilers on the same platform.
>  * they are not going to clash.

* they require so much symbolic information that in order to perform
mangling you pretty much have to #include all of the relevant C++
headers.

Consider typedefs, templates with partial or explicit specializations,
default template arguments, besides the possibility of varying
definitions across platforms.

> what about annotating the import pragma in some way such that the platform
> mangling is applied by the compiler?

That would indeed be desirable, but it is unfortunately not viable.

Consider you have to figure out the correct mangling for this:

  foo::bar<std::iostream&, std::string, u64, g::h>::f

Is foo a namespace, a canonical class name, or a typedef?  (maybe even a
using declaration, or even something brought into the global namespace
by a using directive)

If it's a typedef, what's the canonical name?  (it could be a template
instantiation)

bar is clearly a template type, so you "just" need enough symbolic
information to be able to mangle std::iostream&, std::string, u64,
g::h.

For u64, you just have to look at stdint.h to see which of the
C++-defined types is maps to.

g::h is a mystery.  It could be a type, a function, a member function, a
variable, a data member...

There could be any subsequent template parameters using defaults.  Even
if we were to simplify this (and make it inconvenient for the user)
requiring no defaults to be relied on, that wouldn't get you much
farther.

Finally, we get to f.  We can assume it's not a template type, nor a
template member function, so it would have to be (assuming a well-formed
symbolic reference) a static or non-static data member, a static or
non-static member function, a typedef, a nested type; possibly a
template instantiation, using defaults?).

It could even name an overload set, so you might want to require a
parameter list, and an explicit template parameter list.


We could then require all of this symbolic information, in the form of
type, variable and function declarations, including partial and explicit
specializations, and the transitive closure thereof.

How would you get all of this symbolic information to the compiler of
the Ada unit importing such C++ symbols?  Parsing C++ headers?
Requiring users to bring the relevant declarations into the Ada program?
Searching the symbol tables of object files that would have to have
alreayd been compiled, looking for a match?  None of these are good.

Extracting symbolic information from C++ headers (à-la -fdump-ada-spec,
but with a *lot* more symbolic info) in a first pass, and referencing
that in your imports.  Viable, a *lot* of work, and also a big doh!
-fdump-ada-spec would already get you the Imports with the mangled
names.

This feature is for when you don't want to go through all this trouble,
and would rather reference a few C++ symbols directly in your
target-independent sources.

> it’s nice when an attribute reads in the source to tell you its purpose.

*exporting* is heavily overloaded, so I've been avoiding it.  One thing
the proposed feature does NOT do is to make the alias more visible than
the original symbol.  If it's internal, hidden or protected, or even if
it's local, it won't get exported.  You could use it, and then another
alias declaration referencing it, to get it exported, if you wish, but
that was enough of a reason for me to stay away from the term "export".

> *** right now Darwin fails silently (there doesn’t seem to be the usual error
>  that the target doesn’t support that kind of alias).

Hmm, thanks, I will make sure there's some more verbose failure mode if
we can't find a way for something akin to an alias to be usable there.

-- 
Alexandre Oliva, happy hacker
https://FSFLA.org/blogs/lxo/
Free Software Activist
GNU Toolchain Engineer


More information about the Gcc-patches mailing list