[llvm-dev] RFC: A new ABI for virtual calls, and a change to the virtual call representation in the IR

Peter Collingbourne via llvm-dev llvm-dev at lists.llvm.org
Thu Mar 3 22:31:01 PST 2016


On Mon, Feb 29, 2016 at 1:53 PM, <> wrote:

> Hi all,
>
> I'd like to make a proposal to implement the new vtable ABI described in
> PR26723, which I'll call the relative ABI. That bug gives more details and
> justification for that ABI.
>
> The user interface for the new ABI would be that -fwhole-program-vtables
> would take an optional value indicating which aspects of the program have
> whole-program scope. For example, the existing implementation of
> whole-program
> vcall optimization allows external code to call into translation units
> compiled with -fwhole-program-vtables, but does not allow external code to
> derive from classes defined in such translation units, so you could request
> the current behaviour with "-fwhole-program-vtables=derive", which means
> that derived classes are not allowed from outside the program. To request
> the new ABI, you can specify "-fwhole-program-vtables=call,derive",
> which means that calls and derived classes are both not allowed from
> outside the program. "-fwhole-program-vtables" would be short for
> "-fwhole-program-vtables=call,derive,anythingelseweaddinfuture".
>

Based on discussion with John McCall in PR26723, I’d like to change the
user interface for -fwhole-program-vtables, and introduce an interface
specifically to enable the relative ABI. That interface would be based on a
whitelist rather than a blacklist, and together with
-fwhole-program-vtables would enable devirtualization, virtual const prop,
and virtual function stripping for those classes.

The new user interface is as follows:

We would introduce two new attributes, [[clang::unstable_abi]] and
[[clang::stable_abi]], which would be attached to a class and would enable
or disable the unstable ABI for that class. It is an ODR violation to use
[[clang::unstable_abi]] in two translation units compiled with different
versions of Clang (we may consider extending the object format to allow a
linker to diagnose this). Specifically, mixing different head revisions or
major releases is not allowed, but mixing different point releases is fine.
The attribute __declspec(uuid()) (which is used for COM classes on Windows)
would imply [[clang::stable_abi]].

A “dynamic-introducing” class is a class that declares new virtual member
functions or virtual bases, and has no dynamic bases or virtual bases. A
class that is dynamic but not dynamic-introducing would use the same ABI as
its dynamic base classes. The compiler will diagnose if a class has two or
more dynamic bases with different ABIs, or if the bases have a different
ABI from the one explicitly specified by an attribute.

The ABI for a dynamic-introducing class is determined from the attribute,
or if the class has no attribute, from the following flags:

-funstable-c++-abi or -funstable-c++-abi-classes would enable the unstable
C++ ABI for all classes (the idea being that -funstable-c++-abi would also
cover any unrelated ABI breaks we may want to make in future).
-funstable-c++-abi-classes=PATH would enable the unstable C++ ABI for
dynamic-introducing classes specified in the file at PATH.
The -fwhole-program-vtables-blacklist flag would be removed, and I'm no
longer proposing that -fwhole-program-vtables would take a value. The
whole-program blacklist would be replaced by either inference based on
visibility or a new [[clang::no_whole_program]] attribute.

It is effectively an ODR violation to define a class that uses the unstable
ABI in a translation unit compiled with a different set of
-funstable-c++-abi* flags. It is also a violation for a linkage unit other
than the one compiled with -fwhole-program-vtables to define any of the
classes that use the unstable ABI.

The format of the file is a series of lines ending in either * or **.
Preceding that is a namespace specifier delimited by double-colons followed
by “::”, or the empty string to denote the global namespace. Each entry in
the list indicates that dynamic-introducing classes in that namespace,
including nested classes, classes defined in enclosed anonymous namespaces,
and classes defined within member functions of those classes, use the
unstable ABI. If the line ends in “*” this applies to the given namespace
only, while if the line ends in “**” it applies to the given namespace and
any enclosed namespaces.

In Chromium for example, the contents of the file would look like this:

*
app::**
base::**
browser::**
[...]
wm::**
zip::**

This whitelist specifies that classes defined in the global namespace as
well as app, base, browser etc. and any enclosed namespaces would use the
unstable ABI. This list excludes std::**, so we can continue to use the
system standard library. If Chromium did start using its own copy of the
standard library, we could create another whitelist with that entry in it,
or just use the -funstable-c++-abi-classes flag.

We would also add a new warning: -Wc++-stable-abi. This would warn for any
classes defined in non-system header files that are inferred from
namespaces to use the stable ABI. This warning would be intended to be used
by programs that intend to use the unstable ABI for any non-system classes
(such as Chromium).

Control flow integrity (-fsanitize=cfi*) would also only be supported for
classes using the unstable ABI, and would require the
-fwhole-program-vtables flag, unless the cross-DSO mode
(-fsanitize-cfi-cross-dso) is enabled.

Next steps:

I will send out a patch that implements the semantic analysis side of this.
Once that lands, follow-up patches will actually start changing the
unstable ABI.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160303/79ce9df3/attachment.html>


More information about the llvm-dev mailing list