Removed more extraneous code tags from docs.
This commit is contained in:
parent
8e00cd7e66
commit
1b67d32f4b
4 changed files with 10 additions and 20 deletions
|
|
@ -403,13 +403,11 @@ example, we can create a C file with the following simple function:
|
|||
#include <stdio.h>
|
||||
|
||||
double putchard(double x) {
|
||||
putchar((char)x); return 0; } {%
|
||||
endhighlight %}
|
||||
putchar((char)x); return 0; }
|
||||
|
||||
We can then compile this into a shared library with GCC:
|
||||
|
||||
gcc -shared -fPIC -o putchard.so putchard.c {%
|
||||
endhighlight %}
|
||||
gcc -shared -fPIC -o putchard.so putchard.c
|
||||
|
||||
Now we can load this library into the Python process using
|
||||
``llvm.core.load_library_permanently`` and access it from Kaleidoscope
|
||||
|
|
|
|||
|
|
@ -601,8 +601,7 @@ expression for the loop value:
|
|||
.. code-block:: python
|
||||
|
||||
def CodeGen(self): # Emit the start code first,
|
||||
without 'variable' in scope. start_value = self.start.CodeGen() {%
|
||||
endhighlight %}
|
||||
without 'variable' in scope. start_value = self.start.CodeGen()
|
||||
|
||||
With this out of the way, the next step is to set up the LLVM basic
|
||||
block for the start of the loop body. In the case above, the whole loop
|
||||
|
|
|
|||
|
|
@ -91,8 +91,7 @@ keywords:
|
|||
BinaryToken(object): pass class UnaryToken(object): pass ... def
|
||||
Tokenize(string): ... elif identifier == 'in': yield InToken() elif
|
||||
identifier == 'binary': yield BinaryToken() elif identifier == 'unary':
|
||||
yield UnaryToken() else: yield IdentifierToken(identifier) {%
|
||||
endhighlight %}
|
||||
yield UnaryToken() else: yield IdentifierToken(identifier)
|
||||
|
||||
This just adds lexer support for the unary and binary keywords, like we
|
||||
did in `previous chapters <PythonLangImpl5.html#iflexer>`_. One nice
|
||||
|
|
@ -446,8 +445,7 @@ denser the character:
|
|||
' else if d > 4 then putchard(46) # '.' else if d > 2 then putchard(43)
|
||||
# '+' else putchard(42); # '*' ... ready> printdensity(1):
|
||||
printdensity(2): printdensity(3) : printdensity(4): printdensity(5):
|
||||
printdensity(9): putchard(10)*\ ++.. Evaluated to 0.000000 {%
|
||||
endhighlight %}
|
||||
printdensity(9): putchard(10)*\ ++.. Evaluated to 0.000000
|
||||
|
||||
Based on these simple primitive operations, we can start to define more
|
||||
interesting things. For example, here's a little function that solves
|
||||
|
|
|
|||
|
|
@ -350,8 +350,7 @@ from the stack slot:
|
|||
def CodeGen(self): if self.name in
|
||||
g_named_values: return
|
||||
g_llvm_builder.load(g_named_values[self.name], self.name) else:
|
||||
raise RuntimeError('Unknown variable name: ' + self.name) {%
|
||||
endhighlight %}
|
||||
raise RuntimeError('Unknown variable name: ' + self.name)
|
||||
|
||||
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
|
||||
|
|
@ -431,8 +430,7 @@ get good codegen once again:
|
|||
g_llvm_pass_manager.add(PASS_PROMOTE_MEMORY_TO_REGISTER) # Do
|
||||
simple "peephole" optimizations and bit-twiddling optzns.
|
||||
g_llvm_pass_manager.add(PASS_INSTRUCTION_COMBINING) # Reassociate
|
||||
expressions. g_llvm_pass_manager.add(PASS_REASSOCIATE) {%
|
||||
endhighlight %}
|
||||
expressions. g_llvm_pass_manager.add(PASS_REASSOCIATE)
|
||||
|
||||
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
|
||||
|
|
@ -448,8 +446,7 @@ get good codegen once again:
|
|||
%subtmp5 = fsub double %x4, 2.000000e+00 %calltmp6 = call double
|
||||
@fib(double %subtmp5) %addtmp = fadd double %calltmp, %calltmp6 br label
|
||||
%ifcont ifcont: ; preds = %else, %then %iftmp = phi double [
|
||||
1.000000e+00, %then ], [ %addtmp, %else ] ret double %iftmp } {%
|
||||
endhighlight %}
|
||||
1.000000e+00, %then ], [ %addtmp, %else ] ret double %iftmp }
|
||||
|
||||
Here there is only one variable (x, the input argument) but you can
|
||||
still see the extremely simple-minded code generation strategy we are
|
||||
|
|
@ -517,8 +514,7 @@ step is to set a precedence:
|
|||
def main(): ... # Install standard binary
|
||||
operators. # 1 is lowest possible precedence. 40 is the highest.
|
||||
g_binop_precedence['='] = 2 g_binop_precedence['<'] = 10
|
||||
g_binop_precedence['+'] = 20 g_binop_precedence['-'] = 20 {%
|
||||
endhighlight %}
|
||||
g_binop_precedence['+'] = 20 g_binop_precedence['-'] = 20
|
||||
|
||||
Now that the parser knows the precedence of the binary operator, it
|
||||
takes care of all the parsing and AST generation. We just need to
|
||||
|
|
@ -529,8 +525,7 @@ step is to set a precedence:
|
|||
special case for '=' because we don't want to emit the LHS as an #
|
||||
expression. if self.operator == '=': # Assignment requires the LHS to be
|
||||
an identifier. if not isinstance(self.left, VariableExpressionNode):
|
||||
raise RuntimeError('Destination of "=" must be a variable.') {%
|
||||
endhighlight %}
|
||||
raise RuntimeError('Destination of "=" must be a variable.')
|
||||
|
||||
Unlike the rest of the binary operators, our assignment operator doesn't
|
||||
follow the "emit LHS, emit RHS, do computation" model. As such, it is
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue