From 415c01f74545fa4a83602ffa1f48046a341cca53 Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Thu, 9 Aug 2012 13:53:21 -0500 Subject: [PATCH] DOC: Add first version of updated documentation. --- docs/source/doc/examples.rst | 207 +----------------- docs/source/doc/examples/JITTutorial1.rst | 61 +++--- docs/source/doc/examples/JITTutorial2.rst | 87 ++++---- docs/source/doc/examples/index.rst | 10 + docs/source/doc/firstexample.rst | 125 +++++++++++ docs/source/doc/getting_started.rst | 153 +++++++++++++ .../doc/kaleidoscope/PythonLangImpl1.rst | 20 +- .../doc/kaleidoscope/PythonLangImpl2.rst | 18 +- .../doc/kaleidoscope/PythonLangImpl3.rst | 21 +- .../doc/kaleidoscope/PythonLangImpl4.rst | 19 +- .../doc/kaleidoscope/PythonLangImpl5.rst | 19 +- .../doc/kaleidoscope/PythonLangImpl6.rst | 19 +- .../doc/kaleidoscope/PythonLangImpl7.rst | 19 +- .../doc/kaleidoscope/PythonLangImpl8.rst | 15 +- docs/source/doc/kaleidoscope/index.rst | 21 ++ docs/source/doc/llvm_concepts.rst | 88 +++++--- docs/source/doc/llvmpy_package.rst | 8 +- docs/source/doc/userguide.rst | 158 +------------ docs/source/index.rst | 1 + 19 files changed, 474 insertions(+), 595 deletions(-) create mode 100644 docs/source/doc/examples/index.rst create mode 100644 docs/source/doc/firstexample.rst create mode 100644 docs/source/doc/getting_started.rst create mode 100644 docs/source/doc/kaleidoscope/index.rst diff --git a/docs/source/doc/examples.rst b/docs/source/doc/examples.rst index 98552bf..9e01700 100644 --- a/docs/source/doc/examples.rst +++ b/docs/source/doc/examples.rst @@ -1,203 +1,12 @@ -+--------------------------------------+ -| layout: page | -+--------------------------------------+ -| title: Examples and LLVM Tutorials | -+--------------------------------------+ +******************************** +Examples and LLVM Tutorials +******************************** -- This will become a table of contents (this text will be scraped). - {:toc} +.. toctree:: + :maxdepth: 1 -Examples -======== + firstexample.rst + examples/index.rst + kaleidoscope/index.rst -A Simple Function ------------------ - -Let's create a (LLVM) module containing a single function, corresponding -to the ``C`` function: - -{% highlight c %} int sum(int a, int b) { return a + b; } {% -endhighlight %} - -Here's how it looks like: - -{% highlight python %} #!/usr/bin/env python - -Import the llvmpy modules. -=========================== - -from llvm import \* from llvm.core import \* - -Create an (empty) module. -========================= - -my\_module = Module.new('my\_module') - -All the types involved here are "int"s. This type is represented -================================================================ - -by an object of the llvm.core.Type class: -========================================= - -ty\_int = Type.int() # by default 32 bits - -We need to represent the class of functions that accept two integers -==================================================================== - -and return an integer. This is represented by an object of the -============================================================== - -function type (llvm.core.FunctionType): -======================================= - -ty\_func = Type.function(ty\_int, [ty\_int, ty\_int]) - -Now we need a function named 'sum' of this type. Functions are not -================================================================== - -free-standing (in llvmpy); it needs to be contained in a module. -================================================================= - -f\_sum = my\_module.add\_function(ty\_func, "sum") - -Let's name the function arguments as 'a' and 'b'. -================================================= - -f\_sum.args[0].name = "a" f\_sum.args[1].name = "b" - -Our function needs a "basic block" -- a set of instructions that -================================================================ - -end with a terminator (like return, branch etc.). By convention -=============================================================== - -the first block is called "entry". -================================== - -bb = f\_sum.append\_basic\_block("entry") - -Let's add instructions into the block. For this, we need an -=========================================================== - -instruction builder: -==================== - -builder = Builder.new(bb) - -OK, now for the instructions themselves. We'll create an add -============================================================ - -instruction that returns the sum as a value, which we'll use -============================================================ - -a ret instruction to return. -============================ - -tmp = builder.add(f\_sum.args[0], f\_sum.args[1], "tmp") -builder.ret(tmp) - -We've completed the definition now! Let's see the LLVM assembly -=============================================================== - -language representation of what we've created: -============================================== - -print my\_module {% endhighlight %} - -Here is the output: - -{% highlight llvm %} ; ModuleID = 'my\_module' - -define i32 @sum(i32 %a, i32 %b) { entry: %tmp = add i32 %a, %b ; -[#uses=1] ret i32 %tmp } {% endhighlight %} - -Adding JIT Compilation ----------------------- - -Let's compile this function in-memory and run it. - -{% highlight python %} #!/usr/bin/env python - -Import the llvmpy modules. -=========================== - -from llvm import \* from llvm.core import \* from llvm.ee import \* # -new import: ee = Execution Engine - -Create a module, as in the previous example. -============================================ - -my\_module = Module.new('my\_module') ty\_int = Type.int() # by default -32 bits ty\_func = Type.function(ty\_int, [ty\_int, ty\_int]) f\_sum = -my\_module.add\_function(ty\_func, "sum") f\_sum.args[0].name = "a" -f\_sum.args[1].name = "b" bb = f\_sum.append\_basic\_block("entry") -builder = Builder.new(bb) tmp = builder.add(f\_sum.args[0], -f\_sum.args[1], "tmp") builder.ret(tmp) - -Create an execution engine object. This will create a JIT compiler -================================================================== - -on platforms that support it, or an interpreter otherwise. -========================================================== - -ee = ExecutionEngine.new(my\_module) - -The arguments needs to be passed as "GenericValue" objects. -=========================================================== - -arg1 = GenericValue.int(ty\_int, 100) arg2 = GenericValue.int(ty\_int, -42) - -Now let's compile and run! -========================== - -retval = ee.run\_function(f\_sum, [arg1, arg2]) - -The return value is also GenericValue. Let's print it. -====================================================== - -print "returned", retval.as\_int() {% endhighlight %} - -And here's the output: - -:: - - returned 142 - --------------- - -LLVM Tutorials -============== - -Simple JIT Tutorials --------------------- - -The following JIT tutorials were contributed by Sebastien Binet. - -1. `A First Function `_ -2. `A More Complicated Function `_ - -Kaleidoscope ## {#kaleidoscope} -------------------------------- - -Implementing a Language with LLVM - -The LLVM `Kaleidoscope `_ tutorial -has been ported to llvmpy by Max Shawabkeh. - -1. `Tutorial Introduction and the - Lexer `_ -2. `Implementing a Parser and AST `_ -3. `Implementing Code Generation to LLVM - IR `_ -4. `Adding JIT and Optimizer - Support `_ -5. `Extending the language: control - flow `_ -6. `Extending the language: user-defined - operators `_ -7. `Extending the language: mutable variables / SSA - construction `_ -8. `Conclusion and other useful LLVM - tidbits `_ diff --git a/docs/source/doc/examples/JITTutorial1.rst b/docs/source/doc/examples/JITTutorial1.rst index 7c02fb1..09f3c33 100644 --- a/docs/source/doc/examples/JITTutorial1.rst +++ b/docs/source/doc/examples/JITTutorial1.rst @@ -1,45 +1,36 @@ -+-------------------------+ -| layout: page | -+-------------------------+ -| title: JIT Tutorial 1 | -+-------------------------+ +A First Function +================== -{% highlight python %} #!/usr/bin/env python +.. code-block:: python -from llvm.core import \* + #!/usr/bin/env python + + from llvm.core import * -create a module -=============== + #create a module + module = Module.new("tut1") -module = Module.new ("tut1") + #create a function type taking 3 32-bit integers, return a 32-bit integer + ty_int = Type.int(32) + func_type = Type.function(ty_int, (ty_int,)*3) -create a function type taking 3 32-bit integers, return a 32-bit integer -======================================================================== + #create a function of that type + mul_add = Function.new (module, func_type, "mul_add") + mul_add.calling_convention = CC_C + x = mul_add.args[0]; x.name = "x" + y = mul_add.args[1]; y.name = "y" + z = mul_add.args[2]; z.name = "z" -ty\_int = Type.int (32) func\_type = Type.function (ty\_int, -(ty\_int,)\*3) + #implement the function -create a function of that type -============================== + #new block + blk = mul_add.append_basic_block("entry") -mul\_add = Function.new (module, func\_type, "mul\_add") -mul\_add.calling\_convention = CC\_C x = mul\_add.args[0]; x.name = "x" -y = mul\_add.args[1]; y.name = "y" z = mul\_add.args[2]; z.name = "z" + #IR builder + bldr = Builder.new(blk) + tmp_1 = bldr.mul(x, y, "tmp_1") + tmp_2 = bldr.add(tmp_1, z, "tmp_2") -implement the function -====================== + bldr.ret(tmp_2) -new block -========= - -blk = mul\_add.append\_basic\_block ("entry") - -IR builder -========== - -bldr = Builder.new (blk) tmp\_1 = bldr.mul (x, y, "tmp\_1") tmp\_2 = -bldr.add (tmp\_1, z, "tmp\_2") - -bldr.ret (tmp\_2) - -print(module) {% endhighlight %} + print module diff --git a/docs/source/doc/examples/JITTutorial2.rst b/docs/source/doc/examples/JITTutorial2.rst index 8c420c5..a9a9979 100644 --- a/docs/source/doc/examples/JITTutorial2.rst +++ b/docs/source/doc/examples/JITTutorial2.rst @@ -1,62 +1,55 @@ -+-------------------------+ -| layout: page | -+-------------------------+ -| title: JIT Tutorial 2 | -+-------------------------+ +A More Complicated Function +==================== -{% highlight python %} #!/usr/bin/env python +.. code-block:: python -from llvm.core import \* + #!/usr/bin/env python -create a module -=============== + from llvm.core import * -module = Module.new ("tut2") + #create a module + module = Module.new("tut2") -create a function type taking 2 integers, return a 32-bit integer -================================================================= + #create a function type taking 2 integers, return a 32-bit integer + ty_int = Type.int(32) + func_type = Type.function(ty_int, (ty_int, ty_int)) -ty\_int = Type.int (32) func\_type = Type.function (ty\_int, (ty\_int, -ty\_int)) + #create a function of that type + gcd = Function.new(module, func_type, "gcd") -create a function of that type -============================== + #name function args + x = gcd.args[0]; x.name = "x" + y = gcd.args[1]; y.name = "y" -gcd = Function.new (module, func\_type, "gcd") + #implement the function -name function args -================== + #blocks... + entry = gcd.append_basic_block("entry") + ret = gcd.append_basic_block("return") + cond_false = gcd.append_basic_block("cond_false") + cond_true = gcd.append_basic_block("cond_true") + cond_false_2 = gcd.append_basic_block("cond_false_2") -x = gcd.args[0]; x.name = "x" y = gcd.args[1]; y.name = "y" + #create a llvm::IRBuilder + bldr = Builder.new(entry) + x_eq_y = bldr.icmp(IPRED_EQ, x, y, "tmp") + bldr.cbranch(x_eq_y, ret, cond_false) -implement the function -====================== + bldr.position_at_end (ret) + bldr.ret(x) -blocks... -========= + bldr.position_at_end(cond_false) + x_lt_y = bldr.icmp(IPRED_ULT, x, y, "tmp") + bldr.cbranch(x_lt_y, cond_true, cond_false_2) -entry = gcd.append\_basic\_block ("entry") ret = -gcd.append\_basic\_block ("return") cond\_false = -gcd.append\_basic\_block ("cond\_false") cond\_true = -gcd.append\_basic\_block ("cond\_true") cond\_false\_2 = -gcd.append\_basic\_block ("cond\_false\_2") + bldr.position_at_end(cond_true) + y_sub_x = bldr.sub(y, x, "tmp") + recur_1 = bldr.call(gcd, (x, y_sub_x,), "tmp") + bldr.ret(recur_1) -create a llvm::IRBuilder -======================== + bldr.position_at_end(cond_false_2) + x_sub_y = bldr.sub(x, y, "x_sub_y") + recur_2 = bldr.call(gcd, (x_sub_y, y,), "tmp") + bldr.ret(recur_2) -bldr = Builder.new (entry) x\_eq\_y = bldr.icmp (IPRED\_EQ, x, y, "tmp") -bldr.cbranch (x\_eq\_y, ret, cond\_false) - -bldr.position\_at\_end (ret) bldr.ret(x) - -bldr.position\_at\_end (cond\_false) x\_lt\_y = bldr.icmp (IPRED\_ULT, -x, y, "tmp") bldr.cbranch (x\_lt\_y, cond\_true, cond\_false\_2) - -bldr.position\_at\_end (cond\_true) y\_sub\_x = bldr.sub (y, x, "tmp") -recur\_1 = bldr.call (gcd, (x, y\_sub\_x,), "tmp") bldr.ret (recur\_1) - -bldr.position\_at\_end (cond\_false\_2) x\_sub\_y = bldr.sub (x, y, -"x\_sub\_y") recur\_2 = bldr.call (gcd, (x\_sub\_y, y,), "tmp") bldr.ret -(recur\_2) - -print(module) {% endhighlight %} + print module diff --git a/docs/source/doc/examples/index.rst b/docs/source/doc/examples/index.rst new file mode 100644 index 0000000..0cd3532 --- /dev/null +++ b/docs/source/doc/examples/index.rst @@ -0,0 +1,10 @@ +LLVM Tutorials +============== + +The following JIT tutorials were contributed by Sebastien Binet. + +.. toctree:: + :titlesonly: + + JITTutorial1.rst + JITTutorial2.rst diff --git a/docs/source/doc/firstexample.rst b/docs/source/doc/firstexample.rst new file mode 100644 index 0000000..0f6a4d0 --- /dev/null +++ b/docs/source/doc/firstexample.rst @@ -0,0 +1,125 @@ +Examples +======== + +A Simple Function +----------------- + +Let's create a (LLVM) module containing a single function, corresponding +to the ``C`` function: + +.. code-block:: c + + int sum(int a, int b) + { + return a + b; + } + +Here's how it looks in llvmpy: + +.. code-block:: python + + #!/usr/bin/env python + + # Import the llvmpy modules. + from llvm import * + from llvm.core import * + + # Create an (empty) module. + my_module = Module.new('my_module') + + # All the types involved here are "int"s. This type is represented + # by an object of the llvm.core.Type class: + ty_int = Type.int() # by default 32 bits + + # We need to represent the class of functions that accept two integers + # and return an integer. This is represented by an object of the + # function type (llvm.core.FunctionType): + ty_func = Type.function(ty_int, [ty_int, ty_int]) + + # Now we need a function named 'sum' of this type. Functions are not + # free-standing (in llvmpy); it needs to be contained in a module. + + f_sum = my_module.add_function(ty_func, "sum") + + # Let's name the function arguments as 'a' and 'b'. + f_sum.args[0].name = "a" + f_sum.args[1].name = "b" + + # Our function needs a "basic block" -- a set of instructions that + # end with a terminator (like return, branch etc.). By convention + # the first block is called "entry". + bb = f_sum.append_basic_block("entry") + + # Let's add instructions into the block. For this, we need an + # instruction builder: + builder = Builder.new(bb) + + # OK, now for the instructions themselves. We'll create an add + # instruction that returns the sum as a value, which we'll use + # a ret instruction to return. + tmp = builder.add(f_sum.args[0], f_sum.args[1], "tmp") + builder.ret(tmp) + + # We've completed the definition now! Let's see the LLVM assembly + # language representation of what we've created: + + print my_module + +Here is the output: + +.. code-block:: llvm + + ; ModuleID = 'my_module' + + define i32 @sum(i32 %a, i32 %b) { + entry: + %tmp = add i32 %a, %b ; [#uses=1] + ret i32 %tmp + } + +Adding JIT Compilation +---------------------- + +Let's compile this function in-memory and run it. + +.. code-block:: python + + #!/usr/bin/env python + + # Import the llvmpy modules. + + from llvm import * + from llvm.core import * + from llvm.ee import * # new import: ee = Execution Engine + + #Create a module, as in the previous example. + my_module = Module.new('my_module') + ty_int = Type.int() # by default 32 bits + ty_func = Type.function(ty_int, [ty_int, ty_int]) + f_sum = my_module.add_function(ty_func, "sum") + f_sum.args[0].name = "a" + f_sum.args[1].name = "b" + bb = f_sum.append_basic_block("entry") + builder = Builder.new(bb) + tmp = builder.add(f_sum.args[0], f_sum.args[1], "tmp") + builder.ret(tmp) + + # Create an execution engine object. This will create a JIT compiler + # on platforms that support it, or an interpreter otherwise. + ee = ExecutionEngine.new(my_module) + + # The arguments needs to be passed as "GenericValue" objects. + arg1 = GenericValue.int(ty_int, 100) + arg2 = GenericValue.int(ty_int, 42) + + # Now let's compile and run! + retval = ee.run_function(f_sum, [arg1, arg2]) + + # The return value is also GenericValue. Let's print it. + print "returned", retval.as_int() + +And here's the output: + +:: + + returned 142 diff --git a/docs/source/doc/getting_started.rst b/docs/source/doc/getting_started.rst new file mode 100644 index 0000000..4d35074 --- /dev/null +++ b/docs/source/doc/getting_started.rst @@ -0,0 +1,153 @@ + +Introduction +============ + +`LLVM `_ (Low-Level Virtual Machine) provides +enough infrastructure to use it as the backend for your compiled, or +JIT-compiled language. It provides extensive optimization support, and +static and dynamic (JIT) backends for many platforms. See the website at +http://www.llvm.org/ to discover more. + +Python bindings for LLVM provides a gentler learning curve for working +with the LLVM APIs. It should also be easier to create working +prototypes and experimental languages using this medium. + +Together with `clang `_ or +`llvm-gcc `_ it also a provides a +means to quickly instrument C and C++ sources. For e.g., llvm-gcc can be +used to generate the LLVM assembly for a given C source file, which can +then be loaded and manipulated (adding profiling code to every function, +say) using a llvmpy based Python script. + +License +------- + +Both LLVM and llvmpy are distributed under (different) permissive open +source licenses. llvmpy uses the `new BSD +license `_. More +information is available +`here `_. + +Platforms +--------- + +llvmpy has been built/tested/reported to work on various GNU/Linux +flavours, BSD, Mac OS X; on i386 and amd64 architectures. Windows is not +supported, for a variety of reasons. + +Versions +-------- + +llvmpy 0.8.2 requires version 3.1 of LLVM. It may not work with +previous versions. + +llvmpy has been built and tested with Python 2.7. It should work with +earlier versions. It has not been tried with Python 3.x (patches +welcome). + + +Installation +============ + +The Git repo of llvmpy is at https://github.com/numba/llvmpy.git. +You'll need to build and install it before it can be used. At least the +following will be required for this: + +- C and C++ compilers (gcc/g++) +- Python itself +- Python development files (headers and libraries) +- LLVM, either installed or built + +On debian-based systems, the first three can be installed with the +command ``sudo apt-get install gcc g++ python python-dev``. Ensure that +your distro's repository has the appropriate version of LLVM! + +It does not matter which compiler LLVM itself was built with (``g++``, +``llvm-g++`` or any other); llvmpy can be built with any compiler. It +has been tried only with gcc/g++ though. + + +LLVM and ``--enable-pic`` +------------------------- + +The result of an LLVM build is a set of static libraries and object +files. The llvmpy contains an extension package that is built into a +shared object (\_core.so) which links to these static libraries and +object files. It is therefore required that the LLVM libraries and +object files be built with the ``-fPIC`` option (generate position +independent code). Be sure to use the ``--enable-pic`` option while +configuring LLVM (default is no PIC), like this: + +{% highlight bash %} ~/llvm$ ./configure --enable-pic --enable-optimized +{% endhighlight %} + +llvm-config +----------- + +In order to build llvmpy, it's build script needs to know from where it +can invoke the llvm helper program, ``llvm-config``. If you've installed +LLVM, then this will be available in your ``PATH``, and nothing further +needs to be done. If you've built LLVM yourself, or for any reason +``llvm-config`` is not in your ``PATH``, you'll need to pass the full +path of ``llvm-config`` to the build script. + +You'll need to be 'root' to install llvmpy. Remember that your ``PATH`` +is different from that of 'root', so even if ``llvm-config`` is in your +``PATH``, it may not be available when you do ``sudo``. + +Steps +----- + +Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to +LLVM's 'configure'. + +Get llvmpy and install it: + +{% highlight bash %} $ git clone git@github.com:numba/llvmpy.git $ cd +llvmpy $ python setup.py install {% endhighlight %} + +If you need to tell the build script where ``llvm-config`` is, do it +this way: + +{% highlight bash %} $ python setup.py install --user +--llvm-config=/home/mdevan/llvm/Release/bin/llvm-config {% endhighlight +%} + +To build a debug version of llvmpy, that links against the debug +libraries of LLVM, use this: + +{% highlight bash %} $ python setup.py build -g +--llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config $ python setup.py +install --user --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config {% +endhighlight %} + +Be warned that debug binaries will be huge (100MB+) ! They are required +only if you need to debug into LLVM also. + +``setup.py`` is a standard Python distutils script. See the Python +documentation regarding `Installing Python +Modules `_ and `Distributing +Python Modules `_ for more +information on such scripts. + + +Uninstall +============== + +If you'd installed llvmpy with the ``--user`` option, then llvmpy +would be present under ``~/.local/lib/python2.7/site-packages``. +Otherwise, it might be under ``/usr/lib/python2.7/site-packages`` or +``/usr/local/lib/python2.7/site-packages``. The directory would vary +with your Python version and OS flavour. Look around. + +Once you've located the site-packages directory, the modules and the +"egg" can be removed like so: + +{% highlight bash %} $ rm -rf /llvm /llvm\_py-.egg-info {% endhighlight +%} + +See the `Python +documentation `_ for more +information. + +-------------- diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst index 4bbb81f..3314187 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst @@ -1,24 +1,12 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 1" | -+------------------------------------+ - -Tutorial Introduction and the Lexer -=================================== +************************************************* +Chapter 1: Tutorial Introduction and the Lexer +************************************************* Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 1** - -- This will become a table of contents (this text will be scraped). - {:toc} - -`**Chapter 2: Implementing a Parser and AST** `_ - Introduction -============ +========= Welcome to the "Implementing a language with LLVM" tutorial. This tutorial runs through the implementation of a simple language, showing diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl2.rst b/docs/source/doc/kaleidoscope/PythonLangImpl2.rst index d7d3bd1..f918633 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl2.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl2.rst @@ -1,22 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 2" | -+------------------------------------+ - -Implementing a Parser and AST -============================= +*************************************************** +Chapter 2: Implementing a Parser and AST +*************************************************** Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 2** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 3: Code generation to LLVM IR `_** - Introduction # {#intro} ======================= diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl3.rst b/docs/source/doc/kaleidoscope/PythonLangImpl3.rst index 61594b1..562f0f3 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl3.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl3.rst @@ -1,23 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 3" | -+------------------------------------+ - -Code generation to LLVM IR -========================== +******************************************* +Chapter 3: Code generation to LLVM IR +******************************************* Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 3** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 4: Adding JIT and Optimizer -Support `_** - Introduction # {#intro} ======================= @@ -32,7 +19,7 @@ and parser than it is to generate LLVM IR code. :) **Please note**: the code in this chapter and later requires llvmpy 0.6 and LLVM 2.7. Earlier versions will most likely not work with it. Also note that you need to use a version of this tutorial that matches your -llvmpy release: If you are using an official llvm-py release, use the +llvmpy release: If you are using an official llvmpy release, use the version of the documentation on the `llvmpy examples page `_ diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl4.rst b/docs/source/doc/kaleidoscope/PythonLangImpl4.rst index 14cefb5..d9e32da 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl4.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl4.rst @@ -1,23 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 4" | -+------------------------------------+ - -Adding JIT and Optimizer Support -================================ +************************************************* +Chapter 4: Adding JIT and Optimizer Support +************************************************* Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 4** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 5: Extending the Language: Control -Flow `_** - Introduction # {#intro} ======================= diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst index 326a5bf..e66944e 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst @@ -1,23 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 5" | -+------------------------------------+ - -Extending the Language: Control Flow -==================================== +***************************************************** +Chapter 5: Extending the Language: Control Flow +***************************************************** Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 5** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 6: Extending the Language: User-defined -Operators `_** - Introduction # {#intro} ======================= diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst index c0c1f0e..c7e354d 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst @@ -1,23 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 6" | -+------------------------------------+ - -Extending the Language: User-defined Operators -============================================== +********************************************************************** +Chapter 6: Extending the Language: User-defined Operators +********************************************************************** Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 6** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 7: Extending the Language: Mutable Variables / SSA -Construction `_** - Introduction # {#intro} ======================= diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index ada3043..cc44969 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst @@ -1,23 +1,10 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 7" | -+------------------------------------+ - -Extending the Language: Mutable Variables / SSA construction -============================================================ +******************************************************************************* +Chapter 7: Extending the Language: Mutable Variables / SSA construction +******************************************************************************* Written by `Chris Lattner `_ and `Max Shawabkeh `_ -**Chapter 7** - -- This will become a table of contents (this text will be scraped). - {:toc} - -**`Chapter 8: Conclusion and other useful LLVM -tidbits `_** - Introduction # {#intro} ======================= diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst index cb9eebf..d9b81ac 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst @@ -1,18 +1,9 @@ -+------------------------------------+ -| layout: page | -+------------------------------------+ -| title: "Kaleidoscope: Chapter 8" | -+------------------------------------+ - -Conclusion and other useful LLVM tidbits -======================================== +***************************************************************** +Chapter 8: Conclusion and other useful LLVM tidbits +***************************************************************** Written by `Chris Lattner `_ -**Chapter 8** - -- This will become a table of contents (this text will be scraped). - {:toc} Tutorial Conclusion # {#conclusion} =================================== diff --git a/docs/source/doc/kaleidoscope/index.rst b/docs/source/doc/kaleidoscope/index.rst new file mode 100644 index 0000000..6099fea --- /dev/null +++ b/docs/source/doc/kaleidoscope/index.rst @@ -0,0 +1,21 @@ +Kaleidoscope +-------------- + +Implementing a Language with LLVM + +The LLVM `Kaleidoscope `_ tutorial +has been ported to llvmpy by Max Shawabkeh. + +.. toctree:: + :titlesonly: + :numbered: + + PythonLangImpl1.rst + PythonLangImpl2.rst + PythonLangImpl3.rst + PythonLangImpl4.rst + PythonLangImpl5.rst + PythonLangImpl6.rst + PythonLangImpl7.rst + PythonLangImpl8.rst + diff --git a/docs/source/doc/llvm_concepts.rst b/docs/source/doc/llvm_concepts.rst index a5b449b..c5f74aa 100644 --- a/docs/source/doc/llvm_concepts.rst +++ b/docs/source/doc/llvm_concepts.rst @@ -1,12 +1,16 @@ -+------------------------+ -| layout: page | -+------------------------+ -| title: LLVM Concepts | -+------------------------+ +******************** +LLVM Concepts +******************** This section explains a few concepts related to LLVM, not specific to llvmpy. +.. toctree:: + :hidden: + + + + Intermediate Representation =========================== @@ -36,7 +40,6 @@ instructions related to variable argument handling, exception handling, and garbage collection. These allow high-level languages to be represented cleanly in the IR. --------------- SSA Form and PHI Nodes ====================== @@ -51,15 +54,24 @@ when a variable can be assigned a different value based on the path of control flow. For example, the value of *b* at the end of execution of the snippet below: -{% highlight c %} a = 1; if (v < 10) a = 2; b = a; {% endhighlight %} +.. code-block:: c + + a = 1; + if (v < 10) + a = 2; + b = a; cannot be determined statically. The value of '2' cannot be assigned to the 'original' *a*, since *a* can be assigned to only once. There are two *a* 's in there, and the last assignment has to choose between which version to pick. This is accomplished by adding a PHI node: -{% highlight c %} a1 = 1; if (v < 10) a2 = 2; b = PHI(a1, a2); {% -endhighlight %} +.. code-block:: c + + a1 = 1; + if (v < 10) + a2 = 2; + b = PHI(a1, a2); The PHI node selects *a1* or *a2*, depending on where the control reached the PHI node. The argument *a1* of the PHI node is associated @@ -68,7 +80,6 @@ with the block *"a1 = 1;"* and *a2* with the block *"a2 = 2;"*. PHI nodes have to be explicitly created in the LLVM IR. Accordingly the LLVM instruction set has an instruction called *phi*. --------------- LLVM Assembly Language ====================== @@ -90,30 +101,48 @@ language code. Just to get a feel of the LLVM assembly language, here's a function in C, and the corresponding LLVM assembly (as generated by the demo page): -{% highlight c %} /\* compute sum of 1..n \*/ unsigned sum(unsigned n) { -if (n == 0) return 0; else return n + sum(n-1); } {% endhighlight %} +.. code-block:: c + + /* compute sum of 1..n */ + unsigned sum(unsigned n) { + if (n == 0) + return 0; + else + return n + sum(n-1); + } The corresponding LLVM assembly: -{% highlight llvm %} ; ModuleID = '/tmp/webcompile/\_7149\_0.bc' target -datalayout = -"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" -target triple = "x86\_64-linux-gnu" +.. code-block:: llvm -define i32 @sum(i32 %n) nounwind readnone { entry: %0 = icmp eq i32 %n, -0 ; [#uses=1] br i1 %0, label %bb2, label %bb1 + ; ModuleID = '/tmp/webcompile/_7149_0.bc' + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + target triple = "x86_64-linux-gnu" -bb1: ; preds = %entry %1 = add i32 %n, -1 ; [#uses=2] %2 = icmp eq i32 -%1, 0 ; [#uses=1] br i1 %2, label %sum.exit, label %bb1.i + define i32 @sum(i32 %n) nounwind readnone { + entry: + %0 = icmp eq i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb2, label %bb1 -bb1.i: ; preds = %bb1 %3 = add i32 %n, -2 ; [#uses=1] %4 = tail call i32 -@sum(i32 %3) nounwind ; [#uses=1] %5 = add i32 %4, %1 ; [#uses=1] br -label %sum.exit + bb1: ; preds = %entry + %1 = add i32 %n, -1 ; [#uses=2] + %2 = icmp eq i32 %1, 0 ; [#uses=1] + br i1 %2, label %sum.exit, label %bb1.i -sum.exit: ; preds = %bb1.i, %bb1 %6 = phi i32 [ %5, %bb1.i ], [ 0, %bb1 -] ; [#uses=1] %7 = add i32 %6, %n ; [#uses=1] ret i32 %7 + bb1.i: ; preds = %bb1 + %3 = add i32 %n, -2 ; [#uses=1] + %4 = tail call i32 @sum(i32 %3) nounwind ; [#uses=1] + %5 = add i32 %4, %1 ; [#uses=1] + br label %sum.exit -bb2: ; preds = %entry ret i32 0 } {% endhighlight %} + sum.exit: ; preds = %bb1.i, %bb1 + %6 = phi i32 [ %5, %bb1.i ], [ 0, %bb1 ] ; [#uses=1] + %7 = add i32 %6, %n ; [#uses=1] + ret i32 %7 + + bb2: ; preds = %entry + ret i32 0 + } Note the usage of SSA form. The long string called ``target datalayout`` is a specification of the platform ABI (like endianness, sizes of types, @@ -122,7 +151,6 @@ alignment etc.). The `LLVM Language Reference `_ defines the LLVM assembly language including the entire instruction set. --------------- Modules ======= @@ -139,7 +167,6 @@ contained within modules. Modules may be combined (linked) together to give a bigger resultant module. During this process LLVM attempts to reconcile the references between the combined modules. --------------- Optimization and Passes ======================= @@ -184,7 +211,6 @@ LLVM defines two kinds of pass managers: `PassManager `_ manages module passes for optimizing the entire module. --------------- Bitcode ======= @@ -195,7 +221,6 @@ compiler `_. See `LLVM documentation `_ for detail about the bitcode format. --------------- Execution Engine, JIT and Interpreter ===================================== @@ -209,6 +234,3 @@ multiple modules. Inter-module reference is not possible. That is module ``A`` cannot call a function in module ``B``, directly. --------------- - -**Next** -- `llvmpy Package <./llvm-py_package.html>`_ diff --git a/docs/source/doc/llvmpy_package.rst b/docs/source/doc/llvmpy_package.rst index 1a9ad6f..fc690fc 100644 --- a/docs/source/doc/llvmpy_package.rst +++ b/docs/source/doc/llvmpy_package.rst @@ -1,8 +1,6 @@ -+------------------------------+ -| layout: page | -+------------------------------+ -| title: The llvmpy Package | -+------------------------------+ +*********************** +The llvmpy Package +*********************** The llvmpy is a Python package, consisting of 6 modules, that wrap over enough LLVM APIs to allow the implementation of your own compiler/VM diff --git a/docs/source/doc/userguide.rst b/docs/source/doc/userguide.rst index 8b5c267..1bb4b4f 100644 --- a/docs/source/doc/userguide.rst +++ b/docs/source/doc/userguide.rst @@ -6,158 +6,12 @@ llvmpy provides Python bindings for LLVM. This document explains how you can setup and use it. A working knowledge of Python and a basic idea of LLVM is assumed. -Introduction -============ +.. toctree:: + :maxdepth: 1 -`LLVM `_ (Low-Level Virtual Machine) provides -enough infrastructure to use it as the backend for your compiled, or -JIT-compiled language. It provides extensive optimization support, and -static and dynamic (JIT) backends for many platforms. See the website at -http://www.llvm.org/ to discover more. + getting_started.rst + llvm_concepts.rst + llvmpy_package.rst + -Python bindings for LLVM provides a gentler learning curve for working -with the LLVM APIs. It should also be easier to create working -prototypes and experimental languages using this medium. -Together with `clang `_ or -`llvm-gcc `_ it also a provides a -means to quickly instrument C and C++ sources. For e.g., llvm-gcc can be -used to generate the LLVM assembly for a given C source file, which can -then be loaded and manipulated (adding profiling code to every function, -say) using a llvmpy based Python script. - -License -------- - -Both LLVM and llvmpy are distributed under (different) permissive open -source licenses. llvmpy uses the `new BSD -license `_. More -information is available -`here `_. - -Platforms ---------- - -llvmpy has been built/tested/reported to work on various GNU/Linux -flavours, BSD, Mac OS X; on i386 and amd64 architectures. Windows is not -supported, for a variety of reasons. - -Versions --------- - -llvmpy 0.8.2 requires version 3.1 of LLVM. It may not work with -previous versions. - -llvmpy has been built and tested with Python 2.7. It should work with -earlier versions. It has not been tried with Python 3.x (patches -welcome). - --------------- - -Installation -============ - -The Git repo of llvmpy is at https://github.com/numba/llvmpy.git. -You'll need to build and install it before it can be used. At least the -following will be required for this: - -- C and C++ compilers (gcc/g++) -- Python itself -- Python development files (headers and libraries) -- LLVM, either installed or built - -On debian-based systems, the first three can be installed with the -command ``sudo apt-get install gcc g++ python python-dev``. Ensure that -your distro's repository has the appropriate version of LLVM! - -It does not matter which compiler LLVM itself was built with (``g++``, -``llvm-g++`` or any other); llvmpy can be built with any compiler. It -has been tried only with gcc/g++ though. - -LLVM and ``--enable-pic`` -------------------------- - -The result of an LLVM build is a set of static libraries and object -files. The llvmpy contains an extension package that is built into a -shared object (\_core.so) which links to these static libraries and -object files. It is therefore required that the LLVM libraries and -object files be built with the ``-fPIC`` option (generate position -independent code). Be sure to use the ``--enable-pic`` option while -configuring LLVM (default is no PIC), like this: - -{% highlight bash %} ~/llvm$ ./configure --enable-pic --enable-optimized -{% endhighlight %} - -llvm-config ------------ - -In order to build llvmpy, it's build script needs to know from where it -can invoke the llvm helper program, ``llvm-config``. If you've installed -LLVM, then this will be available in your ``PATH``, and nothing further -needs to be done. If you've built LLVM yourself, or for any reason -``llvm-config`` is not in your ``PATH``, you'll need to pass the full -path of ``llvm-config`` to the build script. - -You'll need to be 'root' to install llvmpy. Remember that your ``PATH`` -is different from that of 'root', so even if ``llvm-config`` is in your -``PATH``, it may not be available when you do ``sudo``. - -Steps ------ - -Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to -LLVM's 'configure'. - -Get llvmpy and install it: - -{% highlight bash %} $ git clone git@github.com:numba/llvmpy.git $ cd -llvmpy $ python setup.py install {% endhighlight %} - -If you need to tell the build script where ``llvm-config`` is, do it -this way: - -{% highlight bash %} $ python setup.py install --user ---llvm-config=/home/mdevan/llvm/Release/bin/llvm-config {% endhighlight -%} - -To build a debug version of llvmpy, that links against the debug -libraries of LLVM, use this: - -{% highlight bash %} $ python setup.py build -g ---llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config $ python setup.py -install --user --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config {% -endhighlight %} - -Be warned that debug binaries will be huge (100MB+) ! They are required -only if you need to debug into LLVM also. - -``setup.py`` is a standard Python distutils script. See the Python -documentation regarding `Installing Python -Modules `_ and `Distributing -Python Modules `_ for more -information on such scripts. - --------------- - -Uninstall # {#uninstall} -======================== - -If you'd installed llvmpy with the ``--user`` option, then llvmpy -would be present under ``~/.local/lib/python2.7/site-packages``. -Otherwise, it might be under ``/usr/lib/python2.7/site-packages`` or -``/usr/local/lib/python2.7/site-packages``. The directory would vary -with your Python version and OS flavour. Look around. - -Once you've located the site-packages directory, the modules and the -"egg" can be removed like so: - -{% highlight bash %} $ rm -rf /llvm /llvm\_py-.egg-info {% endhighlight -%} - -See the `Python -documentation `_ for more -information. - --------------- - -**Next** -- :doc:`llvm_concepts` diff --git a/docs/source/index.rst b/docs/source/index.rst index 76670e6..fbca2ec 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,6 +10,7 @@ Contents: .. toctree:: :titlesonly: + :maxdepth: 2 doc/userguide.rst doc/examples.rst