"byval" when there is a non-trivial Destructor or Copy Constructor

re: passing c++ objects with copy constructors/destructors, there are multiple ABIs for doing this (e.g., the gcc way, msvc way). Is there a reason that the DefaultABIInfo’s classifyArgumentType doesn’t match either of the existing ABIs? It both makes a temp copy the gcc way, AND marks pointers as “byval”. All of the other ABIs (x86, arm, mips) which would check and do:

if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
return ABIArgInfo::getIndirect(0, /ByVal=/false);

to only have one temp copy. So, should the default not mark “byval”?

LE32 / PNaCl is currently using the default, and we would like avoid the extra copy from the “byval” attribute. If the default should not be changed, is it okay to add an LE32ABIInfo (for le32 / PNaCl) which diverges from the DefaultABIInfo in this way (no “byval” attribute on the pointer for non-trivial c++ objects)? If this second approach (adding LE32ABIInfo) is acceptable, please see attached patch w/ tests for le32 changes.

If the default should be changed, I can send another patch.

Thanks!

  • Jan

clang_le32_nontriv.patch (5.58 KB)

The default should probably be changed, given that passing a record
with a non-trivial copy constructor as byval can't possibly work.

-Eli

re: passing c++ objects with copy constructors/destructors, there are multiple ABIs for doing this (e.g., the gcc way, msvc way).

There are? How does MSVC do it that’s not just passing a pointer to a temporary? Is the callee responsible for copying into a temporary or something? I can’t imagine how that would work.

Is there a reason that the DefaultABIInfo’s classifyArgumentType doesn’t match either of the existing ABIs? It both makes a temp copy the gcc way, AND marks pointers as “byval”. All of the other ABIs (x86, arm, mips) which would check and do:

if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
return ABIArgInfo::getIndirect(0, /ByVal=/false);

to only have one temp copy. So, should the default not mark “byval”?

Yes, you’re right, the default should not mark byval.

John.

On MSVC, returning an class is roughly the same, but passing in a
class essentially does byval using the copy constructor instead of
memcpy. I think there's a PR open about the fact that there isn't any
way to represent this construct in IR at the moment.

-Eli

re: passing c++ objects with copy constructors/destructors, there are multiple ABIs for doing this (e.g., the gcc way, msvc way).

There are? How does MSVC do it that’s not just passing a pointer to a temporary? Is the callee responsible for copying into a temporary or something? I can’t imagine how that would work.

I don’t have good documentation on it, but there is a description of it: http://llvm.org/bugs/show_bug.cgi?id=5064. The temp copy is part of the argument stack, and the constructors are run with that arg stack slot as “this”.

Is there a reason that the DefaultABIInfo’s classifyArgumentType doesn’t match either of the existing ABIs? It both makes a temp copy the gcc way, AND marks pointers as “byval”. All of the other ABIs (x86, arm, mips) which would check and do:

if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
return ABIArgInfo::getIndirect(0, /ByVal=/false);

to only have one temp copy. So, should the default not mark “byval”?

Yes, you’re right, the default should not mark byval.

John.

Change to default attached.

clang_default_cpp.patch (736 Bytes)

Ah, interesting. Thanks.

John.