mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-29 22:30:33 +00:00
many edits, patch by Kelly Wilson!
llvm-svn: 44157
This commit is contained in:
parent
f16da54ae2
commit
e29010c2f0
@ -41,15 +41,16 @@ Variables / SSA Construction</li>
|
||||
|
||||
<p>Welcome to Chapter 6 of the "<a href="index.html">Implementing a language
|
||||
with LLVM</a>" tutorial. At this point in our tutorial, we now have a fully
|
||||
functional language that is fairly minimal, but also useful. One big problem
|
||||
with it though is that it doesn't have many useful operators (like division,
|
||||
logical negation, or even any comparisons other than less-than.</p>
|
||||
functional language that is fairly minimal, but also useful. There
|
||||
is still one big problem with it, however. Our language doesn't have many
|
||||
useful operators (like division, logical negation, or even any comparisons
|
||||
besides less-than).</p>
|
||||
|
||||
<p>This chapter of the tutorial takes a wild digression into adding user-defined
|
||||
operators to the simple and beautiful Kaleidoscope language, giving us a
|
||||
simple and ugly language in some ways, but also a powerful one at the same time.
|
||||
operators to the simple and beautiful Kaleidoscope language. This digression now gives
|
||||
us a simple and ugly language in some ways, but also a powerful one at the same time.
|
||||
One of the great things about creating your own language is that you get to
|
||||
decide what is good or bad. In this tutorial we'll assume that it is okay and
|
||||
decide what is good or bad. In this tutorial we'll assume that it is okay to
|
||||
use this as a way to show some interesting parsing techniques.</p>
|
||||
|
||||
<p>At the end of this tutorial, we'll run through an example Kaleidoscope
|
||||
@ -73,8 +74,8 @@ capability to Kaleidoscope, which will let the user round out the set of
|
||||
operators that are supported.</p>
|
||||
|
||||
<p>The point of going into user-defined operators in a tutorial like this is to
|
||||
show the power and flexibility of using a hand-written parser. The parser we
|
||||
are using so far is using recursive descent for most parts of the grammar, and
|
||||
show the power and flexibility of using a hand-written parser. Thus far, the parser
|
||||
we have been implementing uses recursive descent for most parts of the grammar and
|
||||
operator precedence parsing for the expressions. See <a
|
||||
href="LangImpl2.html">Chapter 2</a> for details. Without using operator
|
||||
precedence parsing, it would be very difficult to allow the programmer to
|
||||
@ -152,12 +153,12 @@ static int gettok() {
|
||||
|
||||
<p>This just adds lexer support for the unary and binary keywords, like we
|
||||
did in <a href="LangImpl5.html#iflexer">previous chapters</a>. One nice thing
|
||||
about our current AST is that we represent binary operators fully generally
|
||||
with their ASCII code as the opcode. For our extended operators, we'll use the
|
||||
about our current AST, is that we represent binary operators with full generalisation
|
||||
by using their ASCII code as the opcode. For our extended operators, we'll use this
|
||||
same representation, so we don't need any new AST or parser support.</p>
|
||||
|
||||
<p>On the other hand, we have to be able to represent the definitions of these
|
||||
new operators, in the "def binary| 5" part of the function definition. In the
|
||||
new operators, in the "def binary| 5" part of the function definition. In our
|
||||
grammar so far, the "name" for the function definition is parsed as the
|
||||
"prototype" production and into the <tt>PrototypeAST</tt> AST node. To
|
||||
represent our new user-defined operators as prototypes, we have to extend
|
||||
@ -257,14 +258,14 @@ static PrototypeAST *ParsePrototype() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This is all fairly straight-forward parsing code, and we have already seen
|
||||
a lot of similar code in the past. One interesting piece of this is the part
|
||||
that sets up <tt>FnName</tt> for binary operators. This builds names like
|
||||
"binary@" for a newly defined "@" operator. This takes advantage of the fact
|
||||
that symbol names in the LLVM symbol table are allowed to have any character in
|
||||
them, even including embedded nul characters.</p>
|
||||
<p>This is all fairly straightforward parsing code, and we have already seen
|
||||
a lot of similar code in the past. One interesting part about the code above is
|
||||
the couple lines that set up <tt>FnName</tt> for binary operators. This builds names
|
||||
like "binary@" for a newly defined "@" operator. This then takes advantage of the
|
||||
fact that symbol names in the LLVM symbol table are allowed to have any character in
|
||||
them, including embedded nul characters.</p>
|
||||
|
||||
<p>The next interesting piece is codegen support for these binary operators.
|
||||
<p>The next interesting thing to add, is codegen support for these binary operators.
|
||||
Given our current structure, this is a simple addition of a default case for our
|
||||
existing binary operator node:</p>
|
||||
|
||||
@ -301,10 +302,10 @@ Value *BinaryExprAST::Codegen() {
|
||||
<p>As you can see above, the new code is actually really simple. It just does
|
||||
a lookup for the appropriate operator in the symbol table and generates a
|
||||
function call to it. Since user-defined operators are just built as normal
|
||||
functions (because the "prototype" boils down into a function with the right
|
||||
functions (because the "prototype" boils down to a function with the right
|
||||
name) everything falls into place.</p>
|
||||
|
||||
<p>The final missing piece is a bit of top level magic, here:</p>
|
||||
<p>The final piece of code we are missing, is a bit of top level magic:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -330,10 +331,9 @@ Function *FunctionAST::Codegen() {
|
||||
|
||||
<p>Basically, before codegening a function, if it is a user-defined operator, we
|
||||
register it in the precedence table. This allows the binary operator parsing
|
||||
logic we already have to handle it. Since it is a fully-general operator
|
||||
precedence parser, this is all we need to do to "extend the grammar".</p>
|
||||
logic we already have in place to handle it. Since we are working on a fully-general operator precedence parser, this is all we need to do to "extend the grammar".</p>
|
||||
|
||||
<p>With that, we have useful user-defined binary operators. This builds a lot
|
||||
<p>Now we have useful user-defined binary operators. This builds a lot
|
||||
on the previous framework we built for other operators. Adding unary operators
|
||||
is a bit more challenging, because we don't have any framework for it yet - lets
|
||||
see what it takes.</p>
|
||||
@ -347,7 +347,7 @@ see what it takes.</p>
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Since we don't currently support unary operators in the Kaleidoscope
|
||||
language, we'll need to add everything for them. Above, we added simple
|
||||
language, we'll need to add everything to support them. Above, we added simple
|
||||
support for the 'unary' keyword to the lexer. In addition to that, we need an
|
||||
AST node:</p>
|
||||
|
||||
@ -390,14 +390,14 @@ static ExprAST *ParseUnary() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>The grammar we add is pretty straight-forward here. If we see a unary
|
||||
<p>The grammar we add is pretty straightforward here. If we see a unary
|
||||
operator when parsing a primary operator, we eat the operator as a prefix and
|
||||
parse the remaining piece as another unary operator. This allows us to handle
|
||||
multiple unary operators (e.g. "!!x"). Note that unary operators can't have
|
||||
ambiguous parses like binary operators can, so there is no need for precedence
|
||||
information.</p>
|
||||
|
||||
<p>The problem with the above is that we need to call ParseUnary from somewhere.
|
||||
<p>The problem with this function, is that we need to call ParseUnary from somewhere.
|
||||
To do this, we change previous callers of ParsePrimary to call ParseUnary
|
||||
instead:</p>
|
||||
|
||||
@ -424,7 +424,7 @@ static ExprAST *ParseExpression() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>With these two simple changes, we now parse unary operators and build the
|
||||
<p>With these two simple changes, we are now able to parse unary operators and build the
|
||||
AST for them. Next up, we need to add parser support for prototypes, to parse
|
||||
the unary operator prototype. We extend the binary operator code above
|
||||
with:</p>
|
||||
@ -587,7 +587,7 @@ Evaluated to 0.000000
|
||||
|
||||
<p>Based on these simple primitive operations, we can start to define more
|
||||
interesting things. For example, here's a little function that solves for the
|
||||
number of iterations it takes for a function in the complex plane to
|
||||
number of iterations it takes a function in the complex plane to
|
||||
converge:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -779,8 +779,8 @@ and powerful language. It may not be self-similar :), but it can be used to
|
||||
plot things that are!</p>
|
||||
|
||||
<p>With this, we conclude the "adding user-defined operators" chapter of the
|
||||
tutorial. We successfully extended our language with the ability to extend the
|
||||
language in the library, and showed how this can be used to build a simple but
|
||||
tutorial. We have successfully augmented our language, adding the ability to extend the
|
||||
language in the library, and we have shown how this can be used to build a simple but
|
||||
interesting end-user application in Kaleidoscope. At this point, Kaleidoscope
|
||||
can build a variety of applications that are functional and can call functions
|
||||
with side-effects, but it can't actually define and mutate a variable itself.
|
||||
@ -790,7 +790,7 @@ with side-effects, but it can't actually define and mutate a variable itself.
|
||||
languages, and it is not at all obvious how to <a href="LangImpl7.html">add
|
||||
support for mutable variables</a> without having to add an "SSA construction"
|
||||
phase to your front-end. In the next chapter, we will describe how you can
|
||||
add this without building SSA in your front-end.</p>
|
||||
add variable mutation without building SSA in your front-end.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -49,11 +49,11 @@ respectable, albeit simple, <a
|
||||
href="http://en.wikipedia.org/wiki/Functional_programming">functional
|
||||
programming language</a>. In our journey, we learned some parsing techniques,
|
||||
how to build and represent an AST, how to build LLVM IR, and how to optimize
|
||||
the resultant code and JIT compile it.</p>
|
||||
the resultant code as well as JIT compile it.</p>
|
||||
|
||||
<p>While Kaleidoscope is interesting as a functional language, this makes it
|
||||
"too easy" to generate LLVM IR for it. In particular, a functional language
|
||||
makes it very easy to build LLVM IR directly in <a
|
||||
<p>While Kaleidoscope is interesting as a functional language, the fact that it
|
||||
is functional makes it "too easy" to generate LLVM IR for it. In particular, a
|
||||
functional language makes it very easy to build LLVM IR directly in <a
|
||||
href="http://en.wikipedia.org/wiki/Static_single_assignment_form">SSA form</a>.
|
||||
Since LLVM requires that the input code be in SSA form, this is a very nice
|
||||
property and it is often unclear to newcomers how to generate code for an
|
||||
@ -124,13 +124,13 @@ the LLVM IR, and they live in the then/else branches of the if statement
|
||||
(cond_true/cond_false). In order to merge the incoming values, the X.2 phi node
|
||||
in the cond_next block selects the right value to use based on where control
|
||||
flow is coming from: if control flow comes from the cond_false block, X.2 gets
|
||||
the value of X.1. Alternatively, if control flow comes from cond_tree, it gets
|
||||
the value of X.1. Alternatively, if control flow comes from cond_true, it gets
|
||||
the value of X.0. The intent of this chapter is not to explain the details of
|
||||
SSA form. For more information, see one of the many <a
|
||||
href="http://en.wikipedia.org/wiki/Static_single_assignment_form">online
|
||||
references</a>.</p>
|
||||
|
||||
<p>The question for this article is "who places phi nodes when lowering
|
||||
<p>The question for this article is "who places the phi nodes when lowering
|
||||
assignments to mutable variables?". The issue here is that LLVM
|
||||
<em>requires</em> that its IR be in SSA form: there is no "non-ssa" mode for it.
|
||||
However, SSA construction requires non-trivial algorithms and data structures,
|
||||
@ -162,12 +162,12 @@ represents stack variables.
|
||||
</p>
|
||||
|
||||
<p>In LLVM, all memory accesses are explicit with load/store instructions, and
|
||||
it is carefully designed to not have (or need) an "address-of" operator. Notice
|
||||
it is carefully designed not to have (or need) an "address-of" operator. Notice
|
||||
how the type of the @G/@H global variables is actually "i32*" even though the
|
||||
variable is defined as "i32". What this means is that @G defines <em>space</em>
|
||||
for an i32 in the global data area, but its <em>name</em> actually refers to the
|
||||
address for that space. Stack variables work the same way, but instead of being
|
||||
declared with global variable definitions, they are declared with the
|
||||
address for that space. Stack variables work the same way, except that instead of
|
||||
being declared with global variable definitions, they are declared with the
|
||||
<a href="../LangRef.html#i_alloca">LLVM alloca instruction</a>:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -259,10 +259,10 @@ cond_next:
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>The mem2reg pass implements the standard "iterated dominator frontier"
|
||||
<p>The mem2reg pass implements the standard "iterated dominance frontier"
|
||||
algorithm for constructing SSA form and has a number of optimizations that speed
|
||||
up (very common) degenerate cases. mem2reg is the answer for dealing with
|
||||
mutable variables, and we highly recommend that you depend on it. Note that
|
||||
up (very common) degenerate cases. The mem2reg optimization pass is the answer to dealing
|
||||
with mutable variables, and we highly recommend that you depend on it. Note that
|
||||
mem2reg only works on variables in certain circumstances:</p>
|
||||
|
||||
<ol>
|
||||
@ -288,10 +288,10 @@ more powerful and can promote structs, "unions", and arrays in many cases.</li>
|
||||
|
||||
<p>
|
||||
All of these properties are easy to satisfy for most imperative languages, and
|
||||
we'll illustrate this below with Kaleidoscope. The final question you may be
|
||||
we'll illustrate it below with Kaleidoscope. The final question you may be
|
||||
asking is: should I bother with this nonsense for my front-end? Wouldn't it be
|
||||
better if I just did SSA construction directly, avoiding use of the mem2reg
|
||||
optimization pass? In short, we strongly recommend that use you this technique
|
||||
optimization pass? In short, we strongly recommend that you use this technique
|
||||
for building SSA form, unless there is an extremely good reason not to. Using
|
||||
this technique is:</p>
|
||||
|
||||
@ -309,8 +309,8 @@ assignment point, good heuristics to avoid insertion of unneeded phi nodes, etc.
|
||||
|
||||
<li>Needed for debug info generation: <a href="../SourceLevelDebugging.html">
|
||||
Debug information in LLVM</a> relies on having the address of the variable
|
||||
exposed to attach debug info to it. This technique dovetails very naturally
|
||||
with this style of debug info.</li>
|
||||
exposed so that debug info can be attached to it. This technique dovetails
|
||||
very naturally with this style of debug info.</li>
|
||||
</ul>
|
||||
|
||||
<p>If nothing else, this makes it much easier to get your front-end up and
|
||||
@ -337,7 +337,7 @@ add two features:</p>
|
||||
</ol>
|
||||
|
||||
<p>While the first item is really what this is about, we only have variables
|
||||
for incoming arguments and for induction variables, and redefining those only
|
||||
for incoming arguments as well as for induction variables, and redefining those only
|
||||
goes so far :). Also, the ability to define new variables is a
|
||||
useful thing regardless of whether you will be mutating them. Here's a
|
||||
motivating example that shows how we could use these:</p>
|
||||
@ -403,8 +403,8 @@ locations.
|
||||
</p>
|
||||
|
||||
<p>To start our transformation of Kaleidoscope, we'll change the NamedValues
|
||||
map to map to AllocaInst* instead of Value*. Once we do this, the C++ compiler
|
||||
will tell use what parts of the code we need to update:</p>
|
||||
map so that it maps to AllocaInst* instead of Value*. Once we do this, the C++
|
||||
compiler will tell us what parts of the code we need to update:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -452,7 +452,7 @@ Value *VariableExprAST::Codegen() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>As you can see, this is pretty straight-forward. Next we need to update the
|
||||
<p>As you can see, this is pretty straightforward. Now we need to update the
|
||||
things that define the variables to set up the alloca. We'll start with
|
||||
<tt>ForExprAST::Codegen</tt> (see the <a href="#code">full code listing</a> for
|
||||
the unabridged code):</p>
|
||||
@ -518,7 +518,7 @@ into the alloca, and register the alloca as the memory location for the
|
||||
argument. This method gets invoked by <tt>FunctionAST::Codegen</tt> right after
|
||||
it sets up the entry block for the function.</p>
|
||||
|
||||
<p>The final missing piece is adding the 'mem2reg' pass, which allows us to get
|
||||
<p>The final missing piece is adding the mem2reg pass, which allows us to get
|
||||
good codegen once again:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -537,7 +537,7 @@ good codegen once again:</p>
|
||||
|
||||
<p>It is interesting to see what the code looks like before and after the
|
||||
mem2reg optimization runs. For example, this is the before/after code for our
|
||||
recursive fib. Before the optimization:</p>
|
||||
recursive fib function. Before the optimization:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -709,7 +709,7 @@ have "(x+1) = expr" - only things like "x = expr" are allowed.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Once it has the variable, codegen'ing the assignment is straight-forward:
|
||||
<p>Once we have the variable, codegen'ing the assignment is straightforward:
|
||||
we emit the RHS of the assignment, create a store, and return the computed
|
||||
value. Returning a value allows for chained assignments like "X = (Y = Z)".</p>
|
||||
|
||||
@ -799,7 +799,7 @@ optionally have an initializer value. As such, we capture this information in
|
||||
the VarNames vector. Also, var/in has a body, this body is allowed to access
|
||||
the variables defined by the var/in.</p>
|
||||
|
||||
<p>With this ready, we can define the parser pieces. First thing we do is add
|
||||
<p>With this in place, we can define the parser pieces. The first thing we do is add
|
||||
it as a primary expression:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -972,7 +972,7 @@ definitions, and we even (trivially) allow mutation of them :).</p>
|
||||
<p>With this, we completed what we set out to do. Our nice iterative fib
|
||||
example from the intro compiles and runs just fine. The mem2reg pass optimizes
|
||||
all of our stack variables into SSA registers, inserting PHI nodes where needed,
|
||||
and our front-end remains simple: no iterated dominator frontier computation
|
||||
and our front-end remains simple: no "iterated dominance frontier" computation
|
||||
anywhere in sight.</p>
|
||||
|
||||
</div>
|
||||
|
@ -98,7 +98,7 @@ Programmer's Manual</a> that describes how to construct them.</li>
|
||||
<li><b>standard runtime</b> - Our current language allows the user to access
|
||||
arbitrary external functions, and we use it for things like "printd" and
|
||||
"putchard". As you extend the language to add higher-level constructs, often
|
||||
these constructs make the most amount of sense to be lowered into calls into a
|
||||
these constructs make the most sense if they are lowered to calls into a
|
||||
language-supplied runtime. For example, if you add hash tables to the language,
|
||||
it would probably make sense to add the routines to a runtime, instead of
|
||||
inlining them all the way.</li>
|
||||
@ -106,14 +106,14 @@ inlining them all the way.</li>
|
||||
<li><b>memory management</b> - Currently we can only access the stack in
|
||||
Kaleidoscope. It would also be useful to be able to allocate heap memory,
|
||||
either with calls to the standard libc malloc/free interface or with a garbage
|
||||
collector. If you choose to use garbage collection, note that LLVM fully
|
||||
collector. If you would like to use garbage collection, note that LLVM fully
|
||||
supports <a href="../GarbageCollection.html">Accurate Garbage Collection</a>
|
||||
including algorithms that move objects and need to scan/update the stack.</li>
|
||||
|
||||
<li><b>debugger support</b> - LLVM supports generation of <a
|
||||
href="../SourceLevelDebugging.html">DWARF Debug info</a> which is understood by
|
||||
common debuggers like GDB. Adding support for debug info is fairly
|
||||
straight-forward. The best way to understand it is to compile some C/C++ code
|
||||
straightforward. The best way to understand it is to compile some C/C++ code
|
||||
with "<tt>llvm-gcc -g -O0</tt>" and taking a look at what it produces.</li>
|
||||
|
||||
<li><b>exception handling support</b> - LLVM supports generation of <a
|
||||
@ -139,22 +139,22 @@ expression interpreter into native code with LLVM?</li>
|
||||
|
||||
<p>
|
||||
Have fun - try doing something crazy and unusual. Building a language like
|
||||
everyone else always has is much less fun than trying something a little crazy
|
||||
and off the wall and seeing how it turns out. If you get stuck or want to talk
|
||||
everyone else always has, is much less fun than trying something a little crazy
|
||||
or off the wall and seeing how it turns out. If you get stuck or want to talk
|
||||
about it, feel free to email the <a
|
||||
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">llvmdev mailing
|
||||
list</a>: it has lots of people who are interested in languages and are often
|
||||
willing to help out.
|
||||
</p>
|
||||
|
||||
<p>Before we end, I want to talk about some "tips and tricks" for generating
|
||||
<p>Before we end this tutorial, I want to talk about some "tips and tricks" for generating
|
||||
LLVM IR. These are some of the more subtle things that may not be obvious, but
|
||||
are very useful if you want to take advantage of LLVM's capabilities.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<div class="doc_section"><a name="llvmirproperties">Properties of LLVM
|
||||
<div class="doc_section"><a name="llvmirproperties">Properties of the LLVM
|
||||
IR</a></div>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
@ -184,7 +184,7 @@ compiling that on targets that LLVM doesn't support natively. You can trivially
|
||||
tell that the Kaleidoscope compiler generates target-independent code because it
|
||||
never queries for any target-specific information when generating code.</p>
|
||||
|
||||
<p>The fact that LLVM provides a compact target-independent representation for
|
||||
<p>The fact that LLVM provides a compact, target-independent, representation for
|
||||
code gets a lot of people excited. Unfortunately, these people are usually
|
||||
thinking about C or a language from the C family when they are asking questions
|
||||
about language portability. I say "unfortunately", because there is really no
|
||||
@ -208,7 +208,7 @@ the input text:</p>
|
||||
</div>
|
||||
|
||||
<p>While it is possible to engineer more and more complex solutions to problems
|
||||
like this, it cannot be solved in full generality in a way better than shipping
|
||||
like this, it cannot be solved in full generality in a way that is better than shipping
|
||||
the actual source code.</p>
|
||||
|
||||
<p>That said, there are interesting subsets of C that can be made portable. If
|
||||
@ -263,7 +263,7 @@ few observations:</p>
|
||||
writing, there is no way to distinguish in the LLVM IR whether an SSA-value came
|
||||
from a C "int" or a C "long" on an ILP32 machine (other than debug info). Both
|
||||
get compiled down to an 'i32' value and the information about what it came from
|
||||
is lost. The more general issue here is that the LLVM type system uses
|
||||
is lost. The more general issue here, is that the LLVM type system uses
|
||||
"structural equivalence" instead of "name equivalence". Another place this
|
||||
surprises people is if you have two types in a high-level language that have the
|
||||
same structure (e.g. two different structs that have a single int field): these
|
||||
@ -275,10 +275,10 @@ continue to enhance and improve it in many different ways. In addition to
|
||||
adding new features (LLVM did not always support exceptions or debug info), we
|
||||
also extend the IR to capture important information for optimization (e.g.
|
||||
whether an argument is sign or zero extended, information about pointers
|
||||
aliasing, etc. Many of the enhancements are user-driven: people want LLVM to
|
||||
do some specific feature, so they go ahead and extend it to do so.</p>
|
||||
aliasing, etc). Many of the enhancements are user-driven: people want LLVM to
|
||||
include some specific feature, so they go ahead and extend it.</p>
|
||||
|
||||
<p>Third, it <em>is possible and easy</em> to add language-specific
|
||||
<p>Third, it is <em>possible and easy</em> to add language-specific
|
||||
optimizations, and you have a number of choices in how to do it. As one trivial
|
||||
example, it is easy to add language-specific optimization passes that
|
||||
"know" things about code compiled for a language. In the case of the C family,
|
||||
@ -291,7 +291,7 @@ function does.</p>
|
||||
other language-specific information into the LLVM IR. If you have a specific
|
||||
need and run into a wall, please bring the topic up on the llvmdev list. At the
|
||||
very worst, you can always treat LLVM as if it were a "dumb code generator" and
|
||||
implement the high-level optimizations you desire in your front-end on the
|
||||
implement the high-level optimizations you desire in your front-end, on the
|
||||
language-specific AST.
|
||||
</p>
|
||||
|
||||
@ -316,8 +316,8 @@ offsetof/sizeof</a></div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>One interesting thing that comes up if you are trying to keep the code
|
||||
generated by your compiler "target independent" is that you often need to know
|
||||
<p>One interesting thing that comes up, if you are trying to keep the code
|
||||
generated by your compiler "target independent", is that you often need to know
|
||||
the size of some LLVM type or the offset of some field in an llvm structure.
|
||||
For example, you might need to pass the size of a type into a function that
|
||||
allocates memory.</p>
|
||||
@ -342,10 +342,10 @@ they are garbage collected or to allow easy implementation of closures. There
|
||||
are often better ways to implement these features than explicit stack frames,
|
||||
but <a
|
||||
href="http://nondot.org/sabre/LLVMNotes/ExplicitlyManagedStackFrames.txt">LLVM
|
||||
does support them if you want</a>. It requires your front-end to convert the
|
||||
does support them,</a> if you want. It requires your front-end to convert the
|
||||
code into <a
|
||||
href="http://en.wikipedia.org/wiki/Continuation-passing_style">Continuation
|
||||
Passing Style</a> and use of tail calls (which LLVM also supports).</p>
|
||||
Passing Style</a> and the use of tail calls (which LLVM also supports).</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user