Page MenuHomePhabricator

Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline

Debug Info: Support DW_AT_calling_convention on composite types.

Authored by aprantl on Jan 4 2018, 3:43 PM.



This implements the DWARF 5 feature described at

This allows a consumer to understand whether a composite data type is
trivially copyable and thus should be passed by value instead of by
reference. The canonical example is being able to distinguish the
following two types:

// S is not trivially copyable because of the explicit destructor.
struct S {
   ~S() {}

// T is a POD type.
struct T {
  ~T() = default;

To avoid bloating the debug info with calling convention attributes,
this patch only adds them were the calling convention is not obvious
from the context.

Implicitly by value is everything that clearly looks like a C struct, i.e.:

  • Non-C++ record types.
  • Types that define none of destructor, copy/move constructor, copy/move assignment operator.

Implicitly by reference is everything clearly looks like a non-pod type:

  • Types that define a destructor, a copy constructor, and a copy assignment operator.

Diff Detail


Event Timeline

aprantl created this revision.Jan 4 2018, 3:43 PM

I related D41039 (Add support for attribute "trivial_abi") which will also benefit from this feature. It is not a hard dependency though, this patch is also useful for standard C++.

rsmith added a subscriber: rsmith.Jan 4 2018, 4:06 PM
rsmith added inline comments.
2812–2814 ↗(On Diff #128664)

I do not believe this is sufficient. Consider:

struct A {
  A(const A&) = default;
struct B : A {};

Now, A is passed indirectly, because it has a non-trivial copy constructor (A::A(A&)). But B is passed directly, because it only has a trivial copy constructor, despite having an A subobject.

I would not expect debuggers to get intricacies like this right. (In general, determining how to pass a class like B can require performing template instantiation, which it's clearly not reasonable to expect a debugger to do.)

If you want to give the debugger a hint for any type that's non-POD (as the comment says), then use CXXRecordDecl::isPOD to determine that. I think it is reasonable to believe that a debugger will figure out that objects of POD types are passed direct.

2817 ↗(On Diff #128664)

"isTriviallyCopyable()" is the wrong thing to check here. The best you can do to get a per-type "calling convention" value is to call CGCXXABI::getRecordArgABI.

However, that does not tell the full story: in particular, in the MS ABI, member functions always return objects of class type indirectly, regardless of whether they could otherwise be returned in registers. If DWARF 5 allows you to override the calling convention on a particular usage of a type, you can check whether a function's return type should be indirect by calling CGCXXABI::classifyReturnType.

2821–2822 ↗(On Diff #128664)

The assignment operators are irrelevant here. Does any debugger really base its calling convention decision on their existence?

2825–2827 ↗(On Diff #128664)

Why are you not checking for move operations on this side?

Thanks! I think you got me convinced that we should probably stick the calling convention attribute unconditionally on all C++ types. At least in DWARF 5 it should be part of the abbreviation and thus almost free.

aprantl updated this revision to Diff 128686.Jan 4 2018, 5:00 PM

Just unconditionally emit the flags for all CXXRecordDecls. Richard convinced me that a debugger does not want to be in the business of determining the correct calling convention.

rsmith accepted this revision.Jan 4 2018, 5:10 PM

LGTM, thanks!

This revision is now accepted and ready to land.Jan 4 2018, 5:10 PM
This revision was automatically updated to reflect the committed changes.