<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 11 March 2014 18:28, Mikael Persson <span dir="ltr"><<a href="mailto:mikael.s.persson@gmail.com" target="_blank">mikael.s.persson@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Hi all,<div><br></div><div>I recently picked up the Templight code (see <a href="http://plc.inf.elte.hu/templight/" target="_blank">http://plc.inf.elte.hu/templight/</a>) because I love the idea of having proper debugging and profiling tools for template meta-programming in C++. As admitted by the original authors (Zoltán Borók-Nagy, Zoltán Porkoláb and József Mihalicza), the code was rather crude, but a great first step. </div>
<div><br></div><div>-- Templight "version 2" -- (patch: templight_v2_clang35.diff)</div><div><br></div><div>So, I refactored the code to make it a bit more modular and less intrusive on the Sema class. Here is an outline of the main changes included in the attached patch (from Clang r202671):</div>
</div></blockquote><div><br></div><div>Hi Mikael,</div><div><br></div><div>Sorry to lead with this, but it's important. The llvm project requires that patches be submitted by their author (or authors). If you grabbed the original templight code and refactored it, then it may be coauthored between you and the original authors. Our policy requires that an author submit their own code, not mail in someone else's, see <a href="http://llvm.org/docs/DeveloperPolicy.html#attribution-of-changes" target="_blank">http://llvm.org/docs/DeveloperPolicy.html#attribution-of-changes</a> for specifics.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">
<div>Changes to existing Clang code-base:<br></div><div><br></div><div> (1) Moved the "ActiveTemplateInstantiation" class out of the Sema class scope, and into the clang namespace-scope. This was done to make the templight code independent from the Sema class by allowing a forward-declaration of ActiveTemplateInstantiation (can't be done if it is nested in Sema).</div>
</div></blockquote><div><br></div><div>Great! I think that ActiveTemplateInstantiation should be changed to a form of InstantiationRecord and held from the relevant AST nodes.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr">
<div> (2) Minor updates to reflect the above change in scope of the ActiveTemplateInstantiation class.<br></div></div></blockquote><div><br></div><div>The changes to ATI to pull it out of Sema and make it part of the AST are complicated enough, I think you should send that out as a first patch. It may not be much code, but for review we'll want to make sure that the representation is accurate to what the standard says, efficient in memory usage and has fast accessors.</div>
<div><br></div><div>There's also template instantiation for different reasons which are not currently recorded (ie., due to overload resolution, due to virtual methods). Since that's a change to ATI, that would logically go next.</div><div>
<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div></div><div> (3) Created a "TemplateInstantiationObserver" base-class which bundles callback functions that are called during the template instantiations (and when leaving them). This class also supports linked-list-style chaining of additional observers.<br></div></div></blockquote><div><br></div><div>I think we usually use "Callbacks" instead of "Observer", similar to PPCallbacks?</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>
</div>
<div> (4) Added a OwningPtr<TemplateInstantiationObserver> in the Sema class to hold the chain of template instantiation observers.<br></div><div><br></div><div> (5) Added callbacks for begin / end of template instantiations. These were added in all the places where the original Templight code had templight calls. This replaces the original templight tracing calls.</div></div></blockquote><div><br></div><div>At a high level, I think that what we currently do in Sema by tracking template instantiations as a stack (Sema::ActiveTemplateInstantiations) should be available in the AST after instantiation is complete. Then we could query the AST to ask why something was instantiated instead of tracing the act of instantiation. Is there any use case for templight where this wouldn't work?</div><div><br></div><div>Nick</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">
<div> (6) Added calls to initialize and finalize the template instantiation observers in the ParseAST code (see issues below).<br></div><div><br></div><div> (7) Added front-end options for Templight (mostly the same as in the original templight patch).</div>
<div><span><br></span></div><div>Changes to the Templight implementation: (unless noted here, the behavior is the same)</div><div>N.B.: The output (yaml, xml, txt) is *identical* to the original Templight code.</div>
<div><br></div><div> (8) All the templight code was moved out of the Sema class and into its own cpp-file. This was done mainly to avoid additional pollution in the Sema class, and to isolate the templight code's implementation dependencies (llvm support libs, yaml output code, etc.).</div>
<div><span><br></span></div><div> (9) Created the TemplightTracer class (derived from TemplateInstantiationObserver) to expose the functionality of Templight. This class is PImpl'd.</div><div><span><br>
</span></div><div> (10) Removed the "TemplightFlag" in favor of having created the tracer or not.</div><div><br></div><div> (11) Removed the "-templight-capacity" option because I changed the non-safe-mode to record the instantiation traces up to when the instantiations come back to the top-level context, at which point, I dump the traces. This will not affect the profiling because at the top-level context there is no pending timing or memory to be recorded. With this change, the number of traces recorded become proportional to the maximum instantiation depth (which is limited by the compiler), therefore making the templight-capacity redundant.</div>
<div><span><br></span></div><div> (12) Changed the recording of the traces to be stored in a std::vector, as opposed to a bare dynamic array.</div><div><span><br></span></div><div> (13) Added the "-templight-ignore-system" option to ignore (not traced) any template instantiation coming from a system-include header file.</div>
<div><br></div><div> (14) Updated the "creation" code where front-end options are pulled and used to create the tracer.</div><div><br></div><div><br>-- Templight GDB-style Debugger -- (patch: templight_v2_clang35_with_debugger.diff)<br>
</div><div><span><br></span></div><div>Here is the really sweet part. When I realized how easy it would be to create a gdb-style debugger with the new layout that I described above, I just had to give it a go, and the result is pretty nice, albeit still crude. I welcome you to try it!</div>
<div><span><br></span></div><div>I added the option "-templight-debugger" which turns on an interactive debugging session during the template instantiations. This is implemented in the TemplightDebugger class (also PImpl'd, and also deriving from TemplateInstantiationObserver). The debugger respects the relevant <span style="line-height:normal;font-size:small">templight</span> options (memory and ignore-system) and can be used in parallel with the templight tracer (although timing values will obviously be useless).</div>
<div><span><br></span></div><div>The debugger implements most of the basic gdb commands and reproduces its behavior as much as possible. You can set breakpoints (by complete name of template instantiation), you can "step", "next", "run", "kill", etc.. with the same behavior as gdb. You can print back-traces. And each time a template instantiation is entered or left, there is a structured print out similar to gdb, making it usable (I hope) in a GUI front-end similar to the various GUI front-ends to gdb.</div>
<div><span><br></span></div><div>This is really just a first draft of it, it's quite crude. I use C-style functions for the console input to avoid pulling in the C++ iostream monster (as required in coding standards of LLVM). And, as usual with interactive programs, it's hard to make sure that it is robust to people entering random nonsense.</div>
<div><span><br></span></div><div>Here are a few issues I'd like some feedback on:</div><div><br></div><div> (15) I feel that the XML output of the templight tracer could easily be nested, as opposed to having matched "Begin" and "End" blocks. </div>
<div><br></div><div> (16) I feel a bit uneasy about the place where the tracer / debugger get created, initialized and finalized. Currently, this is done in the "createSema" function and in the ParseAST code. It works this way, but it feels out-of-place. I don't know the Clang code-base well enough (in fact, barely at all) to know where this should go. Ideally, I would also like to get rid of the initialize / finalize functions in the TemplateInstantiationObserver class, but that is impossible as long as the Sema object and most of Clang's main structures are left to leak (always-on "-delete-free" option), as RAII is no longer available as a mechanism for handling the clean up. If anyone that understands Clang's main structures could weight in on this, I'd be glad to hear suggestions.</div>
<div><span><br></span></div><div> (17) Is there anything in LLVM/Clang that can help in terms of doing console input? Currently, I use <cstdio> functions and hand-written "tokenizing".</div><div><br>
</div><div> (18) I feel like the template debugger should be a separate entity (not an option to the main clang compiler), but at the same time, it needs the entire compilation process to be running, and so, if separate, it would have to be duplicate of clang with only small additions (in terms of code).</div>
<div><br></div><div> (19) Finally, I'd like to have ideas about what kind of diagnostic information that could be added to the debugger. Currently, it only prints out the name of the template instantiation, the location, and total memory usage. It would be nice to have features similar to GDB's "print" commands, like being able to print the list of template arguments and their values within the current context, and things like that. I simply don't have enough knowledge of Clang's code to know how to tap into that kind of information.</div>
<div><br></div><div><br></div><div>I know this was a long email, but I hope you had the interest to read up to here, and I hope to hear back.</div><div><br></div><div>Cheers,</div><div>Mikael.</div><span><font color="#888888"><div>
<br></div><div><br>
</div><div>-- <br>Sven Mikael Persson, M.Sc.(Tech.)<br>PhD Candidate, McGill University,<br>
</div></font></span></div>
<br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div>