You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
19 KiB
245 lines
19 KiB
LLVM Bindings for Lua/Ravi
|
|
==========================
|
|
|
|
As part of the Ravi Programming Language, it is my intention to provide a Lua 5.3 compatible LLVM binding.
|
|
This will allow Lua programmers to write their own JIT compilers in Lua!
|
|
|
|
Right now this is in early development so there is no documentation. But the Lua programs here
|
|
demonstrate the features available to date.
|
|
|
|
LLVM Modules and Execution Engines
|
|
----------------------------------
|
|
One of the complexities of LLVM is the handling of modules and execution engines in a JIT environment. In Ravi I made the simple decision that each Lua function would get its own module and EE. This allows the function to be
|
|
garbage collected as normal and release the associated module and EE. One of
|
|
the things that is possible but not yet implemented is releasing the module
|
|
and EE early; this requires implementing a custom memory manager (issue #48).
|
|
|
|
To mimic the Ravi model, the LLVM bindings provide a shortcut to setup
|
|
an LLVM module and execution engine for a Lua C function. The following example
|
|
illustrates::
|
|
|
|
-- Get the LLVM context - right now this is the
|
|
-- global context
|
|
local context = llvm.context()
|
|
|
|
-- Create a lua_CFunction instance
|
|
-- At this stage the function will get a module and
|
|
-- execution engine but no body
|
|
local mainfunc = context:lua_CFunction("demo")
|
|
|
|
Above creates an ``llvm::Function`` instance within a new module. An EE is
|
|
automatically attached. You can get hold of the module as shown below::
|
|
|
|
-- Get hold of the module
|
|
local module = mainfunc:module()
|
|
|
|
Other native functions may be created within the same module as normal. However
|
|
note that once the Lua function is compiled then no further updates to the
|
|
module are possible.
|
|
|
|
The model I recommend when using this feature is to create one exported
|
|
Lua C function in the module, with several private 'internal' supporting functions within the module.
|
|
|
|
Creating Modules and Execution Engines
|
|
--------------------------------------
|
|
The LLVM api for these functions are not exposed yet.
|
|
|
|
Examples
|
|
--------
|
|
For examples that illustrate the bindings please visit the `llvmbindings folder <https://github.com/dibyendumajumdar/ravi/tree/master/llvmbinding>`_ in the repository.
|
|
|
|
Type Hierarchy
|
|
--------------
|
|
The bindings provide a number of Lua types::
|
|
|
|
+ LLVMcontext
|
|
+ LLVMfunction
|
|
+ LLVMmainfunction
|
|
+ LLVMmodule
|
|
+ LLVMtype
|
|
+ LLVMstructtype
|
|
+ LLVMpointertype
|
|
+ LLVMfunctiontype
|
|
+ LLVMvalue
|
|
+ LLVMinstruction
|
|
+ LLVMconstant
|
|
+ LLVMphinode
|
|
+ LLVMirbuilder
|
|
+ LLVMbasicblock
|
|
|
|
|
|
Available Bindings
|
|
------------------
|
|
The following table lists the Lua LLVM api functions available.
|
|
|
|
+----------------------------------------------------------------------------------------------+
|
|
| Lua LLVM API |
|
|
+==============================================================================================+
|
|
| ``llvm.context() -> LLVMcontext`` |
|
|
| Returns global llvm::Context |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMcontext methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``lua_CFunction(name) -> LLVMmainfunction`` |
|
|
| Creates an llvm::Function within a new llvm::Module; and associates an |
|
|
| llvm::ExecutionEngine with the module |
|
|
| ``types() -> table of predefined type bindings`` |
|
|
| Returns a table of predefined LLVM type bindings |
|
|
| ``structtype(name) -> LLVMstructtype`` |
|
|
| Opaque struct type; body can be added |
|
|
| ``pointertype(type) -> LLVMpointertype`` |
|
|
| Given a type returns a pointertype |
|
|
| ``functiontype(return_type, {argtypes}, {options}) -> LLVMfunctiontype`` |
|
|
| Creates a function type with specified return type, argument types. Takes the option |
|
|
| 'vararg' which is false by default. |
|
|
| ``basicblock(name) -> LLVMbasicblock`` |
|
|
| Create a basic block |
|
|
| ``intconstant(intgervalue) -> LLVMvalue`` |
|
|
| Returns an integer constant value |
|
|
| ``nullconstant(pointertype) -> LLVMvalue`` |
|
|
| Returns a NULL constant of specified pointertype |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMstructtype methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``setbody({types})`` |
|
|
| Adds members to the struct type |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMmainfunction methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``appendblock(LLVMbasicblock)`` |
|
|
| Adds a basic block to the end |
|
|
| ``compile()`` |
|
|
| Compiles the module and returns a reference to the C Closure |
|
|
| ``arg(position) -> LLVMvalue`` |
|
|
| Returns the argument at position; position >= 1; returns ``nil`` if argument not available |
|
|
| ``module() -> LLVMmodule`` |
|
|
| Returns the module associated with the function |
|
|
| ``extern(name[, functiontype]) -> LLVMconstant`` |
|
|
| Returns an extern declaration; A number of Lua Api functions are predefined. |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMmodule methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``newfunction(name, functiontype) -> LLVMfunction`` |
|
|
| Returns an internal linkage function within the module |
|
|
| ``dump()`` |
|
|
| Dumps the module |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMfunction methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``appendblock(LLVMbasicblock)`` |
|
|
| Adds a basic block to the end |
|
|
| ``arg(position) -> LLVMvalue`` |
|
|
| Returns the argument at position; position >= 1; returns ``nil`` if argument not available |
|
|
| ``alloca(type[, name [,arraysize]]) -> LLVMinstruction`` |
|
|
| Creates a variable in the first block of the function |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMirbuilder methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``setinsertpoint(basicblock)`` |
|
|
| Set current basicblock |
|
|
| ``ret([value])`` |
|
|
| Emit return instruction |
|
|
| ``stringconstant(string) -> LLVMvalue`` |
|
|
| Create a global string constant |
|
|
| ``call({args}, {options}) -> LLVMinstruction`` |
|
|
| Emit call instruction; 'tailcall' option is false by default |
|
|
| ``br(basicblock) -> LLVMinstruction`` |
|
|
| Emit a branch instruction |
|
|
| ``condbr(value, true_block, false_block) -> LLVMinstruction`` |
|
|
| Emit a conditional branch |
|
|
| ``phi(type, num_values[, name]) -> LLVMphinode`` |
|
|
| Generate a PHINode |
|
|
| |
|
|
| GEP Operators |
|
|
| |
|
|
| ``gep(value, {offsets}) -> LLVMvalue`` |
|
|
| getelementptr to obtain ptr to an array or struct element |
|
|
| ``inboundsgep(value, {offsets}) -> LLVMvalue`` |
|
|
| inbounds version of getelementptr |
|
|
| |
|
|
| Memory Operators |
|
|
| |
|
|
| ``load(ptr) -> LLVMinstruction`` |
|
|
| Loads the value at ptr |
|
|
| ``store(value, ptr) -> LLVMinstruction`` |
|
|
| Stores the value to ptr |
|
|
| |
|
|
| Binary Operators of the form ``op(value1, value2) -> LLVMvalue`` |
|
|
| |
|
|
| * ``icmpeq`` |
|
|
| * ``icmpne`` |
|
|
| * ``icmpugt`` |
|
|
| * ``icmpuge`` |
|
|
| * ``icmpult`` |
|
|
| * ``icmpule`` |
|
|
| * ``icmpsgt`` |
|
|
| * ``icmpsge`` |
|
|
| * ``icmpslt`` |
|
|
| * ``icmpsle`` |
|
|
| * ``fcmpoeq`` |
|
|
| * ``fcmpogt`` |
|
|
| * ``fcmpoge`` |
|
|
| * ``fcmpolt`` |
|
|
| * ``fcmpole`` |
|
|
| * ``fcmpone`` |
|
|
| * ``fcmpord`` |
|
|
| * ``fcmpun`` |
|
|
| * ``fcmpueq`` |
|
|
| * ``fcmpugt`` |
|
|
| * ``fcmpuge`` |
|
|
| * ``fcmpult`` |
|
|
| * ``fcmpule`` |
|
|
| * ``fcmpune`` |
|
|
| * ``nswadd`` |
|
|
| * ``nuwadd`` |
|
|
| * ``nswsub`` |
|
|
| * ``nuwsub`` |
|
|
| * ``udiv`` |
|
|
| * ``exactudiv`` |
|
|
| * ``sdiv`` |
|
|
| * ``exactsdiv`` |
|
|
| * ``urem`` |
|
|
| * ``srem`` |
|
|
| * ``and`` |
|
|
| * ``or`` |
|
|
| * ``xor`` |
|
|
| * ``fadd`` |
|
|
| * ``fsub`` |
|
|
| * ``fmul`` |
|
|
| * ``fdiv`` |
|
|
| * ``frem`` |
|
|
| |
|
|
| Unary Operators of the form ``op(value) -> LLVMvalue`` |
|
|
| |
|
|
| * ``not`` |
|
|
| * ``neg`` |
|
|
| * ``fneg`` |
|
|
| |
|
|
| Conversion Operators of the form ``op(value,type) -> LLVMvalue`` |
|
|
| |
|
|
| * ``trunc`` |
|
|
| * ``zext`` |
|
|
| * ``sext`` |
|
|
| * ``zextortrunc`` |
|
|
| * ``sextortrunc`` |
|
|
| * ``fptoui`` |
|
|
| * ``fptosi`` |
|
|
| * ``uitofp`` |
|
|
| * ``sitofp`` |
|
|
| * ``fptrunc`` |
|
|
| * ``fpext`` |
|
|
| * ``ptrtoint`` |
|
|
| * ``inttoptr`` |
|
|
| * ``bitcast`` |
|
|
| * ``sextorbitcast`` |
|
|
| * ``zextorbitcast`` |
|
|
| * ``truncorbitcast`` |
|
|
| * ``pointercast`` |
|
|
| * ``fpcast`` |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| **LLVMphinode methods** |
|
|
+----------------------------------------------------------------------------------------------+
|
|
| ``addincoming(value, basicblock)`` |
|
|
| Adds incoming edge |
|
|
+----------------------------------------------------------------------------------------------+
|