[llvm-commits] [lld] r152591 - in /lld/trunk/www: content.css hello.png index.html linker_design.html menu.css

Chris Lattner clattner at apple.com
Fri Mar 16 11:54:02 PDT 2012


Overall, looks great.  On the main index.html page, you sidestep the file format discussion.

It would probably make sense to mention that compatibility with ELF, Macho, PECOFF object files are specific goals, but that it also will define a native object file format.  The goal is to produce "normal" final linked images.

For the object file format, you could mention is that the object file format is to be designed to make it fast to write from the compiler and fast to read from into the linker (unlike other formats that are designed to be similar to final linked image formats). 

Overall, the dox look great!

-Chris




On Mar 12, 2012, at 5:10 PM, Nick Kledzik wrote:

> Author: kledzik
> Date: Mon Mar 12 19:10:27 2012
> New Revision: 152591
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=152591&view=rev
> Log:
> Added first round of documentation
> 
> Added:
>    lld/trunk/www/content.css
>    lld/trunk/www/hello.png   (with props)
>    lld/trunk/www/index.html
>    lld/trunk/www/linker_design.html
>    lld/trunk/www/menu.css
> 
> Added: lld/trunk/www/content.css
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/www/content.css?rev=152591&view=auto
> ==============================================================================
> --- lld/trunk/www/content.css (added)
> +++ lld/trunk/www/content.css Mon Mar 12 19:10:27 2012
> @@ -0,0 +1,27 @@
> +html { margin: 0px; } body { margin: 8px; }
> +
> +html, body {
> +  padding:0px;
> +  font-size:small; font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif; background-color: #fff; color: #222;
> +  line-height:1.5;
> +}
> +
> +h1, h2, h3, tt { color: #000 }
> +
> +h1 { padding-top:0px; margin-top:0px;}
> +h2 { color:#333333; padding-top:0.5em; }
> +h3 { padding-top: 0.5em; margin-bottom: -0.25em; color:#2d58b7}
> +li { padding-bottom: 0.5em; }
> +ul { padding-left:1.5em; }
> +
> +/* Slides */
> +IMG.img_slide {
> +    display: block;
> +    margin-left: auto;
> +    margin-right: auto
> +}
> +
> +.itemTitle { color:#2d58b7 }
> +
> +/* Tables */
> +tr { vertical-align:top }
> 
> Added: lld/trunk/www/hello.png
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/www/hello.png?rev=152591&view=auto
> ==============================================================================
> Binary file - no diff available.
> 
> Propchange: lld/trunk/www/hello.png
> ------------------------------------------------------------------------------
>    svn:mime-type = application/octet-stream
> 
> Added: lld/trunk/www/index.html
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/www/index.html?rev=152591&view=auto
> ==============================================================================
> --- lld/trunk/www/index.html (added)
> +++ lld/trunk/www/index.html Mon Mar 12 19:10:27 2012
> @@ -0,0 +1,99 @@
> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
> +          "http://www.w3.org/TR/html4/strict.dtd">
> +<!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ -->
> +<html>
> +<head>
> +  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
> +  <title>lld: a linker for LLMV</title>
> +  <link type="text/css" rel="stylesheet" href="menu.css">
> +  <link type="text/css" rel="stylesheet" href="content.css">
> +</head>
> +
> +<body>
> +<div id="menu">
> +  <div>
> +    <a href="http://llvm.org/">LLVM Home</a>
> +  </div>
> +
> +  <div class="submenu">
> +    <label>lld Info</label>
> +    <a href="./index.html">About</a>
> +    <a href="linker_design.html">Design</a>
> +  </div>
> +
> +  <div class="submenu">
> +    <label>Quick Links</label>
> +    <a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/">commits</a>
> +    <a href="http://llvm.org/bugs/">Bug Reports</a>
> +    <a href="http://llvm.org/svn/llvm-project/lld/trunk/">Browse SVN</a>
> +    <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/">Browse ViewVC</a>
> +  </div>
> +</div>
> +
> +<div id="content">
> +  <!--*********************************************************************-->
> +  <h1>lld: a linker for LLVM</h1>
> +  <!--*********************************************************************-->
> +
> +  <p>lld is a new set of modular code for creating linker tools.</p>
> +
> +  <!--=====================================================================-->
> +  <h2 id="goals">Features and Goals</h2>
> +  <!--=====================================================================-->
> +
> +	<p><b>End-User Features:</b></p>
> +    <ul>
> +		<li>Compatible with existing linker options</li>
> +        <li>Fast link times</li>
> +        <li>Minimal memory use</li>
> +        <li>Remove clang's reliance on "the system linker"</li>
> +    </ul>
> +
> +	<p><b>Applications:</b></p>
> +    <ul>
> +        <li>Use the LLVM 'BSD' License</li>
> +        <li>Modular design</li>
> +        <li>Support cross linking</li>
> +        <li>Easy to add new CPU support</li>
> +        <li>Can be built as static tool or library</li>
> +    </ul>
> +	
> +	<p><b>Design and Implementation:</b></p>
> +    <ul>
> +        <li>Extensive unit tests</li>
> +        <li>Internal linker model can be dumped/read to textual format</li>
> +		<li>Internal linker model can be dumped/read to new native format</li>
> +        <li>Additional linking features can be plugged in as "passes"</li>
> +        <li>OS specific and CPU specific code factored out</li>
> +    </ul>
> +
> +  <!--=====================================================================-->
> +  <h2 id="why">Why a new linker?</h2>
> +  <!--=====================================================================-->
> +
> +  <p>The fact that clang relies on whatever linker tool you happen to have
> +	installed means that clang has been very conservative adopting features
> +	which require a recent linker.</p>
> +	
> + <p>In the same way that the MC layer of LLVM has removed clang's reliance
> +	on the system assembler tool, the lld project will remove clang's reliance
> +	on the system linker tool.</p>
> +
> +
> +  <!--=====================================================================-->
> +  <h2 id="status">Current Status</h2>
> +  <!--=====================================================================-->
> +
> +   <p>lld is in its very early stages of development.</p>
> +
> + <!--=====================================================================-->
> +  <h2>Design Documents</h2>
> +  <!--=====================================================================-->
> +
> +<ul>
> +   <li><a href="linker_design.html">Design of lld</a></li>
> +</ul>
> + 
> +</div>
> +</body>
> +</html>
> 
> Added: lld/trunk/www/linker_design.html
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/www/linker_design.html?rev=152591&view=auto
> ==============================================================================
> --- lld/trunk/www/linker_design.html (added)
> +++ lld/trunk/www/linker_design.html Mon Mar 12 19:10:27 2012
> @@ -0,0 +1,421 @@
> +<html>
> +<head>
> +  <title>Design of lld</title>
> +</head>
> +<body>
> +
> +
> +<h1>
> +  Design of lld 
> +</h1>
> +
> +<h2>
> +  <a name="introduction">Introduction</a>
> +</h2>
> +
> +<p>lld is a new generation of linker.  It is not "section" based
> +like traditional linkers which mostly just interlace sections from multiple
> +object files into the output file.  Instead, lld is based on "Atoms".
> +Traditional section based linking work well for simple linking, but their model
> +makes advanced linking features difficult to implement.  Features like dead code 
> +stripping, reordering functions for locality, and C++ coalescing require the
> +linker to work at a finer grain.
> +</p>
> +
> +<p>An atom is an indivisible chunk of code or data.  An atom has a set of
> +attributes, such as: name, scope, content-type, alignment, etc.  An atom also
> +has a list of References.  A Reference contains: a kind, an optional offset, 
> +an optional addend, and an optional target atom.</p>
> +
> +<p>The Atom model allows the linker to use standard graph theory models for 
> +linking data structures.  Each atom is a node, and each Reference is an edge. 
> +The feature of dead code stripping is implemented by following edges to mark
> +all live atoms, and then delete the non-live atoms.</p>
> +<br>
> +<h2>
> +  <a name="Atom model">Atom model</a>
> +</h2>
> +
> +<p>An atom is an indivisible chuck of code or data.  Typically each user
> +written function or global variable is an atom.  In addition, the compiler may
> +emit other atoms, such as for literal c-strings or floating point constants, or
> +for runtime data structures like dwarf unwind info or pointers to initializers.
> +</p>
> +
> +<p>A simple "hello world" object file would be modeled like this:</p>
> +<img src="hello.png" alt="hello world graphic"/>
> +<p>There are three atoms: main, a proxy for printf, and an anonymous atom 
> +containing the c-string literal "hello world".  The Atom "main" has two  
> +references. One is the call site for the call to printf, and the other is 
> +a refernce for the instruction that loads the address of the c-string literal. 
> +</p>
> +
> +<br>
> +<h2>
> +  <a name="File model">File model</a>
> +</h2>
> +
> +<p>The linker views the input files as basically containers of Atoms and 
> +References, and just a few attributes of their own.  The linker works with three 
> +kinds of files: object files, static libraries, and dynamic shared libraries.   
> +Each kind of file has reader object which presents the file in the model 
> +expected by the linker.</p>
> +<h4> <a>Object File</a> 
> +</h4>
> +An object file is just a container of atoms.  When linking 
> +an object file, a reader is instantiated which parses the object file and 
> +instantiates a set of atoms representing all content in the .o file.  The
> +linker adds all those atoms to a master graph.
> +
> +<h4> <a>Static Library (Archive)</a> 
> +</h4>
> +This is the traditional unix static archive which is just a collection of
> +object files with a "table of contents". When linking with a static library,
> +by default nothing is added to the master graph of atoms. Instead, if after
> +merging all atoms from object files into a master graph, if any "undefined" atoms
> +are left remaining in the master graph, the linker reads the 
> +table of contents for each static library to see if any have the needed 
> +definitions. If so, the set of atoms from the specified object file in the 
> +static library is added to the master graph of atoms. 
> +
> +<h4> <a>Dynamic Library (Shared Object)</a> 
> +</h4>
> +Dynamic libraries are different than object files and static libraries in that 
> +they don't directly add any content.
> +Their purpose is to check at build time that the remaining undefined references 
> +can be resolved at runtime, and provide a list of dynamic libraries (SO_NEEDED) 
> +that will be needed at runtime. 
> +The way this is modeled in the linker is that a dynamic library contributes
> +no atoms to the initial graph of atoms.  Instead, (like static libraries) if
> +there are "undefined" atoms in the master graph of all atoms, then each 
> +dynamic library is checked to see if exports the required symbol. If so,
> +a "shared library" atom is instantiated by the by the reader which the linker
> +uses to replace the "undefined" atom.</p>
> +
> +<br>
> +<h2>
> +  <a name="Linking Steps">Linking Steps</a>
> +</h2>
> +<p>Through the use of abstract Atoms, the core of linking is architecture 
> +independent and file format independent.  All command line parsing is factored
> +out into a separate "options" abstraction which enables the linker to be driven
> +with different command line sets.</p>
> +<p>The overall steps in linking are:<p>
> +<ol>
> +  <li>Command line processing</li>
> +  <li>Parsing input files</li>
> +  <li>Resolving</li>
> +  <li>Passes/Optimizations</li>
> +  <li>Generate output file</li>
> +</ol>
> +
> +<p>The Resolving and Passes steps are done purely on the master graph of atoms, 
> +so they have no notion of file formats such as mach-o or ELF.</p>
> +
> +<h4> <a>Resolving</a> 
> +</h4>
> +<p>The resolving step takes all the atoms graphs from each object file and 
> +combines them into one master object graph.  Unfortunately, it is not as simple
> +as appending the atom list from each file into one big list.  There are many
> +cases where atoms need to be coalesced.  That is, two or more atoms need to 
> +be coalesced into one atom.  This is necessary to support: C language
> + "tentative definitions", C++ weak symbols for templates and inlines defined
> +in headers, replacing undefined atoms with actual definition atoms, and 
> +for merging copies of constants like c-strings and floating point constants.</p>
> +
> +<p>The linker support coalescing by-name and by-content. By-name is used for
> +tentative definitions and weak symbols.  By-content is used for constant data
> +that can be merged. </p>
> +
> +<p>The resolving process maintains some global linking "state", including
> +a "symbol table" which is a map from llvm::StringRef to lld::Atom*.
> +With these data structures, the linker iterates all atoms in all input files. F
> +or each atom, it checks if the atom is named and has a global or hidden scope.
> +If so, the atom is added to the symbol table map.  If there already is
> +a matching atom in that table, that means the current atom needs to be 
> +coalesced with the found atom, or it is a multiple definition error.
> +</p>
> +
> +<p>When all initial input file atoms have been processed by the resolver,  
> +a scan is made to see if there are any undefined atoms in the graph.  If there
> +are, the linker scans all libraries (both static and dynamic) looking for  
> +definitions to replace the undefined atoms.  It is an error if any undefined  
> +atoms are left remaining.
> +</p>
> +
> +<p>Dead code stripping (if requested) is done at the end of resolving.  The
> +linker does a simple mark-and-sweep. It starts with "root" atoms (like "main"
> +in a main executable) and follows each references and marks each Atom that
> +it visits as "live".  When done, all atoms not marked "live" are removed.
> +</p>
> +
> +<p>The result of the Resolving phase is the creation of an lld::File object.  
> +The goal is that the lld::File model is <b>the</b> internal representation throughout
> +the linker. The file readers parse (mach-o, ELF, COFF) into an lld::File.
> +The file writers (mach-o, ELF, COFF) taken an lld::File and produce their
> +file kind, and every Pass only operates on an lld::File.  This is not only
> +a simpler, consistent model, but it enables the state of the linker to be 
> +dumped at any point in the link for testing purposes.
> +</p>
> +
> +
> +<h4> <a>Passes</a> 
> +</h4>
> +<p>The Passes step
> +is an open ended set of routines that each get a change to modify or enhance
> +the current lld::File object. Some example Passes are:</p>
> +<ul>
> +  <li>stub (PLT) generation</li>
> +  <li>GOT instantiation</li>
> +  <li>order_file optimization</li>
> +  <li>branch island generation</li>
> +  <li>branch shim generation</li>
> +  <li>Objective-C optimizations (Darwin specific)</li>
> +  <li>TLV instantiation (Darwin specific)</li>
> +  <li>dtrace probe processing (Darwin specific)</li>
> +  <li>compact unwind encoding (Darwin specific)</li>
> +</ul>
> +<p>Some of these passes are specific to Darwin's runtime environments.  But many
> +of the passes are applicable to any OS (such as generating branch island for 
> +out of range branch instructions).</p>
> +
> +<p>The general structure of a pass is to iterate through the atoms in the
> +current lld::File object, inspecting each atom and doing something.  
> +For instance, the stub pass, looks for call sites to shared library atoms
> +(e.g. call to printf).  It then
> +instantiates a "stub" atom (PLT entry) and a "lazy pointer" atom for each 
> +proxy atom needed, and these new atoms are added to the current lld::File 
> +object.  Next, all the noted call sites to shared library atoms have their
> +References altered to point to the stub atom instead of the shared library
> +atom.</p>  
> +
> +<h4><a>Generate Output File</a> 
> +</h4>
> +<p>Once the passes are done, the output file writer is given current lld::File 
> +object.  The writer's job is to create the executable content file wrapper 
> +and place the content of the atoms into it. 
> +</p>
> +
> +
> +<h2>
> +  <a name="lld::File representations">lld::File representations</a>
> +</h2>
> +<p>Just as LLMV has three representations of its IR model, lld has three
> +representations of its File/Atom/Reference model: 
> +<ul>
> +	<li>In memory, abstract C++ classes 
> +	     (lld::Atom, lld::Reference, and lld::File)</li>
> +	<li>textual (in YAML)</li>
> +	<li>binary format ("native")</li>
> +</ul>
> +</p>
> +
> +<h4><a>Binary File Format</a> 
> +</h4>
> +<p>In theory, lld::File objects could be written to disk in an existing 
> +Object File format standard (e.g. ELF).  Instead we choose to define a new
> +binary file format. There are two main reasons for this: fidelity and 
> +performance.</p>
> +<p>In order for lld to work as a linker on all platforms, its internal model
> +must be rich enough to model all CPU and OS linking features.  But if we choose 
> +an existing Object File format as the lld binary format, that means an on
> +going need to retrofit each platform specific feature needed from alternate
> +platforms into the existing Object File format.  Having our own "native"
> +binary format side steps that issue.  We still need to be able to binary
> +encode all the features, but once the in-memory model can represent the feature,
> +it is straight forward to binary encode it.</p>
> +
> +<p>The reason to use a binary file format at all, instead of a textual file 
> +format, is speed.  You want the binary format to be as fast as possible to read 
> +into the in-memory model. Given that we control the in-memory model and the 
> +binary format, the obvious way to make reading super fast it to make the file
> +format be basically just an array of atoms.  The reader just mmaps in the file 
> +and looks at the header to see how many atoms there are and instantiate that  
> +many atom objects with the atom attribute information coming from that array.   
> +The trick is designing this in a way that can be extended as the Atom mode 
> +evolves and new attributes are added.
> +</p>
> +
> +<p>The native object file format starts with a header that lists how many 
> +"chunks" are in the file.  A chunk is an array of "ivar data".  The native
> +file reader instantiates an array of Atom objects (with one large malloc call). 
> +Each atom contains just a pointer to its vtable and a pointer to its ivar data. 
> +All methods on lld::Atom are virtual, so all the method implementations return
> +values based on the ivar data to which it has a pointer.
> +If a new linking features is added which requires a change to the lld::Atom
> +model, a new native reader class (e.g. version 2) is defined which knows
> +how to read the new feature information from the new ivar data.  The old
> +reader class (e.g. version 1) is updated to do its best to model (the lack
> +of the new feature) given the old ivar data in existing native object files.
> +</p>
> +
> +<p>With this model for the native file format, files can be read and turned
> +into the in-memory graph of lld::Atoms with just a few memory allocations.  
> +And the format can easily adapt over time to new features</p>
> +
> +
> +<h4><a>Textual representations in YAML</a> 
> +</h4>
> +<p>
> +In designing a textual format we want something easy for humans to read and
> +easy for the linker to parse.  Since an atom has lots of attributes most of
> +which are usually just the default, we should define default values for 
> +every attribute so that those can be omitted from the text representation.
> +Here is the atoms for a simple hello world program expressed in YAML.
> +</p>
> +<pre>
> +---
> +target-triple:   x86_64-apple-darwin11
> +
> +atoms:
> +    - name:    _main
> +      scope:   global
> +      type:    code
> +      content: [ 55, 48, 89, e5, 48, 8d, 3d, 00, 00, 00, 00, 30, c0, e8, 00, 00,
> +                 00, 00, 31, c0, 5d, c3 ]
> +      fixups:
> +      - offset: 07
> +        kind:   pcrel32
> +        target: 2
> +      - offset: 0E
> +        kind:   call32
> +        target: _fprintf
> +
> +    - type:    c-string
> +      content: [ 73, 5A, 00 ]
> +
> +...
> +</pre>
> +
> +<p>The biggest use for the textual format will be writing test cases. 
> +Writing test cases in C is problematic because the compiler 
> +may vary its output over time for its own optimization reasons which my 
> +inadvertently disable or break the linker feature trying to be tested. By 
> +writing test cases in the linkers own textual format, we can exactly specify 
> +every attribute of every atom and thus target specific linker logic.
> +</p>
> +
> +
> +
> +
> +<h2>
> +  <a name="Testing">Testing</a>
> +</h2>
> +<p>The lld project contains a test suite which is being built up as new code
> +is added to lld.  All new lld functionality should have a tests added to the 
> +test suite.</p>
> +<p>The test suite is <a href="http://llvm.org/cmds/lit.html">lit</a> driven.
> +Each test is a text file with comments telling lit how to run the test and
> +check the result</p>
> +<p>To facilitate testing, the lld project builds a tool called lld-core.
> +This tool reads a YAML file (default from stdin), parses it into one or
> +more lld::File objects in memory and then feeds those lld::File objects 
> +to the resolver phase.  The output of the resolver is written as a native
> +object file.  It is then read back in using the native object file reader
> +and then pass to the YAML writer.  This round-about path means that all three
> +representations (in-memory, binary, and text) are exercised, and any new
> +feature has to work in all the representations to pass the test.
> +</p>
> +
> +<h4><a>Resolver testing</a> 
> +</h4>
> +<p>Basic testing is the "core linking" or resolving phase.  That
> +is where the linker merges object files.  All test cases are written in YAML.
> +One feature of YAML is that it allows multiple "documents" to be encoding in
> +one YAML stream.  That means one text file can appear to the linker as 
> +multiple .o files - the normal case for the linker.  
> +</p>
> +<p>Here is a simple example of a core linking test case. It checks that
> +an undefined atom from one file will be replaced by a definition from
> +another file.</p>
> +<pre>
> +# RUN: lld-core %s | FileCheck %s
> +
> +#
> +# Test that undefined atoms are replaced with defined atoms.
> +#
> +
> +---
> +atoms:
> +    - name:              foo
> +      definition:        undefined
> +---
> +atoms:
> +    - name:              foo
> +      scope:             global
> +      type:              code
> +...
> +
> +# CHECK:       name:       foo
> +# CHECK:       scope:      global
> +# CHECK:       type:       code
> +# CHECK-NOT:   name:       foo
> +# CHECK:       ...
> +</pre>
> +
> +<h4><a>Passes testing</a> 
> +</h4>
> +<p>Since Passes just operate on an lld::File object, the lld-core tool has
> +the option to run a particular pass (after resolving).  Thus, you can write
> +a YAML test case with carefully crafted input to exercise areas of a Pass
> +and the check the resulting lld::File object as represented in YAML.
> +</p>
> +
> +
> +<h2>
> +  <a name="Design Issues">Design Issues</a>
> +</h2>
> +
> +<p>There are a number of open issues in the design of lld.  The plan is to 
> +wait and make these design decisions when we need to.</p>
> +
> +
> +<h4><a>Debug Info</a> 
> +</h4>
> +<p>Currently, the lld model says nothing about debug info.  But the most 
> +popular debug format is DWARF and there is some impedance mismatch with the 
> +lld model and DWARF.  In lld there are just Atoms and only Atoms that need
> +to be in a special section at runtime have an associated section.  Also, 
> +Atoms do not have addresses.  The way DWARF is spec'ed different parts of 
> +DWARF are supposed to go into specially named sections and the DWARF references
> +function code by address.</p>
> +
> +<h4><a>CPU and OS specific functionality</a> 
> +</h4>
> +<p>Currently, lld has an abstract "Platform" that deals with any CPU or OS
> +specific differences in linking.  We just keep adding virtual methods to
> +the base Platform class as we find linking areas that might need customization.
> +At some point we'll need to structure this better.
> +</p>
> +
> +<h4><a>File Attributes</a> 
> +</h4>
> +<p>Currently, lld::File just has a path and a way to iterate its atoms. We 
> +will need to add mores attributes on a File.  For example, some equivalent
> +to the target triple.  There is also a number of cached or computed attributes
> +that could make various Passes more efficient.  For instance, on Darwin
> +there are a number of Objective-C optimizations that can be done by a Pass.
> +But it would improve the plain C case if the Objective-C optimization Pass did
> +not have to scan all atoms looking for any Objective-C data structures.  This
> +could be done if the lld::File object had an attribute that said if the file
> +had any Objective-C data in it. The Resolving phase would then be required
> +to "merge" that attribute as object files are added.
> +</p>
> +
> +<h4><a>Command Line Processing</a> 
> +</h4>
> +<p>Eventually, we may want this linker to be able to be a drop in replacement 
> +linker for existing linker tools.  That means being able to handle command
> +line arguments for different platforms (e.g. darwin or linux).  Currently,
> +there is no command line processing code in lld. If clang winds up
> +incorporating the lld libraries into the clang binary, lld may be able to punt
> +this work because clang will be responsible for setting up the state for lld.
> +</p>
> +
> +
> +
> +
> +
> +</body>
> +</html>
> +
> 
> Added: lld/trunk/www/menu.css
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/www/menu.css?rev=152591&view=auto
> ==============================================================================
> --- lld/trunk/www/menu.css (added)
> +++ lld/trunk/www/menu.css Mon Mar 12 19:10:27 2012
> @@ -0,0 +1,39 @@
> +/***************/
> +/* page layout */
> +/***************/
> +
> +[id=menu] {
> +	position:fixed;
> +	width:25ex;
> +}
> +[id=content] {
> +	/* *****  EDIT THIS VALUE IF CONTENT OVERLAPS MENU ***** */
> +	position:absolute;
> +  left:29ex;
> +	padding-right:4ex;
> +}
> +
> +/**************/
> +/* menu style */
> +/**************/
> +
> +#menu .submenu {
> +	padding-top:1em;
> +	display:block;
> +}
> +
> +#menu label {
> +	display:block;
> +	font-weight: bold;
> +	text-align: center;
> +	background-color: rgb(192,192,192);
> +}
> +#menu a {
> +	padding:0 .2em;
> +	display:block;
> +	text-align: center;
> +	background-color: rgb(235,235,235);
> +}
> +#menu a:visited {
> +	color:rgb(100,50,100);
> +}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list