For this C code: typedef struct s2 { char s2C1 , s2C2; } s2td; clang generates: %struct.s2 = type { i8, i8 } which I lets llvm decide on the actual layout of this type. For the return statement in: struct s2 fs2 ( char fs2p1 ) { struct s2 ls2; ls2.s2C1 = 'B'; ls2.s2C2 = fs2p1; return ls2; } I see this IR: %struct.s2 = type { i8, i8 } define i16 @fs2(i8 signext %fs2p1) #0 { entry: %retval = alloca %struct.s2, align 1 ; [#uses=2 type=%struct.s2*] ... %3 = bitcast %struct.s2* %retval to i16*, !dbg !46 ; [#uses=1 type=i16*] [debug line = 25:0] %4 = load i16* %3, align 1, !dbg !46 ; [#uses=1 type=i16] [debug line = 25:0] ret i16 %4, !dbg !46 ; [debug line = 25:0] } which returns the struct in a scalar i16. I have three questions about this. 1) Larger structs are returned differently, via memcpy. Do these methods of returning struct values show through in the ultimately generated machine code? It seems hard to imagine that, of the many different target code generators in llvm, there would not be at least some with standardized ABIs that differ in such respects. Does llvm make target- dependent transformations for different targets to match their ABIs? Or do I have to do that at the level of generating llvm IR? 2) To correctly return the value using a bitcast, as in the example, the front end has to independently and correctly duplicate the layout that llvm will produce. This seems both very fragile and difficult to diagnose when it fails. My front end already does record layout, but I had previously decided, after a discussion on this list, that it was better to let llvm do it. Any advice on the best way here? 3) I am also a little worried about the implications of returning an i16, with alignment of 1. Won't this create trouble somewhere, or at least lose some benefit of returning as a scalar? -- Rodney Bates rodney.m.bates at acm.org
On Tue, Jan 20, 2015 at 9:52 AM, Rodney M. Bates <rodney_bates at lcwb.coop> wrote:> > 1) Larger structs are returned differently, via memcpy. Do > these methods of returning struct values show through in > the ultimately generated machine code? It seems hard to > imagine that, of the many different target code generators > in llvm, there would not be at least some with standardized > ABIs that differ in such respects. Does llvm make target- > dependent transformations for different targets to match > their ABIs? Or do I have to do that at the level of generating > llvm IR? >LLVM handles the low-level ABI details like what registers to use for arguments, but frontends unfortunately need to handle lots of ABI issues around struct passing. LLVM isn't really responsible for transforming IR to make it match any particular ABI.> 2) To correctly return the value using a bitcast, as in the example, the > front end has to independently and correctly duplicate the layout that > llvm will produce. This seems both very fragile and difficult to > diagnose when it fails. My front end already does record layout, but > I had previously decided, after a discussion on this list, that it was > better to let llvm do it. Any advice on the best way here? >Personally, I wouldn't recommend letting LLVM do struct layout. I would recommend creating high-level LLVM struct types, but the frontend should use packed struct types to precisely control the layout. In that way, the frontend can still make assumptions about the exact layout in memory. Make sense? In this particular case, probably all you need to know is the size of the struct, and notice that it is small. I would try to find the Sys V ABI docs to get the threshold or check the Clang source code.> 3) I am also a little worried about the implications of returning an > i16, with alignment of 1. Won't this create trouble somewhere, or > at least lose some benefit of returning as a scalar?First, the optimizer will typically remove the alloca and the load. Second, the low alignment on the alloca and load looks like a bug in Clang. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150120/abb49774/attachment.html>
On 01/20/2015 12:45 PM, Reid Kleckner wrote:> On Tue, Jan 20, 2015 at 9:52 AM, Rodney M. Bates <rodney_bates at lcwb.coop <mailto:rodney_bates at lcwb.coop>> wrote: > > 1) Larger structs are returned differently, via memcpy. Do > these methods of returning struct values show through in > the ultimately generated machine code? It seems hard to > imagine that, of the many different target code generators > in llvm, there would not be at least some with standardized > ABIs that differ in such respects. Does llvm make target- > dependent transformations for different targets to match > their ABIs? Or do I have to do that at the level of generating > llvm IR? > > > LLVM handles the low-level ABI details like what registers to use for arguments, but frontends unfortunately need to handle lots of ABI issues around struct passing. LLVM isn't really responsible for transforming IR to make it match any particular ABI. > > 2) To correctly return the value using a bitcast, as in the example, the > front end has to independently and correctly duplicate the layout that > llvm will produce. This seems both very fragile and difficult to > diagnose when it fails. My front end already does record layout, but > I had previously decided, after a discussion on this list, that it was > better to let llvm do it. Any advice on the best way here? > > > Personally, I wouldn't recommend letting LLVM do struct layout. I would recommend creating high-level LLVM struct types, but the frontend should use packed struct types to precisely control the layout. In that way, the frontend can still make assumptions about the exact layout in memory. Make sense? >So, if I build the llvm struct type with packed attribute, will it just put every field in the next available bit? I see the two ways of accessing fields (GEP) and insertvalue/extractvalue both identify the field with a field sequence number, so I would have to be sure I could control the way llvm laid the struct out.> In this particular case, probably all you need to know is the size of the struct, and notice that it is small. I would try to find the Sys V ABI docs to get the threshold or check the Clang source code. > > 3) I am also a little worried about the implications of returning an > i16, with alignment of 1. Won't this create trouble somewhere, or > at least lose some benefit of returning as a scalar? > > > First, the optimizer will typically remove the alloca and the load. Second, the low alignment on the alloca and load looks like a bug in Clang.-- Rodney Bates rodney.m.bates at acm.org