[ms-cxxabi] Set proper SRet flags for most functions; also handle empty struct arguments correctly
John McCall
rjmccall at apple.com
Tue Apr 9 12:55:38 PDT 2013
On Apr 9, 2013, at 12:37 PM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
> 2013/4/9 John McCall <rjmccall at apple.com>:
>> On Apr 9, 2013, at 11:17 AM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>>> 2013/3/28 John McCall <rjmccall at apple.com>:
>>>> On Mar 26, 2013, at 7:23 PM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>>>>> 2013/3/26 John McCall <rjmccall at apple.com>:
>>>>>> On Mar 26, 2013, at 6:27 PM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>>>>>>> 2013/3/26 Timur Iskhodzhanov <timurrrr at google.com>:
>>>>>>>> 2013/3/22 John McCall <rjmccall at apple.com>:
>>>>>>>>>
>>>>>>>>> On Mar 21, 2013, at 1:45 PM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
>>>>>>>>>
>>>>>>>>>> Hi John,
>>>>>>>>>>
>>>>>>>>>> Please see the attached patch.
>>>>>>>>>>
>>>>>>>>>> It addresses most of the Clang-side change needed to fix http://llvm.org/PR13676
>>>>>>>>>
>>>>>>>>> + bool IsMicrosoftABI = getContext().getTargetInfo().getCXXABI().isMicrosoft();
>>>>>>>>> +
>>>>>>>>> if (isAggregateTypeForABI(RetTy)) {
>>>>>>>>> if (const RecordType *RT = RetTy->getAs<RecordType>()) {
>>>>>>>>> // Structures with either a non-trivial destructor or a non-trivial
>>>>>>>>> // copy constructor are always indirect.
>>>>>>>>> - if (hasNonTrivialDestructorOrCopyConstructor(RT))
>>>>>>>>> + if (hasNonTrivialDestructorOrCopyConstructor(RT) ||
>>>>>>>>> + (IsMicrosoftABI && hasNonTrivialDefaultConstructor(RT)))
>>>>>>>>>
>>>>>>>>> Please don't compute IsMicrosoftABI before it's needed.
>>>>>>>> Done.
>>>>>>>>
>>>>>>>>> Are you sure it's just that the *default* constructor is non-trivial, or is it
>>>>>>>>> the presence of *any* non-trivial constructor, or possibly even any
>>>>>>>>> explicit constructor?
>>>>>>>> I've made some more experiments and it seems the condition is rather
>>>>>>>> "is this a POD?", e.g. we should use SRet if A has a virtual function
>>>>>>>> or a destructor or an assignment operator (but not "void
>>>>>>>> operator=(int);") or a private member or a base class.
>>>>>>
>>>>>> Interesting, okay. I guess we'll assume that that means the C++98
>>>>>> definition of POD.
>>>>>>
>>>>>>>> See the attached updated patch.
>>>>>>>>
>>>>>>>> I was a bit lazy to write tests for all these cases, will add them
>>>>>>>> later if we ever find new incompatibilities.
>>>>>>>> I've also added a couple of tests for the upcoming byval compatibility
>>>>>>>> cleanup with FIXMEs.
>>>>>>
>>>>>> + bool IsMicrosoftABI = getContext().getTargetInfo().getCXXABI().isMicrosoft();
>>>>>> // Structures with either a non-trivial destructor or a non-trivial
>>>>>> // copy constructor are always indirect.
>>>>>> - if (hasNonTrivialDestructorOrCopyConstructor(RT))
>>>>>> + if (hasNonTrivialDestructorOrCopyConstructor(RT) ||
>>>>>> + (IsMicrosoftABI && !isPOD(RT)))
>>>>>>
>>>>>> Let's just abstract this decision into the C++ ABI. In both the argument
>>>>>> and the return-type cases, when you're working with a RecordType and
>>>>>> the decl is a CXXRecordDecl, just ask the current CGCXXABI.
>>>>> Should I abstract out only the isAggregateTypeForABI() branches or the
>>>>> classifyReturnType/classifyArgumentType functions completely?
>>>>> What should the interface method return, an ABIArgInfo?
>>>>
>>>> I'm thinking:
>>>>
>>>> bool isReturnTypeIndirect(const CXXRecordDecl *) const;
>>> Done for X86_32ABIInfo, please see the attached patch.
>>>
>>> If that looks OK - I assume I should do the same for other ABIInfos ?
>>> (I hope they are covered with tests well...)
>>>
>>>> /// How should we pass a particular record type as an argument?
>>>> enum RecordArgABI {
>>>> /// Pass it using the normal C aggregate rules for the ABI, potentially
>>>> /// introducing extra copies and passing some or all of it in registers.
>>>> RAA_DirectInRegisters,
>>>>
>>>> /// Pass it on the stack using its defined layout. The argument must be
>>>> /// evaluated directly into the correct stack position in the arguments area,
>>>> /// and the call machinery must not move it or introduce extra copies.
>>>> RAA_DirectInMemory,
>>>>
>>>> /// Pass it as a pointer to temporary memory.
>>>> RAA_Indirect
>>>> };
>>> I'm not sure I can effectively use the first two cases right now and
>>> there should also be RAA_IndirectByval (see what I do for Microsoft
>>> ABI), so I've created a slightly simpler enum.
>>
>> Despite how it looks in IR, "byval" is direct in memory.
>>
>> Just to be clear, the Itanium ABI would use RAA_Indirect if the copy constructor
>> or destructor is non-trivial and RAA_DirectInRegisters otherwise, and the
>> MS ABI would use RAA_DirectInMemory if there's any non-trivial constructor or
>> destructor and RAA_DirectInRegisters otherwise.
> Oh, I see.
> Will do the change.
>
> Is everything else OK?
> Should I need another round of review when I change the other spots to
> use these two new CGCXXABI methods?
Yeah, I haven't looked at the rest of your patch; I'll just review the new one
when it's ready.
John.
More information about the cfe-commits
mailing list