diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl4.rst b/docs/source/doc/kaleidoscope/PythonLangImpl4.rst index 84b28e2..3b94ce9 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl4.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl4.rst @@ -403,13 +403,11 @@ example, we can create a C file with the following simple function: #include 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 diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst index 9dae1b9..eb113e2 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst @@ -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 diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst index 01876eb..382f0ef 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst @@ -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 `_. 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 diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index c64b070..be681d6 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst @@ -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