| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
| "http://www.w3.org/TR/html4/strict.dtd"> |
| <html> |
| <head> |
| <title>System Library</title> |
| <link rel="stylesheet" href="llvm.css" type="text/css"> |
| </head> |
| <body> |
| |
| <div class="doc_title">System Library</div> |
| |
| <div class="doc_warning"> |
| <p>Warning: This document is a work in progress.</p> |
| </div> |
| |
| <ul> |
| <li><a href="#abstract">Abstract</a></li> |
| <li><a href="#requirements">System Library Requirements</a> |
| <ol> |
| <li><a href="#headers">Hide System Header Files</a></li> |
| <li><a href="#nofunc">No Exposed Functions</a></li> |
| <li><a href="#nodata">No Exposed Data</a></li> |
| <li><a href="#xcptns">No Exceptions</a></li> |
| <li><a href="#errors">Standard Error Codes</a></li> |
| <li><a href="#overhead">Minimize Overhead</a></li> |
| </ol></li> |
| <li><a href="#design">System Library Design</a> |
| <ol> |
| <li><a href="#opaque">Use Opaque Classes</a></li> |
| <li><a href="#common">Common Implementations</a></li> |
| <li><a href="#multi_imps">Multiple Implementations</a></li> |
| <li><a href="#lowlevel">Use Low Level Interfaces</a></li> |
| <li><a href="#memalloc">No Memory Allocation</a></li> |
| <li><a href="#virtuals">No Virtual Methods</a></li> |
| </ol></li> |
| <li><a href="#detail">System Library Details</a> |
| <ol> |
| <li><a href="#bug">Tracking Bugzilla Bug: 351</a></li> |
| <li><a href="#refimpl">Reference Implementatation</a></li> |
| </ol></li> |
| </ul> |
| |
| <div class="doc_author"> |
| <p>Written by <a href="rspencer@x10sys.com">Reid Spencer</a></p> |
| </div> |
| |
| |
| <!-- *********************************************************************** --> |
| <div class="doc_section"><a name="abstract">Abstract</a></div> |
| <div class="doc_text"> |
| <p>This document describes the requirements, design, and implementation |
| details of LLVM's System Library. The library is composed of the header files |
| in <tt>llvm/include/llvm/System</tt> and the source files in |
| <tt>llvm/lib/System</tt>. The goal of this library is to completely shield |
| LLVM from the variations in operating system interfaces. By centralizing |
| LLVM's use of operating system interfaces, we make it possible for the LLVM |
| tool chain and runtime libraries to be more easily ported to new platforms. |
| The library also unclutters the rest of LLVM from #ifdef use and special |
| cases for specific operating systems.</p> |
| <p>The System Library was donated to LLVM by Reid Spencer who formulated the |
| original design as part of the eXtensible Programming System (XPS) which is |
| based, in part, on LLVM.</p> |
| </div> |
| |
| <!-- *********************************************************************** --> |
| <div class="doc_section"> |
| <a name="requirements">System Library Requirements</a> |
| </div> |
| <div class="doc_text"> |
| <p>The System library's requirements are aimed at shielding LLVM from the |
| variations in operating system interfaces. The following sections define the |
| requirements needed to fulfill this objective.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="headers">Hide System Header Files</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="nofunc">No Exposed Functions</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="nodata">No Exposed Data</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="xcptns">No Exceptions</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="errors">Standard Error Codes</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="overhead">Minimize Overhead</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- *********************************************************************** --> |
| <div class="doc_section"><a name="design">System Library Design</a></div> |
| <div class="doc_text"> |
| <p>In order to fulfill the requirements of the system library, strict design |
| objectives must be maintained in the library as it evolves. The goal here |
| is to provide interfaces to operating system concepts (files, memory maps, |
| sockets, signals, locking, etc) efficiently and in such a way that the |
| remainder of LLVM is completely operating system agnostic.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="opaque">Use Opaque Classes</a></div> |
| <div class="doc_text"> |
| <p>no public data</p> |
| <p>onlyprimitive typed private/protected data</p> |
| <p>data size is "right" for platform, not max of all platforms</p> |
| <p>each class corresponds to O/S concept</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="common">Common Implementations</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"> |
| <a name="multi_imps">Multiple Implementations</a> |
| </div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"> |
| <a name="low_level">Use Low Level Interfaces</a> |
| </div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="memalloc">No Memory Allocation</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="virtuals">No Virtual Methods</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- *********************************************************************** --> |
| <div class="doc_section"><a name="detail">System Library Details</a></div> |
| <div class="doc_text"> |
| <p>To be written.</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="bug">Bug 351</a></div> |
| <div class="doc_text"> |
| <p>See <a href="http://llvm.cs.uiuc.edu/PR351">bug 351</a> |
| for further details on the progress of this work</p> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"><a name="bug">Rationale For #include Hierarchy</a> |
| </div> |
| <div class="doc_text"> |
| <p>In order to provide different implementations of the lib/System interface |
| for different platforms, it is necessary for the library to "sense" which |
| operating system is being compiled for and conditionally compile only the |
| applicabe parts of the library. While several operating system wrapper |
| libraries (e.g. APR, ACE) choose to use #ifdef preprocessor statements in |
| combination with autoconf variable (HAVE_* family), lib/System chooses an |
| alternate strategy. <p> |
| <p>To put it succinctly, the lib/System strategy has traded "#ifdef hell" for |
| "#include hell". That is, a given implementation file defines one or more |
| functions for a particular operating system variant. The functions defined in |
| that file have no #ifdef's to disambiguate the platform since the file is only |
| compiled on one kind of platform. While this leads to the same function being |
| imlemented differently in different files, it is our contention that this |
| leads to better maintenance and easier portability.</p> |
| <p>For example, consider a function having different implementations on a |
| variety of platforms. Many wrapper libraries choose to deal with the different |
| implementations by using #ifdef, like this:</p> |
| <pre><tt> |
| void SomeFunction(void) { |
| #if defined __LINUX |
| // .. Linux implementation |
| #elif defined __WIN32 |
| // .. Win32 implementation |
| #elif defined __SunOS |
| // .. SunOS implementation |
| #else |
| #warning "Don't know how to implement SomeFunction on this platform" |
| #endif |
| } |
| </tt></pre> |
| <p>The problem with this is that its very messy to read, especially as the |
| number of operating systems and their variants grow. The above example is |
| actually tame compared to what can happen when the implementation depends on |
| specific flavors and versions of the operating system. In that case you end up |
| with multiple levels of nested #if statements. This is what we mean by "#ifdef |
| hell".</p> |
| <p>To avoid the situation above, we've choosen to locate all functions for a |
| given implementation file for a specific operating system into one place. This |
| has the following advantages:<p> |
| <ul> |
| <li>No "#ifdef hell"</li> |
| <li>When porting, the strategy is quite straight forward: copy the |
| implementation file from a similar operating system to a new directory and |
| re-implement them.<li> |
| <li>Correctness is helped during porting because the new operating system's |
| implementation is wholly contained in a separate directory. There's no |
| chance to make an error in the #if statements and affect some other |
| operating system's implementation.</li> |
| </ul> |
| <p>So, given that we have decided to use #include instead of #if to provide |
| platform specific implementations, there are actually three ways we can go |
| about doing this. None of them are perfect, but we believe we've chosen the |
| lesser of the three evils. Given that there is a variable named $OS which |
| names the platform for which we must build, here's a summary of the three |
| approaches we could use to determine the correct directory:</p> |
| <ol> |
| <li>Provide the compiler with a -I$(OS) on the command line. This could be |
| provided in only the lib/System makefile.</li> |
| <li>Use autoconf to transform #include statements in the implementation |
| files by using substitutions of @OS@. For example, if we had a file, |
| File.cpp.in, that contained "#include <@OS@/File.cpp>" this would get |
| transformed to "#include <actual/File.cpp>" where "actual" is the |
| actual name of the operating system</li> |
| <li>Create a link from $OBJ_DIR/platform to $SRC_DIR/$OS. This allows us to |
| use a generic directory name to get the correct platform, as in #include |
| <platform/File.cpp></li> |
| </ol> |
| <p>Let's look at the pitfalls of each approach.</p> |
| <p>In approach #1, we end up with some confusion as to what gets included. |
| Suppose we have lib/System/File.cpp that includes just File.cpp to get the |
| platform specific part of the implementation. In this case, the include |
| directive with the <> syntax will include the right file but the include |
| directive with the "" syntax will recursively include the same file, |
| lib/System/File.cpp. In the case of #include <File.cpp>, the -I options |
| to the compiler are searched first so it works. But in the #include "File.cpp" |
| case, the current directory is searched first. Furthermore, in both cases, |
| neither include directive documents which File.cpp is getting included.</p> |
| <p>In approach #2, we have the problem of needing to reconfigure repeatedly. |
| Developer's generally hate that and we don't want lib/System to be a thorn in |
| everyone's side because it will constantly need updating as operating systems |
| change and as new operating systems are added. The problem occurs when a new |
| implementation file is added to the library. First of all, you have to add a |
| file with the .in suffix, then you have to add that file name to the list of |
| configurable files in the autoconf/configure.ac file, then you have to run |
| AutoRegen.sh to rebuild the configure script, then you have to run the |
| configure script. This is deemed to be a pretty large hassle.</p> |
| <p>In approach #3, we have the problem that not all platforms support links. |
| Fortunately the autoconf macro used to create the link can compensate for |
| this. If a link can't be made, the configure script will copy the correct |
| directory from $BUILD_SRC_DIR to $BUILD_OBJ_DIR under the new name. The only |
| problem with this is that if a copy is made, the copy doesn't get updated if |
| the programmer adds or modifies files in the $BUILD_SRC_DIR. A reconfigure or |
| manual copying is needed to get things to compile.<p> |
| <p>The approach we have taken in lib/System is #3. Here's why:<p> |
| <ul> |
| <li>Approach #1 is rejected because it doesn't document what's actually |
| getting included and the potential for mistakes with alternate include |
| directive forms is high.</li> |
| <li>Approach #2 are both viable and only really impact development when new |
| files are added to the library.</li> |
| <li>However, approach #2 impacts every new file on every platform all the |
| time. With approach #3, only those platforms not supporting links will be |
| affected. The number of platforms not supporting links is very small and |
| they are generally archaic.</li> |
| <li>Given the above, approach #3 seems to have the least impact.</li> |
| </ul> |
| </div> |
| |
| <!-- ======================================================================= --> |
| <div class="doc_subsection"> |
| <a name="refimpl">Reference Implementation</a> |
| </div> |
| <div class="doc_text"> |
| <p>The <tt>linux</tt> implementation of the system library will always be the |
| reference implementation. This means that (a) the concepts defined by the |
| linux must be identically replicated in the other implementations and (b) the |
| linux implementation must always be complete (provide implementations for all |
| concepts).</p> |
| </div> |
| |
| <!-- *********************************************************************** --> |
| |
| <hr> |
| <address> |
| <a href="http://jigsaw.w3.org/css-validator/check/referer"><img |
| src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a> |
| <a href="http://validator.w3.org/check/referer"><img |
| src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a> |
| |
| <a href="mailto:rspencer@x10sys.com">Reid Spencer</a><br> |
| <a href="http://llvm.cs.uiuc.edu">LLVM Compiler Infrastructure</a><br> |
| Last modified: $Date$ |
| </address> |
| </body> |
| </html> |