On 12/18/18 8:32 AM, Jakub Jelinek wrote: > On Tue, Dec 18, 2018 at 10:23:46AM -0500, Paul Koning wrote: >> >> >>> On Dec 17, 2018, at 2:23 PM, Szabolcs Nagy <szabolcs.n...@arm.com> wrote: >>> >>> On 17/12/2018 18:22, Uecker, Martin wrote: >>>>> >>>>> ... >>>> >>>> So a thread_local static variable for storing the static >>>> chain? >>> >>> something like that, but the more i think about it the >>> harder it seems: the call site of the nested function >>> may not be under control of the nested function writer, >>> in particular the nested function may be called on a >>> different thread, and extern library apis are unlikely >>> to provide guarantees about this, so in general if a >>> nested function escapes into an extern library then >>> this cannot be relied on, which limits my original >>> idea again to cases where there is no escape (which i >>> think is not that useful). >> >> I'm not sure I understand "escape" of a nested function pointer. >> >> Your description makes it sound like you're talking about a function being >> called by someone who has been given the pointer, from outside the scope of >> the function. That sounds like an illegal operation, exactly as it would be >> if you attempted to reference an automatic variable via a pointer from >> outside the scope of that variable. >> >> Did I misunderstand? > > The most common case is when you pass a call to a nested function > to some function that has a function pointer argument, e.g. qsort. > This is well defined with GNU nested functions, but the function that calls > the callback (qsort in this case) doesn't know it is a call to a nested > function. Right. This is the classic example and highlights the ABI concerns. If we use the low bit to distinguish between a normal function pointer and a pointer to a descriptor and qsort doesn't know about it, then we lose.
One way around this is to make *all* function pointers be some kind of descriptor and route all indirect calls through a resolver. THen you need either linker hackery or special code to compare function pointers to preserve ISO C behavior. Note that if you have a nested function and take its address, then go out of scope of the containing function, then that function pointer is no longer valid -- which makes perfect sense if you think about it. THe trampoline was on the stack and if you go out of scope of the containing function, then that stack frame is invalid and you also don't have a suitable frame chain to pass to the nested function either. Jeff