<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Dec 3, 2013 at 9:18 PM, Nick Kledzik <span dir="ltr"><<a href="mailto:kledzik@apple.com" target="_blank">kledzik@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I’m working on mach-o support for the linker and want transparent support for mach-o as yaml or binary.  I also want to make sure that it is possible to make a mach-o linker that does *not* support yaml or archives (such as for an embedded JIT linker).  In working out how to do this I noticed a bunch of design issues in lld.  </div>
<div><br></div>1) LinkingContext has a bunch of oddball methods that have just been added because it was convenient (such as getDefaultHandler which is really only needed by the Archive Reader). <br>2) The native file format does not record the “universe” for the kind field of References.  That is, a mach-o file could be converted to native and an ELF file converted to native and both may have a reference of kind 42, but the same 42 has different semantics.<br>
3) identify_magic() is called redundantly in lots of places.<br>4) We don’t have a way for yaml to hand off control if a yaml test case contains heterogenous yaml file types.<br><div>5) Readers have been refactored into a trivial role.  They just instantiate some File subclass.</div>
<div><br></div><div><br></div><div>There is a design pattern that solves all these problems.  Have a global registry of “handlers”.  Require clients to call functions to which register the handlers they request.  Then any code that needs a handler calls the global registry to call the needed handler.</div>
<div><br></div><div>I see the need for three registries:  a file parser registry, a yaml document tag registry, and a kind string registry.</div><div><br></div><div>Here is one way to implement a registry for the file parser: </div>
<div><br></div><div><font face="Monaco" size="1">class InputParserRegistry {<br>public:<br>  // A function to quickly check if a file can be parsed.  Usually only the <br>  // magic parameter is checked.  But it can also check the file extension, or<br>
  // even look at more of the buffer if needed.<br>  typedef bool (*InputFileChecker)(file_magic magic, StringRef fileExtension, <br>                                   const MemoryBuffer &mb);<br>                                    <br>
  // A function to parse the supplied input file.<br>  typedef error_code (*InputFileParser)(std::unique_ptr<MemoryBuffer> &mb,<br>                                std::vector<std::unique_ptr<File>> &result);<br>
                                <br>  // Registers a checker and parser with the global registry. <br>  // Usually, the checker and parser are static methods in some lld::File <br>  // subclass that will be instantiated.<br>
  static void registerParser(InputFileChecker checker, <br>                             InputFileParser parser);<br>                                    <br>  // Walks registered checkers to parse the specified file.  <br>
  static error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,<br>                              std::vector<std::unique_ptr<File>> &result);<br>};<br></font><br><br></div><div>The mach-o linker tool would call:</div>
<div><font face="Monaco" size="1">   registryAddSupportMachO();</font></div><span style="font-family:Monaco;font-size:x-small">   registryAddSupportArchives();</span><br style="font-family:Monaco;font-size:x-small"><div><font face="Monaco" size="1">   registryAddSupportNative();<br>
</font><br></div><div>The implementation of registryAddSupportMachO would look like:</div><div><span style="font-family:Monaco;font-size:x-small">  void registryAddSupportMachO() {</span></div><div><font face="Monaco" size="1">    InputParserRegistry::</font><span style="font-family:Monaco;font-size:x-small">registerParser(FileMachO::check, FileMachO::parse);</span></div>
<div><font face="Monaco" size="1">  }</font></div><div><br></div><div>The code (in custom InputGraph nodes) no longer needs to call identify_magic, or look at the file extension, or handle archives.  All it does is:</div>
<div><div><font face="Monaco" size="1">  InputParserRegistry::</font><span style="font-family:Monaco;font-size:x-small">parseFile(_buffer, _files);</span></div></div><div><span style="font-family:Monaco;font-size:x-small"><br>
</span></div><div><div>I’ve looked at the llvm::Registry<> classes.  It does not seem to be a good match for what we need here:  It is designed around using static variables whose construction does the registration.  I prefer explicit calls to register to enable clients to *not* drag in support they don’t want.</div>
</div></div></blockquote><div><br></div><div>+1 for this. The last thing we need is static initializers.</div><div><br></div><div>-- Sean Silva</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div>  The  Registry<> model also assume you want to instantiate the object with the default constructor, which we don’t.  And we have no need for listeners or name/description. Yes, by overriding SimpleRegistryEntry and RegistryTraits we could use  llvm::Registry<>, but I’m not sure it is worth the effort.</div>
<div><br></div></div><div><br></div><div>Overall, I want to see what you think of this pattern.  Once we have it worked out, I want to do a similar registry for:</div><div>1) yaml doc tags (so that various kinds of yaml (archive, atom, mach-o, elf, etc) can be intermixed in one test case.</div>
<div>2) Add a namespace registry for kind values.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>-Nick</div><div><br></div></font></span></div><br>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br></blockquote></div><br></div></div>