<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 13 Nov 2019, at 02:33, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:</div><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 12, 2019 at 2:36 PM Christoffer Lernö <<a href="mailto:christoffer@aegik.com" class="">christoffer@aegik.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;" class=""><div class="">The advantages:</div><div class=""><br class=""></div><div class="">1. A pointer to the struct offset can be converted to a pointer without any cost.</div><div class="">2. A nullpointer to a stretchy buffer can be treated as a zero length array. Consequently no actual struct allocation is needed to represent a zero length array.</div></div></blockquote><div class=""><br class=""></div><div class="">(2) could probably be done as well with the other representation (with the prefix data representation you'd still have to special case the null test before going backwards from the pointer to find the size - because you wouldn't want to go backwards from null and try to read bytes there to find the size).</div></div></div></div></blockquote><div><br class=""></div><div>But that runs into (1).</div><div><br class=""></div><div>In the stretchy buffer, converting to a pointer is essentially a NOP.</div><div><br class=""></div><div>For the case you suggest, with the solution in (2) would be the following:</div><div><br class=""></div><div>1. Is it NULL? If so return NULL.</div><div>2. Otherwise return current pointer + size of header as the pointer to the data.</div><div><br class=""></div><div>There is then the question of what happens to indexing.</div><div><br class=""></div><div>If we do the above conversion to pointer then we are doing an addition comparison and add.</div><div><br class=""></div><div>For deref we can optimize away the NULL check for indexing though (assuming UB to index an array out of bounds), for x86 I think the add is included in indexing, but for ARM it’s not.</div><div><br class=""></div><div>It might be a small cost to pay.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;" class=""><div class="">3. A reference to the array is the same size as to a pointer.</div></div></blockquote><div class=""><br class="">(3) Would be true with either representation I'm picturing. (pointing to the start of the struct you've described, rather tahn pointing to the trailing array and walking backwards to find the rest)<br class=""></div></div></div></div></blockquote><div><br class=""></div>Compared to implementations like std::vector I meant.</div><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;" class=""><div class="">4. It can be converted to and back from an pointer without losing any information about the size & capacity.</div></div></blockquote><div class=""><br class="">Converting back you have to know it's the start of an array, though, right? (& you could still do that in the other representation - by subtraction, but yes, wouldn't be free/zero-cost)<br class=""></div></div></div></blockquote><div><br class=""></div>Here I’m again mostly thinking about std::vector.</div><div><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;" class=""><div class="">The downsides are what we discuss. But it looks like I have to accept that I can only represent it as a pointer with unknown length in DWARF then?<br class=""></div></div></blockquote><div class=""><br class="">I imagine it'd be difficult to describe the calling convention for passing this array? Are you going to have instances of this on the stack and passed by value? or only ever individually dynamically allocated & pointed to from other places?<br class=""></div></div></div></blockquote><div><br class=""></div>The array is always passed as reference, but could potentially be put on the stack but would still always be used as a reference.<br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""><br class="">If they were individually dynamically allocated & only ever pointed to the trailing array - the DWARF for that'd be pretty simple - basically just a special pointer type. The pretty printer for it would know it was allowed to walk backwards to find some extra things (as would any member functions, if needed, be implemented in terms of walking the poniter back).<br class=""></div></div></div></blockquote><div><br class=""></div>Alright, so then maybe this is solvable after all? Is there any docs on how to do this the proper way in LLVM? And perhaps also where to patch this into a fork of LLDB?</div><div><br class=""></div><div>Best Regards,</div><div><br class=""></div><div>Christoffer</div></body></html>