<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 16, 2017, at 1:02 PM, Seth Goldstein <<a href="mailto:seth@cmu.edu" class="">seth@cmu.edu</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">The basic goal is the support low-cost parallelism when necessary.</div><div class="">The wrapper function provides some glue which allows the original</div><div class="">function to be invoked as a micro-thread.</div><div class=""><br class=""></div><div class="">So, either the original function or the wrapper function will be</div><div class="">called, depending on certain conditions. There are no "ignorant"</div><div class="">translation units.</div></div></div></blockquote><div><br class=""></div>Can you elaborate on this? Is it a dynamic decision or a static decision? What</div><div>happens if we invoke the function as a micro-thread? — because presumably it</div><div>executes asynchronously to the caller, but since the function can have a return</div><div>value, and that return value can be used, we also presumably need to block on</div><div>the micro-thread. Does that mean that the return value is actually a future? How</div><div>far does the "future-ness" of the return value get propagated before we need to</div><div>force it?</div><div><br class=""></div><div>My intuition is that, if the goal is for this:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>// do some stuff here<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span>int result = foo(args);<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span>// do some more stuff here<br class=""><span class="Apple-tab-span" style="white-space:pre"> </span>return result;</div><div><br class=""></div><div>to not join the micro-thread until the return statement, then you will need to at least</div><div>insert the join code in an LLVM pass, because Clang does not do reliable</div><div>cross-statement data-flow analysis itself.</div><div><br class=""></div><div>Assuming that you don't really care about indirect calls — function pointers, C++</div><div>virtual functions, and so on — then it might be easiest overall to do almost all of</div><div>the work in an LLVM pass. Clang would just do the semantic checking on the</div><div>attribute and then propagate that down to the LLVM function. The LLVM function</div><div>would correspond to the normal, synchronously-executing version of the function.</div><div>Your pass would:</div><div><br class=""></div><div> 1. for each function so annotated, create a new micro-thread-spawning function using</div><div> some straightforward name-derivation scheme and</div><div><br class=""></div><div> 2. for each direct call to such a function, potentially rewrite the call to use the</div><div> micro-thread-spawning variant.</div><div><br class=""></div><div>Unfortunately, doing this on an LLVM level does mean that you might have to</div><div>mess around with some ABI ugliness. For example, if the synchronous function</div><div>has a return value that's returned indirectly, and the asynchronous variant just</div><div>returns a future, the attributes will need to be adjusted. Of course, if this is just an</div><div>academic proof-of-concept, then you could reasonably just add a semantic condition</div><div>that the return type has to be simple in some way — e.g. void, integers, pointers, that</div><div>sort of thing — and basically just wish this whole problem away.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">(In fact, as an extra, I would like the attribute</div><div class="">to be attached to both definitions and declarations so I can check the</div><div class="">use proper use of these functions.)</div></div></div></blockquote><div><br class=""></div><div>That's not the standard C rule, which is that attributes are inherited by redeclarations,</div><div>but it's certainly a reasonable enough goal — of course, the usual provisos of</div><div>cross-translation-unit semantic enforcement in C apply, but you can do your best.</div><div>To do this, you would want to make sure that it was not an InheritableAttr, and you'd</div><div>add some logic to Sema::mergeDeclAttributes.</div></div><div><br class=""></div><div>John.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div></div><div class="gmail_extra"><br clear="all" class=""><div class=""><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr" class=""><div class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">--------------</div><div class="">Seth Copen Goldstein</div><div class="">Carnegie Mellon University</div><div class="">Computer Science Dept</div><div class="">7111 GHC</div><div class="">412-268-3828</div></div></div></div></div></div>
<br class=""><div class="gmail_quote">On Wed, Nov 15, 2017 at 11:14 PM, John McCall <span dir="ltr" class=""><<a href="mailto:rjmccall@apple.com" target="_blank" class="">rjmccall@apple.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On Nov 15, 2017, at 10:32 PM, Seth Goldstein via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="m_3181211099063230633Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">I am wondering what the best approach would be to generate a wrapper</div><div class="">function for functions with a particular attribute. I.e.,</div><div class=""><br class=""></div><div class="">When the compiler sees</div><div class=""><br class=""></div><div class="">__attribute__ ((wrapthis)) int foo(args) {}</div><div class=""><br class=""></div><div class="">I want to generate foo as usual and also generate a function</div><div class=""><br class=""></div><div class="">int</div><div class="">foo_wrapper(args)</div><div class="">{</div><div class=""><span style="white-space:pre-wrap" class=""> </span>// do some stuff here</div><div class=""><span style="white-space:pre-wrap" class=""> </span>int result = foo(args);</div><div class=""><span style="white-space:pre-wrap" class=""> </span>// do some more stuff here</div><div class=""><span style="white-space:pre-wrap" class=""> </span>return result;</div><div class="">}</div><div class=""><br class=""></div><div class="">I am not sure where to generate the wrapper function, e.g., in clang,</div><div class="">in llvm? And, what pass could I look at that might provide me with</div><div class="">some hints about how to go about this. Any help would be appreciated.</div></div></div></blockquote><div class=""><br class=""></div></span>A feature like this could be implemented in many different ways, so it's hard to answer</div><div class="">your question without more basic information. How are you anticipating this wrapper</div><div class="">function being used? Are all existing uses of the function re-routed to it? Is it important</div><div class="">that "ignorant" translation units use the wrapper function? Is it important that ignorant</div><div class="">translation units <i class="">not</i> use the wrapper function? What's the basic goal here?</div><span class="HOEnZb"><font color="#888888" class=""><div class=""><br class=""></div><div class="">John.</div></font></span></div></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></body></html>