[cfe-dev] cfe-dev Digest, Vol 161, Issue 22

Christoffer Lernö via cfe-dev cfe-dev at lists.llvm.org
Fri Nov 13 04:07:51 PST 2020


Is it also C++ which will trigger the special case in GetX86_64ByValArgumentPair?

Here the comments state:

> // In order to correctly satisfy the ABI, we need to the high part to start
> // at offset 8.  If the high and low parts we inferred are both 4-byte types
> // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have
> // the second element at offset 8.  Check for this:

Here I am suspecting that struct Foo { int a; struct { } b; int c; } will create this situation in C++ but not in C. Is that a correct assumption?

Christoffer
AEGIK / www.aegik.se

> Date: Fri, 13 Nov 2020 09:44:54 +0000
> From: David Chisnall via cfe-dev <cfe-dev at lists.llvm.org>
> To: cfe-dev at lists.llvm.org
> Subject: Re: [cfe-dev] The x64 ABI lowering, direct pass of upper
> 	8-bytes, can it happen?
> Message-ID: <54e66ccf-58c7-263e-aa86-f5889ec1d272 at cl.cam.ac.uk>
> Content-Type: text/plain; charset=utf-8; format=flowed
> 
> To give a little bit more context:
> 
> C and C++ require that every field in a structure has a unique pointer 
> value (unless explicitly annotated in C++20) and C requires that a 
> pointer to the first field of an object is equivalent to a pointer to 
> the object.
> 
> This combination of constraints first means that `s3_0` in this example 
> will report a size of 1, but that byte is purely padding.  When we lay 
> out `s3_1`, we have a first field that is one byte (purely of padding) 
> followed by 7 bytes of padding to correctly align `b`.  This adds up to 
> 8 bytes of padding.
> 
> No one would write that by hand deliberately, but you can encounter 
> things like this when you use std::conditional_t in a C++ class to do 
> something like:
> 
> ```c++
> struct Placeholder {};
> 
> template<typename T = void>
> struct SomeClass
> {
> 	std::conditional_t<std::is_same_v<T, void>, T, PlaceHolder> extra_data;
> 	long unconditional_field;
> 	...
> };
> ```
> 
> This pattern is quite useful for classes where you want to provide an 
> extension point for carrying some extra state but still support the case 
> where the instantiating code doesn't want to provide any.  Prior to 
> C++20 there was no standard way of ensuring that the placeholder didn't 
> take up any space.  If you happened to pick the first field of the 
> object for this field then you could end up with something equivalent to 
> Craig's example, where you have 8 bytes of padding at the start of 
> `SomeClass` before `unconditional_field`.
> 
> In C++20, you can write this:
> 
> ```c++
> struct Placeholder {};
> 
> template<typename T = void>
> struct SomeClass
> {
> 	[[no_unique_address]]
> 	std::conditional_t<std::is_same_v<T, void>, T, PlaceHolder> extra_data;
> 	long unconditional_field;
> 	...
> };
> ```
> 
> Now, if `extra_data` gets the type `PlaceHolder`, `(char*)&extra_data == 
> (char*)&unconditional_Field`.  That's typically what you want, because 
> any accesses to `extra_data` will be guarded by a `constexpr if` that 
> checks that `T` is not `void` and so the field will not actually be 
> referenced at all in instantiations where it is not used to carry extra 
> state.
> 
> 
> David
> 
> 
> On 12/11/2020 22:13, Craig Topper via cfe-dev wrote:
>> Adding an assert(0) inside that if fires on this test case from 
>> clang/test/CodeGenCXX/x86_64-arguments.cpp
>> 
>> // PR5831
>> // CHECK-LABEL: define void @_Z2f34s3_1(i64 %x.coerce)
>> struct s3_0 {};
>> struct s3_1 { struct s3_0 a; long b; };
>> void f3(struct s3_1 x) {}
>> 
>> ~Craig

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20201113/f1450583/attachment.html>


More information about the cfe-dev mailing list