From ea5e34f447e85757f9ff916fad83c46635f36fbb Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Fri, 17 Jan 2020 16:01:39 +0000 Subject: [PATCH] issue #180 removing llvm lua api --- include/lualib.h | 5 - llvmbinding/README.rst | 8 - llvmbinding/basics.lua | 107 --- llvmbinding/fib.lua | 141 --- llvmbinding/helloworld.lua | 63 -- readthedocs/index.rst | 1 - readthedocs/llvm-bindings.rst | 244 ----- src/linit.c | 3 - src/ravi_llvmluaapi.cpp | 1618 --------------------------------- 9 files changed, 2190 deletions(-) delete mode 100644 llvmbinding/README.rst delete mode 100644 llvmbinding/basics.lua delete mode 100644 llvmbinding/fib.lua delete mode 100644 llvmbinding/helloworld.lua delete mode 100644 readthedocs/llvm-bindings.rst delete mode 100644 src/ravi_llvmluaapi.cpp diff --git a/include/lualib.h b/include/lualib.h index e34f601..c029c7a 100644 --- a/include/lualib.h +++ b/include/lualib.h @@ -57,11 +57,6 @@ LUAMOD_API int (raviopen_llvmjit)(lua_State *L); #define LUA_ASTLIBNAME "ast" LUAMOD_API int (raviopen_ast_library)(lua_State *L); -//#ifdef USE_LLVM -//#define LUA_LLVMLIBNAME "llvm" -//LUAMOD_API int (raviopen_llvmluaapi)(lua_State *L); -//#endif -/** RAVI change end */ /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/llvmbinding/README.rst b/llvmbinding/README.rst deleted file mode 100644 index a07a320..0000000 --- a/llvmbinding/README.rst +++ /dev/null @@ -1,8 +0,0 @@ -These are examples using the Lua LLVM bindings. - -``helloworld.lua`` - This illustrates creating a Lua callable C function that prints hello world. -``fib.lua`` - This illustrates implementing a fibonacci sequence in LLVM using Lua. - - diff --git a/llvmbinding/basics.lua b/llvmbinding/basics.lua deleted file mode 100644 index af628c2..0000000 --- a/llvmbinding/basics.lua +++ /dev/null @@ -1,107 +0,0 @@ --- ensure that LLVM bindings are available -assert(llvm) - --- Get the LLVM context - right now this is the --- global context -context = llvm.context() -assert(ravitype(context) == "LLVMcontext") - --- The bindings provide a number of predefined types that --- are Lua specific plus some standard C types such as 'int', --- 'double', 'int64_t', etc. -types = context:types() -print 'Listing types' -for k,v in pairs(types) do - print('\t', k, ravitype(v)) - llvm.dump(v) -end - --- ***************************************************\ --- Test creating a struct type --- Just as an exercise create a struct type --- Initially we have an opaque struct -gcobject = context:structtype("GCObject") -assert(ravitype(gcobject) == "LLVMstructtype") - --- Create pointer to GCObject -gcobject_p = context:pointertype(gcobject) -assert(ravitype(gcobject_p) == "LLVMpointertype") - --- Add the members of the struct --- Following demonstrates the use of predefined Lua types -gcobject:setbody {gcobject_p, types.lu_byte, types.lu_byte} - --- Display structure of gcobject -llvm.dump(gcobject) - --- ****************************************************/ - --- ****************************************************\ --- Test building a Lua C function without writing C code! --- --- Create a lua_CFunction instance --- At this stage the function will get a module and --- execution engine but no body -myfunc = context:lua_CFunction("myfunc") -assert(ravitype(myfunc) == "LLVMmainfunction") - --- Get a new IRBuilder intance --- this will be garbage collected by Lua -irbuilder = context:irbuilder() -assert(ravitype(irbuilder) == "LLVMirbuilder") - --- Create a basic block -block = context:basicblock("entry") --- Add it to the end of the function -myfunc:appendblock(block) --- Set this as the next instruction point -irbuilder:setinsertpoint(block) - ------------------------------------------------ --- Test calling a predefined extern function --- Get printf decl ------------------------------------------------ -printf = myfunc:extern("printf") -assert(ravitype(printf) == "LLVMconstant") - -luaL_checklstring = myfunc:extern("luaL_checklstring") -assert(ravitype(luaL_checklstring) == "LLVMconstant") - -hellostr = irbuilder:stringconstant("hello world!\n") -irbuilder:call(printf, { hellostr }) - -------------------------------------------------- --- Test calling a random function -------------------------------------------------- -puts_type = context:functiontype(types.int, {types.pchar}, {vararg=false}) -assert(ravitype(puts_type) == "LLVMfunctiontype") - --- Declare extern puts() -puts = myfunc:extern("puts", puts_type); -assert(ravitype(puts) == "LLVMconstant") - --- Get the L parameter of myfunc -L = myfunc:arg(1) - --- get the first argument as a string -str = irbuilder:call(luaL_checklstring, {L, context:intconstant(1), - context:nullconstant(types.psize_t)} ) - --- Call puts -irbuilder:call(puts, { str }) - --- add CreateRet(0) -inst = irbuilder:ret(context:intconstant(0)) -assert(ravitype(inst) == "LLVMinstruction") --- **************************************************/ - --- what did we get? -llvm.dump(myfunc) - --- JIT compile the function --- returns a C Closure -runnable = myfunc:compile() - -print('Type of compiled function is', type(runnable)) -assert(not runnable('ok\n')) - diff --git a/llvmbinding/fib.lua b/llvmbinding/fib.lua deleted file mode 100644 index 339efe6..0000000 --- a/llvmbinding/fib.lua +++ /dev/null @@ -1,141 +0,0 @@ --- This program demonstrates creating a --- recursive fibonacci calc function in LLVM --- Example based upon --- https://llvm.org/svn/llvm-project/llvm/trunk/examples/Fibonacci/fibonacci.cpp - - --- ensure that LLVM bindings are available -assert(llvm) - - --- Generate the fibonacci function -local function makefib(context, module, types) - - -- The goal of this snippet is to create in the memory the LLVM module - -- consisting of one function as follow: - -- - -- int fib(int x) { - -- if(x<=2) return 1; - -- return fib(x-1)+fib(x-2); - -- } - -- - - -- Create the fib function and insert it into module M. This function is said - -- to return an int and take an int parameter. - local fibtype = context:functiontype(types.int, {types.int}) - local FibF = module:newfunction("fib", fibtype) - - -- Get a new IRBuilder intance - -- this will be garbage collected by Lua - local ir = context:irbuilder() - - -- Add a basic block to the function. - local BB = context:basicblock("EntryBlock"); - FibF:appendblock(BB) - ir:setinsertpoint(BB) - - -- Get pointers to the constants. - local One = context:intconstant(1); - local Two = context:intconstant(2); - - -- Get pointer to the integer argument of the add1 function... - local ArgX = FibF:arg(1); -- Get the arg. - - -- Create the true_block. - local RetBB = context:basicblock("return"); - FibF:appendblock(RetBB) - - -- Create an exit block. - local RecurseBB = context:basicblock("recurse"); - FibF:appendblock(RecurseBB) - - -- Create the "if (arg <= 2) goto exitbb" - local CondInst = ir:icmpsle(ArgX, Two); - ir:condbr(CondInst, RetBB, RecurseBB); - - ir:setinsertpoint(RetBB) - -- Create: ret int 1 - ir:ret(One); - - -- create fib(x-1) - ir:setinsertpoint(RecurseBB) - local Sub = ir:nswsub(ArgX, One); - local CallFibX1 = ir:call(FibF, {Sub}, {tailcall=true}); - - -- create fib(x-2) - Sub = ir:nswsub(ArgX, Two); - local CallFibX2 = ir:call(FibF, {Sub}, {tailcall=true}); - - -- fib(x-1)+fib(x-2) - local Sum = ir:nswadd(CallFibX1, CallFibX2); - - -- Create the return instruction and add it to the basic block - ir:ret(Sum); - - return FibF -end - --- Get the LLVM context - right now this is the --- global context -local context = llvm.context() - --- The bindings provide a number of predefined types that --- are Lua specific plus some standard C types such as 'int', --- 'double', 'int64_t', etc. -local types = context:types() - --- 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("demofib") - --- Get hold of the module --- as we will create the fib function as an --- iternal function -local module = mainfunc:module() - --- The actual fibonacci function is an internal --- function so that it is pure native function -local fib = makefib(context, module, types) - --- Get a new IRBuilder -local ir = context:irbuilder() - --- Our main Lua function has only one block -local BB = context:basicblock("entry") -mainfunc:appendblock(BB) -ir:setinsertpoint(BB) - --- Declare prototypes -local luaL_checkinteger = mainfunc:extern("luaL_checkinteger") -local lua_pushinteger = mainfunc:extern("lua_pushinteger") - --- Get lua_State* -local L = mainfunc:arg(1) - --- We are expecting one integer parameter -local intparam = ir:call(luaL_checkinteger, {L, context:intconstant(1)}) --- cast from 64 to 32 bit -intparam = ir:truncorbitcast(intparam, types.int) - --- Call the fib calculator -local result = ir:call(fib, {intparam}) - --- Extend from 32 to 64 bit -result = ir:zext(result, types.lua_Integer) - --- Push the final integer result -ir:call(lua_pushinteger, {L, result}) - --- Return 1 -ir:ret(context:intconstant(1)) - ----- We are done! --- - --- Dump the module for info -module:dump() - --- compile the Lua callable function -local runnable = mainfunc:compile() -assert(runnable(11) == 89) -print 'Ok' \ No newline at end of file diff --git a/llvmbinding/helloworld.lua b/llvmbinding/helloworld.lua deleted file mode 100644 index 2f1cbe5..0000000 --- a/llvmbinding/helloworld.lua +++ /dev/null @@ -1,63 +0,0 @@ --- This small demo creates a compiled function --- takes a string parameter and calls puts() to --- print this - --- ensure that LLVM bindings are available -assert(llvm) - --- Get the LLVM context - right now this is the --- global context -context = llvm.context() - --- The bindings provide a number of predefined types that --- are Lua specific plus some standard C types such as 'int', --- 'double', 'int64_t', etc. -types = context:types() - --- Create a lua_CFunction instance --- At this stage the function will get a module and --- execution engine but no body -myfunc = context:lua_CFunction("myfunc") - --- Get a new IRBuilder intance --- this will be garbage collected by Lua -irbuilder = context:irbuilder() - --- Create a basic block -block = context:basicblock("entry") --- Add it to the end of the function -myfunc:appendblock(block) --- Set this as the next instruction point -irbuilder:setinsertpoint(block) - --- get declaration for luaL_checklstring -luaL_checklstring = myfunc:extern("luaL_checklstring") - --- Get the L parameter of myfunc -L = myfunc:arg(1) - --- get the first argument as a string -str = irbuilder:call(luaL_checklstring, - {L, context:intconstant(1), - context:nullconstant(types.psize_t)}) - --- declare puts -puts_type = context:functiontype(types.int, {types.pchar}) -puts = myfunc:extern("puts", puts_type); - --- Call puts -irbuilder:call(puts, {str}) - --- add CreateRet(0) -irbuilder:ret(context:intconstant(0)) --- **************************************************/ - --- what did we get? -llvm.dump(myfunc) - --- JIT compile the function --- returns a C Closure -runnable = myfunc:compile() - -assert(not runnable('hello world\n')) - diff --git a/readthedocs/index.rst b/readthedocs/index.rst index 23dd711..4bbb60f 100644 --- a/readthedocs/index.rst +++ b/readthedocs/index.rst @@ -25,7 +25,6 @@ Contents: ravi-jit-compilation-hook ravi-lua-types llvm-tbaa - llvm-bindings ravi-benchmarks ravi-jit-status diff --git a/readthedocs/llvm-bindings.rst b/readthedocs/llvm-bindings.rst deleted file mode 100644 index 375ee85..0000000 --- a/readthedocs/llvm-bindings.rst +++ /dev/null @@ -1,244 +0,0 @@ -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 `_ 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 | -+----------------------------------------------------------------------------------------------+ diff --git a/src/linit.c b/src/linit.c index ce3263a..b156c4a 100644 --- a/src/linit.c +++ b/src/linit.c @@ -52,9 +52,6 @@ static const luaL_Reg loadedlibs[] = { {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_DBLIBNAME, luaopen_debug}, {LUA_RAVILIBNAME, raviopen_llvmjit}, -//#ifdef USE_LLVM -// {LUA_LLVMLIBNAME, raviopen_llvmluaapi}, -//#endif #if USE_DMR_C { "dmrc", raviopen_dmrcluaapi }, #endif diff --git a/src/ravi_llvmluaapi.cpp b/src/ravi_llvmluaapi.cpp deleted file mode 100644 index 954ca25..0000000 --- a/src/ravi_llvmluaapi.cpp +++ /dev/null @@ -1,1618 +0,0 @@ -/****************************************************************************** -* Copyright (C) 2015-2020 Dibyendu Majumdar -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - -/* -This will hopefully eventually contain a Lua binding for LLVM. -*/ - -#if USE_DMR_C -#include -#endif -#include -#include "ravi_llvmcodegen.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "lauxlib.h" - -// Utility to extract a boolean field from a table -static bool l_table_get_bool(lua_State *L, int idx, const char *key, - bool *result, bool default_value) { - bool rc = false; - lua_pushstring(L, key); - lua_gettable(L, idx); /* get table[key] */ - if (!lua_isboolean(L, -1)) - *result = default_value; - else { - *result = lua_toboolean(L, -1) != 0; - rc = true; - } - lua_pop(L, 1); /* remove value */ - return rc; -} - -// We need fixed pointer values for metatable keys -static const char *LLVM_context = "LLVMcontext"; -static const char *LLVM_irbuilder = "LLVMirbuilder"; -static const char *LLVM_module = "LLVMmodule"; -static const char *LLVM_mainfunction = "LLVMmainfunction"; -static const char *LLVM_function = "LLVMfunction"; -static const char *LLVM_type = "LLVMtype"; -static const char *LLVM_value = "LLVMvalue"; -static const char *LLVM_structtype = "LLVMstructtype"; -static const char *LLVM_pointertype = "LLVMpointertype"; -static const char *LLVM_functiontype = "LLVMfunctiontype"; -static const char *LLVM_basicblock = "LLVMbasicblock"; -static const char *LLVM_constant = "LLVMconstant"; -static const char *LLVM_instruction = "LLVMinstruction"; -static const char *LLVM_phinode = "LLVMphinode"; - -#define test_LLVM_irbuilder(L, idx) \ - ((IRBuilderHolder *)luaL_testudata(L, idx, LLVM_irbuilder)) -#define check_LLVM_irbuilder(L, idx) \ - ((IRBuilderHolder *)luaL_checkudata(L, idx, LLVM_irbuilder)) - -#define test_LLVM_type(L, idx) \ - ((TypeHolder *)luaL_testudata(L, idx, LLVM_type)) -#define check_LLVM_type(L, idx) \ - ((TypeHolder *)luaL_checkudata(L, idx, LLVM_type)) - -#define test_LLVM_context(L, idx) \ - ((ContextHolder *)luaL_testudata(L, idx, LLVM_context)) -#define check_LLVM_context(L, idx) \ - ((ContextHolder *)luaL_checkudata(L, idx, LLVM_context)) - -#define test_LLVM_structtype(L, idx) \ - ((StructTypeHolder *)luaL_testudata(L, idx, LLVM_structtype)) -#define check_LLVM_structtype(L, idx) \ - ((StructTypeHolder *)luaL_checkudata(L, idx, LLVM_structtype)) - -#define test_LLVM_pointertype(L, idx) \ - ((PointerTypeHolder *)luaL_testudata(L, idx, LLVM_pointertype)) -#define check_LLVM_pointertype(L, idx) \ - ((PointerTypeHolder *)luaL_checkudata(L, idx, LLVM_pointertype)) - -#define test_LLVM_functiontype(L, idx) \ - ((FunctionTypeHolder *)luaL_testudata(L, idx, LLVM_functiontype)) -#define check_LLVM_functiontype(L, idx) \ - ((FunctionTypeHolder *)luaL_checkudata(L, idx, LLVM_functiontype)) - -#define test_LLVM_mainfunction(L, idx) \ - ((MainFunctionHolder *)luaL_testudata(L, idx, LLVM_mainfunction)) -#define check_LLVM_mainfunction(L, idx) \ - ((MainFunctionHolder *)luaL_checkudata(L, idx, LLVM_mainfunction)) - -#define test_LLVM_function(L, idx) \ - ((FunctionHolder *)luaL_testudata(L, idx, LLVM_function)) -#define check_LLVM_function(L, idx) \ - ((FunctionHolder *)luaL_checkudata(L, idx, LLVM_function)) - -#define test_LLVM_basicblock(L, idx) \ - ((BasicBlockHolder *)luaL_testudata(L, idx, LLVM_basicblock)) -#define check_LLVM_basicblock(L, idx) \ - ((BasicBlockHolder *)luaL_checkudata(L, idx, LLVM_basicblock)) - -#define test_LLVM_value(L, idx) \ - ((ValueHolder *)luaL_testudata(L, idx, LLVM_value)) -#define check_LLVM_value(L, idx) \ - ((ValueHolder *)luaL_checkudata(L, idx, LLVM_value)) - -#define test_LLVM_constant(L, idx) \ - ((ConstantHolder *)luaL_testudata(L, idx, LLVM_constant)) -#define check_LLVM_constant(L, idx) \ - ((ConstantHolder *)luaL_checkudata(L, idx, LLVM_constant)) - -#define test_LLVM_instruction(L, idx) \ - ((InstructionHolder *)luaL_testudata(L, idx, LLVM_instruction)) -#define check_LLVM_instruction(L, idx) \ - ((InstructionHolder *)luaL_checkudata(L, idx, LLVM_instruction)) - -#define test_LLVM_module(L, idx) \ - ((ModuleHolder *)luaL_testudata(L, idx, LLVM_module)) -#define check_LLVM_module(L, idx) \ - ((ModuleHolder *)luaL_checkudata(L, idx, LLVM_module)) - -#define test_LLVM_phinode(L, idx) \ - ((PhiNodeHolder *)luaL_testudata(L, idx, LLVM_phinode)) -#define check_LLVM_phinode(L, idx) \ - ((PhiNodeHolder *)luaL_checkudata(L, idx, LLVM_phinode)) - -struct ContextHolder { - /* Each Ravi instance (Lua instance) has its own - * LLVM context - * Lifetime of this is tied to the Lua instance so - * no need to garbage collect - */ - ravi::RaviJITState *jitState; -}; - -/* garbage collected */ -struct IRBuilderHolder { - llvm::IRBuilder<> *builder; -}; - -struct ValueHolder { - llvm::Value *value; -}; - -struct TypeHolder { - llvm::Type *type; -}; - -struct StructTypeHolder { - llvm::StructType *type; -}; - -struct PointerTypeHolder { - llvm::PointerType *type; -}; - -struct FunctionTypeHolder { - llvm::FunctionType *type; -}; - -/* garbage collected */ -struct MainFunctionHolder { - ravi::RaviJITFunction *func; - lua_CFunction compiled_func; - llvm::Value *arg1; - bool is_valid; -}; - -struct FunctionHolder { - llvm::Function *function; -}; - -struct BasicBlockHolder { - llvm::BasicBlock *b; -}; - -struct ConstantHolder { - llvm::Constant *constant; -}; - -struct InstructionHolder { - llvm::Instruction *i; -}; - -struct ModuleHolder { - std::shared_ptr M; - - ModuleHolder(const std::shared_ptr &module) { - M = module; - // printf("ModuleHolder created\n"); - } - ~ModuleHolder() { - //printf("ModuleHolder destroyed\n"); - } -}; - -struct PhiNodeHolder { - llvm::PHINode *phi; -}; - -static int context_new_LLVM_irbuilder(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - IRBuilderHolder *builder = - (IRBuilderHolder *)lua_newuserdata(L, sizeof(IRBuilderHolder)); - builder->builder = new llvm::IRBuilder<>(context->jitState->context()); - luaL_getmetatable(L, LLVM_irbuilder); - lua_setmetatable(L, -2); - return 1; -} - -/* __gc function for IRBuilderHolder */ -static int collect_LLVM_irbuilder(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - if (builder->builder) { - delete builder->builder; - builder->builder = nullptr; - } - return 0; -} - -static void alloc_LLVM_module(lua_State *L, - const std::shared_ptr &M) { - ModuleHolder *mh = (ModuleHolder *)lua_newuserdata(L, sizeof(ModuleHolder)); - luaL_getmetatable(L, LLVM_module); - lua_setmetatable(L, -2); - new (mh) ModuleHolder(M); -} - -/* __gc for ModuleHolder */ -static int collect_LLVM_module(lua_State *L) { - ModuleHolder *mh = check_LLVM_module(L, 1); - // printf("Module released: usecount %d\n", (int)mh->M.use_count()); - mh->~ModuleHolder(); - return 0; -} - -static void alloc_LLVM_type(lua_State *L, llvm::Type *t) { - TypeHolder *tt = (TypeHolder *)lua_newuserdata(L, sizeof(TypeHolder)); - luaL_getmetatable(L, LLVM_type); - lua_setmetatable(L, -2); - tt->type = t; -} - -static void alloc_LLVM_context(lua_State *L, ravi::RaviJITState *jit) { - ContextHolder *h = (ContextHolder *)lua_newuserdata(L, sizeof(ContextHolder)); - luaL_getmetatable(L, LLVM_context); - lua_setmetatable(L, -2); - h->jitState = jit; -} - -static void alloc_LLVM_value(lua_State *L, llvm::Value *v) { - ValueHolder *h = (ValueHolder *)lua_newuserdata(L, sizeof(ValueHolder)); - luaL_getmetatable(L, LLVM_value); - lua_setmetatable(L, -2); - h->value = v; -} - -static void alloc_LLVM_structtype(lua_State *L, llvm::StructType *type) { - StructTypeHolder *h = - (StructTypeHolder *)lua_newuserdata(L, sizeof(StructTypeHolder)); - luaL_getmetatable(L, LLVM_structtype); - lua_setmetatable(L, -2); - h->type = type; -} - -static void alloc_LLVM_pointertype(lua_State *L, llvm::PointerType *type) { - PointerTypeHolder *h = - (PointerTypeHolder *)lua_newuserdata(L, sizeof(PointerTypeHolder)); - luaL_getmetatable(L, LLVM_pointertype); - lua_setmetatable(L, -2); - h->type = type; -} - -static void alloc_LLVM_functiontype(lua_State *L, llvm::FunctionType *type) { - FunctionTypeHolder *h = - (FunctionTypeHolder *)lua_newuserdata(L, sizeof(FunctionTypeHolder)); - luaL_getmetatable(L, LLVM_functiontype); - lua_setmetatable(L, -2); - h->type = type; -} - -static void alloc_LLVM_function(lua_State *L, llvm::Function *f) { - FunctionHolder *h = - (FunctionHolder *)lua_newuserdata(L, sizeof(FunctionHolder)); - luaL_getmetatable(L, LLVM_function); - lua_setmetatable(L, -2); - h->function = f; -} - -static void alloc_LLVM_constant(lua_State *L, llvm::Constant *f) { - ConstantHolder *h = - (ConstantHolder *)lua_newuserdata(L, sizeof(ConstantHolder)); - luaL_getmetatable(L, LLVM_constant); - lua_setmetatable(L, -2); - h->constant = f; -} - -static void alloc_LLVM_instruction(lua_State *L, llvm::Instruction *i) { - InstructionHolder *h = - (InstructionHolder *)lua_newuserdata(L, sizeof(InstructionHolder)); - luaL_getmetatable(L, LLVM_instruction); - lua_setmetatable(L, -2); - h->i = i; -} - -static void alloc_LLVM_phinode(lua_State *L, llvm::PHINode *phi) { - PhiNodeHolder *h = (PhiNodeHolder *)lua_newuserdata(L, sizeof(PhiNodeHolder)); - luaL_getmetatable(L, LLVM_phinode); - lua_setmetatable(L, -2); - h->phi = phi; -} - -// Creates a new module to hold a Lua C Function -static MainFunctionHolder *alloc_LLVM_mainfunction(lua_State *L, - ravi::RaviJITState *jit, - llvm::FunctionType *type, - const char *name) { - MainFunctionHolder *h = - (MainFunctionHolder *)lua_newuserdata(L, sizeof(MainFunctionHolder)); - h->func = nullptr; - h->compiled_func = nullptr; - h->arg1 = nullptr; - luaL_getmetatable(L, LLVM_mainfunction); - lua_setmetatable(L, -2); - auto module = std::make_shared(G(L)->ravi_state->jit); - h->func = new ravi::RaviJITFunction(&h->compiled_func, module, type, - llvm::Function::ExternalLinkage, name); - h->is_valid = true; - return h; -} - -static bool validate_has_luaCFunction_signature(MainFunctionHolder *h, - char *errormessage, int len) { - auto f = h->func->function(); - if (!f) { - snprintf(errormessage, len, "Function was not found"); - return false; - } - auto ftype = f->getFunctionType(); - auto returnType = ftype->getReturnType(); - if (!returnType->isIntegerTy()) { - snprintf(errormessage, len, - "Invalid return type in function: expected integer"); - return false; - } - if (ftype->isVarArg()) { - // invalid - snprintf(errormessage, len, - "Invalid function: cannot be variable argument type"); - return false; - } - if (ftype->getFunctionNumParams() != 1) { - // invalid - snprintf(errormessage, len, - "Invalid function: function must accept one argument (struct lua_State *) only"); - return false; - } - auto paramType = ftype->getFunctionParamType(0); - if (!paramType->isPointerTy()) { - // invalid - snprintf(errormessage, len, - "Invalid function: argument is not a pointer to struct lua_State"); - return false; - } - auto underLying = paramType->getPointerElementType(); - if (!underLying->isStructTy()) { - // invalid - snprintf(errormessage, len, - "Invalid function: argument is not a pointer to struct lua_State"); - return false; - } - if (!underLying->getStructName().startswith("struct.lua_State")) { - // invalid - snprintf( - errormessage, len, - "Invalid function: argument is not a pointer to struct lua_State"); - return false; - } - return true; -} - -// References an existing function in a Module -static MainFunctionHolder *alloc_LLVM_luaCfunction( - lua_State *L, const std::shared_ptr &module, - const char *name) { - char error_message[128]; - MainFunctionHolder *h = - (MainFunctionHolder *)lua_newuserdata(L, sizeof(MainFunctionHolder)); - h->func = nullptr; - h->compiled_func = nullptr; - h->arg1 = nullptr; - luaL_getmetatable(L, LLVM_mainfunction); - lua_setmetatable(L, -2); - h->func = new ravi::RaviJITFunction(&h->compiled_func, module, name); - h->is_valid = validate_has_luaCFunction_signature(h, error_message, sizeof error_message); - if (!h->is_valid) { - luaL_argerror(L, 2, error_message); - } - return h; -} - -/* __gc for FunctionHolder */ -static int collect_LLVM_mainfunction(lua_State *L) { - MainFunctionHolder *builder = check_LLVM_mainfunction(L, 1); - if (builder->func) { - delete builder->func; - builder->func = nullptr; - //printf("Collected MainFunctionHolder\n"); - } - return 0; -} - -static void alloc_LLVM_basicblock(lua_State *L, llvm::BasicBlock *b) { - BasicBlockHolder *h = - (BasicBlockHolder *)lua_newuserdata(L, sizeof(BasicBlockHolder)); - luaL_getmetatable(L, LLVM_basicblock); - lua_setmetatable(L, -2); - h->b = b; -} - -/* - Create a new struct type - structtype(name) -*/ -static int context_new_struct_type(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - const char *name = luaL_checkstring(L, 2); - alloc_LLVM_structtype( - L, llvm::StructType::create(context->jitState->context(), name)); - return 1; -} - -/* - Create a pointer type - pointertype(type) -*/ -static int context_new_pointer_type(lua_State *L) { - StructTypeHolder *sth = nullptr; - PointerTypeHolder *ph = nullptr; - TypeHolder *th = nullptr; - FunctionTypeHolder *fth = nullptr; - - sth = test_LLVM_structtype(L, 2); - if (sth) { - alloc_LLVM_pointertype(L, llvm::PointerType::get(sth->type, 0)); - goto done; - } - ph = test_LLVM_pointertype(L, 2); - if (ph) { - alloc_LLVM_pointertype(L, llvm::PointerType::get(ph->type, 0)); - goto done; - } - th = test_LLVM_type(L, 2); - if (th) { - alloc_LLVM_pointertype(L, llvm::PointerType::get(th->type, 0)); - goto done; - } - fth = test_LLVM_functiontype(L, 2); - if (fth) { - alloc_LLVM_pointertype(L, llvm::PointerType::get(fth->type, 0)); - goto done; - } - luaL_argerror(L, 2, "invalid argument"); - return 0; -done: - return 1; -} - -/* - Get pre-defined types -*/ -static int context_get_types(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - auto jit = context->jitState; - - lua_newtable(L); - alloc_LLVM_type(L, jit->types()->C_intT); - lua_setfield(L, -2, "int"); - alloc_LLVM_type(L, jit->types()->lua_NumberT); - lua_setfield(L, -2, "lua_Number"); - alloc_LLVM_type(L, jit->types()->lua_IntegerT); - lua_setfield(L, -2, "lua_Integer"); - alloc_LLVM_type(L, jit->types()->lu_byteT); - lua_setfield(L, -2, "lu_byte"); - alloc_LLVM_pointertype(L, jit->types()->C_pcharT); - lua_setfield(L, -2, "pchar"); - alloc_LLVM_type(L, jit->types()->C_doubleT); - lua_setfield(L, -2, "double"); - alloc_LLVM_type(L, jit->types()->C_int64_t); - lua_setfield(L, -2, "int64_t"); - alloc_LLVM_type(L, jit->types()->C_intptr_t); - lua_setfield(L, -2, "intptr_t"); - alloc_LLVM_pointertype(L, jit->types()->C_pintT); - lua_setfield(L, -2, "pint"); - alloc_LLVM_type(L, jit->types()->C_ptrdiff_t); - lua_setfield(L, -2, "ptrdiff_t"); - alloc_LLVM_type(L, jit->types()->C_shortT); - lua_setfield(L, -2, "short"); - alloc_LLVM_type(L, jit->types()->C_size_t); - lua_setfield(L, -2, "size_t"); - alloc_LLVM_pointertype(L, jit->types()->C_psize_t); - lua_setfield(L, -2, "psize_t"); - alloc_LLVM_type(L, jit->types()->lua_UnsignedT); - lua_setfield(L, -2, "lua_Unsigned"); - alloc_LLVM_type(L, jit->types()->C_voidT); - lua_setfield(L, -2, "void"); - alloc_LLVM_functiontype(L, jit->types()->lua_CFunctionT); - lua_setfield(L, -2, "lua_CFunction"); - - return 1; -} - -static int get_llvm_context(lua_State *L) { - auto jit = RaviJIT(L); - alloc_LLVM_context(L, jit); - return 1; -} - -static llvm::Value *get_value(lua_State *L, int idx) { - InstructionHolder *ii = test_LLVM_instruction(L, idx); - if (ii) { return ii->i; } - ValueHolder *v = test_LLVM_value(L, idx); - if (v) { return v->value; } - ConstantHolder *c = test_LLVM_constant(L, idx); - if (c) { return c->constant; } - MainFunctionHolder *m = test_LLVM_mainfunction(L, idx); - if (m) { return m->func->function(); } - FunctionHolder *f = test_LLVM_function(L, idx); - if (f) { return f->function; } - PhiNodeHolder *phi = test_LLVM_phinode(L, idx); - if (phi) { return phi->phi; } - luaL_argerror(L, idx, "Value expected"); - return nullptr; -} - -/* - Dump an LLVM object -*/ -static int dump_content(lua_State *L) { -#if LLVM_VERSION_MAJOR < 5 - TypeHolder *th = nullptr; - StructTypeHolder *sth = nullptr; - PointerTypeHolder *ph = nullptr; - FunctionTypeHolder *fh = nullptr; - MainFunctionHolder *f = nullptr; - InstructionHolder *ii = nullptr; - ModuleHolder *m = nullptr; - PhiNodeHolder *phi = nullptr; - - th = test_LLVM_type(L, 1); - if (th) { - th->type->dump(); - return 0; - } - sth = test_LLVM_structtype(L, 1); - if (sth) { - sth->type->dump(); - return 0; - } - ph = test_LLVM_pointertype(L, 1); - if (ph) { - ph->type->dump(); - return 0; - } - fh = test_LLVM_functiontype(L, 1); - if (fh) { - fh->type->dump(); - return 0; - } - f = test_LLVM_mainfunction(L, 1); - if (f) { - f->func->dump(); - return 0; - } - ii = test_LLVM_instruction(L, 1); - if (ii) { - ii->i->dump(); - return 0; - } - m = test_LLVM_module(L, 1); - if (m) { - m->M->dump(); - return 0; - } - phi = test_LLVM_phinode(L, 1); - if (phi) { - phi->phi->dump(); - return 0; - } -#endif - return 0; -} - -/* - Add members to a struct - addmembers(struct, { members }) -*/ -static int struct_add_members(lua_State *L) { - StructTypeHolder *sh = check_LLVM_structtype(L, 1); - luaL_argcheck(L, lua_istable(L, 2), 2, "table expected"); - int len = luaL_len(L, 2); - std::vector elements; - for (int i = 1; i <= len; i++) { - lua_rawgeti(L, 2, i); - TypeHolder *th = nullptr; - StructTypeHolder *sth = nullptr; - PointerTypeHolder *ph = test_LLVM_pointertype(L, -1); - if (ph) { - elements.push_back(ph->type); - goto done; - } - th = test_LLVM_type(L, -1); - if (th) { - elements.push_back(th->type); - goto done; - } - sth = test_LLVM_structtype(L, -1); - if (sth) { - elements.push_back(sth->type); - goto done; - } - done: - lua_pop(L, 1); - } - sh->type->setBody(elements); - lua_pushinteger(L, elements.size()); - return 1; -} - -static llvm::Type *return_type(lua_State *L, int idx) { - TypeHolder *th = test_LLVM_type(L, idx); - if (th) { return th->type; } - PointerTypeHolder *ph = test_LLVM_pointertype(L, idx); - if (ph) { return ph->type; } - luaL_argerror(L, idx, "unsupported function return type"); - return nullptr; -} - -static llvm::Type *arg_type(lua_State *L, int idx) { - TypeHolder *th = test_LLVM_type(L, idx); - if (th) { return th->type; } - PointerTypeHolder *ph = test_LLVM_pointertype(L, idx); - if (ph) { return ph->type; } - luaL_argerror(L, idx, "unsupported function argument type"); - return nullptr; -} - -/* - functiontype(context, rettype, { argtypes } [, { vararg=true }) -*/ -static int context_new_function_type(lua_State *L) { - llvm::Type *typeret = return_type(L, 2); - luaL_argcheck(L, lua_istable(L, 3), 3, "table expected"); - int len = luaL_len(L, 3); - std::vector elements; - for (int i = 1; i <= len; i++) { - lua_rawgeti(L, 3, i); - llvm::Type *t = arg_type(L, -1); - if (t) elements.push_back(t); - lua_pop(L, 1); - } - bool vararg = false; - if (lua_istable(L, 4)) l_table_get_bool(L, 4, "vararg", &vararg, false); - alloc_LLVM_functiontype(L, - llvm::FunctionType::get(typeret, elements, vararg)); - return 1; -} - -llvm::Function *get_function(lua_State *L, int idx) { - llvm::Function *func = nullptr; - MainFunctionHolder *f = test_LLVM_mainfunction(L, idx); - if (f) - func = f->func->function(); - else { - FunctionHolder *f = check_LLVM_function(L, idx); - func = f->function; - } - return func; -} - -static int context_new_lua_CFunction(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - const char *name = luaL_checkstring(L, 2); - MainFunctionHolder *h = alloc_LLVM_mainfunction( - L, context->jitState, context->jitState->types()->lua_CFunctionT, name); - /* set L arg */ - h->arg1 = &(*h->func->function()->arg_begin()); - h->arg1->setName("L"); - return 1; -} - -static int context_new_module(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - alloc_LLVM_module(L, - std::make_shared(context->jitState)); - return 1; -} - -static int func_getmodule(lua_State *L) { - MainFunctionHolder *f = check_LLVM_mainfunction(L, 1); - alloc_LLVM_module(L, f->func->raviModule()); - return 1; -} - -static int module_newfunction(lua_State *L) { - ModuleHolder *mh = check_LLVM_module(L, 1); - const char *name = luaL_checkstring(L, 2); - FunctionTypeHolder *fth = check_LLVM_functiontype(L, 3); - bool extern_linkage = false; - if (lua_istable(L, 4)) - l_table_get_bool(L, 4, "extern", &extern_linkage, false); - llvm::Function *f = - llvm::Function::Create(fth->type, - extern_linkage ? llvm::Function::ExternalLinkage - : llvm::Function::InternalLinkage, - name, mh->M->module()); - alloc_LLVM_function(L, f); - return 1; -} - -static int module_getfunction(lua_State *L) { - ModuleHolder *mh = check_LLVM_module(L, 1); - const char *name = luaL_checkstring(L, 2); - alloc_LLVM_luaCfunction(L, mh->M, name); - // TODO we should check that the function signature is correct - return 1; -} - -enum { - MAX_ARGS = 50, - MAX_BUFFER = 4096 -}; - -static int collect_args(lua_State *L, int tabindex, char *argv[], int maxargs, - char *buf, int buflen) { - char errormessage[128]; - int len = lua_rawlen(L, tabindex); - if (len > maxargs) { - snprintf(errormessage, sizeof errormessage, - "Arguments exceed total count %d elements", maxargs); - luaL_argerror(L, 2, errormessage); - len = maxargs; - } - char *p = buf; - char *endp = buf + buflen; - int n = 0; - for (int i = 0; i < len; i++) { - lua_rawgeti(L, tabindex, i + 1); - size_t size = 0; - const char *argument = luaL_checklstring(L, -1, &size); - if (argument && size > 0) { - if (p + size + 1 >= endp) { - snprintf(errormessage, sizeof errormessage, - "Arguments exceed combined size of %d bytes", buflen); - luaL_argerror(L, 2, errormessage); - break; - } - strncpy(p, argument, size + 1); - argv[n] = p; - p += (size + 1); - n++; - } - } - assert(p <= endp); - return n; -} - -static int module_compile_C(lua_State *L) { - ModuleHolder *mh = check_LLVM_module(L, 1); - const char *codebuffer = NULL; // luaL_checkstring(L, 2); - char *argv[MAX_ARGS + 1] = {NULL}; - int argc = 0; - char buf[MAX_BUFFER + 1] = {0}; - int guard = 0xfefefefe; - - if (lua_istable(L, 2)) { - argc = collect_args(L, 2, argv, MAX_ARGS, buf, sizeof buf); - assert(argc >= 0 && argc <= MAX_ARGS); - assert(argv[MAX_ARGS] == NULL); - assert(guard == 0xfefefefe); - if (lua_isstring(L, 3)) { codebuffer = lua_tostring(L, 3); } - } - else if (lua_isstring(L, 2)) { - codebuffer = lua_tostring(L, 2); - } - -#if USE_DMR_C - if (dmrC_llvmcompile(argc, argv, llvm::wrap(mh->M->module()), codebuffer)) { - lua_pushboolean(L, true); - } - else { - lua_pushboolean(L, false); - } -#else - (void)mh; - (void)codebuffer; - lua_pushboolean(L, false); -#endif - return 1; -} - -static int module_generate_code(lua_State *L) { - ModuleHolder *mh = check_LLVM_module(L, 1); - mh->M->runpasses(); - mh->M->finalize(); - return 0; -} - -static int context_new_basicblock(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - const char *name = luaL_checkstring(L, 2); - alloc_LLVM_basicblock( - L, llvm::BasicBlock::Create(context->jitState->context(), name)); - return 1; -} - -static int func_append_basicblock(lua_State *L) { - llvm::Function *func = get_function(L, 1); - BasicBlockHolder *b = check_LLVM_basicblock(L, 2); - func->getBasicBlockList().push_back(b->b); - return 0; -} - -static int irbuilder_set_current_block(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - BasicBlockHolder *b = check_LLVM_basicblock(L, 2); - builder->builder->SetInsertPoint(b->b); - return 0; -} - -static int context_intconstant(lua_State *L) { - ContextHolder *context = check_LLVM_context(L, 1); - auto jit = context->jitState; - int i = (int)luaL_checkinteger(L, 2); - alloc_LLVM_value(L, llvm::ConstantInt::get(jit->types()->C_intT, i)); - return 1; -} - -static int irbuilder_retval(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Value *v = get_value(L, 2); - llvm::Instruction *i; - if (v) - i = builder->builder->CreateRet(v); - else - i = builder->builder->CreateRetVoid(); - alloc_LLVM_instruction(L, i); - return 1; -} - -static int irbuilder_branch(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - BasicBlockHolder *b = check_LLVM_basicblock(L, 2); - llvm::Instruction *i = builder->builder->CreateBr(b->b); - alloc_LLVM_instruction(L, i); - return 1; -} - -static int irbuilder_condbranch(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Value *cond = get_value(L, 2); - BasicBlockHolder *true_br = check_LLVM_basicblock(L, 3); - BasicBlockHolder *false_br = check_LLVM_basicblock(L, 4); - llvm::Instruction *i = - builder->builder->CreateCondBr(cond, true_br->b, false_br->b); - alloc_LLVM_instruction(L, i); - return 1; -} - -static int func_compile(lua_State *L) { - MainFunctionHolder *f = check_LLVM_mainfunction(L, 1); - if (!f->is_valid) return 0; - if (!f->func->function()) return 0; - if (!f->compiled_func) { - f->func->raviModule()->runpasses(); - f->func->raviModule()->finalize(); - } - if (!f->compiled_func) return 0; - lua_pushvalue(L, 1); - lua_pushcclosure(L, f->compiled_func, 1); - return 1; -} - -typedef int (*decl_func)(lua_State *L, ravi::RaviJITState *jit, - ravi::RaviJITFunction *f); -typedef struct { - const char *name; - decl_func f; -} FunctionDeclaration; - -#define str(s) #s - -#define decl_func1_(name, ret, arg1, vararg) \ - static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \ - ravi::RaviJITFunction *f) { \ - llvm::Type *args[] = { \ - jit->types()->arg1, \ - }; \ - llvm::FunctionType *type = \ - llvm::FunctionType::get(jit->types()->ret, args, vararg); \ - llvm::Function *extfunc = f->addExternFunction( \ - type, reinterpret_cast(&name), str(name)); \ - alloc_LLVM_constant(L, extfunc); \ - return 1; \ - } - -#define decl_func1v(name, ret, arg1) decl_func1_(name, ret, arg1, true) -#define decl_func1(name, ret, arg1) decl_func1_(name, ret, arg1, false) - -#define decl_func2_(name, ret, arg1, arg2, vararg) \ - static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \ - ravi::RaviJITFunction *f) { \ - llvm::Type *args[] = { \ - jit->types()->arg1, jit->types()->arg2, \ - }; \ - llvm::FunctionType *type = \ - llvm::FunctionType::get(jit->types()->ret, args, vararg); \ - llvm::Function *extfunc = f->addExternFunction( \ - type, reinterpret_cast(&name), str(name)); \ - alloc_LLVM_constant(L, extfunc); \ - return 1; \ - } - -#define decl_func2v(name, ret, arg1, arg2) \ - decl_func2_(name, ret, arg1, arg2, true) -#define decl_func2(name, ret, arg1, arg2) \ - decl_func2_(name, ret, arg1, arg2, false) - -#define decl_func3(name, ret, arg1, arg2, arg3) \ - static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \ - ravi::RaviJITFunction *f) { \ - llvm::Type *args[] = { \ - jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \ - }; \ - llvm::FunctionType *type = \ - llvm::FunctionType::get(jit->types()->ret, args, false); \ - llvm::Function *extfunc = f->addExternFunction( \ - type, reinterpret_cast(&name), str(name)); \ - alloc_LLVM_constant(L, extfunc); \ - return 1; \ - } - -#define decl_func4(name, ret, arg1, arg2, arg3, arg4) \ - static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \ - ravi::RaviJITFunction *f) { \ - llvm::Type *args[] = { \ - jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \ - jit->types()->arg4, \ - }; \ - llvm::FunctionType *type = \ - llvm::FunctionType::get(jit->types()->ret, args, false); \ - llvm::Function *extfunc = f->addExternFunction( \ - type, reinterpret_cast(&name), str(name)); \ - alloc_LLVM_constant(L, extfunc); \ - return 1; \ - } - -#define decl_voidfunc1(name, arg1) decl_func1(name, C_voidT, arg1) -#define decl_voidfunc2(name, arg1, arg2) decl_func2(name, C_voidT, arg1, arg2) -#define decl_voidfunc3(name, arg1, arg2, arg3) \ - decl_func3(name, C_voidT, arg1, arg2, arg3) - -decl_func1v(printf, C_intT, C_pcharT); -decl_func2(lua_absindex, C_intT, plua_StateT, C_intT); -decl_func1(lua_gettop, C_intT, plua_StateT); -decl_voidfunc2(lua_settop, plua_StateT, C_intT); -decl_voidfunc2(lua_pushvalue, plua_StateT, C_intT); -decl_voidfunc3(lua_rotate, plua_StateT, C_intT, C_intT); -decl_voidfunc3(lua_copy, plua_StateT, C_intT, C_intT); -decl_func2(lua_checkstack, C_intT, plua_StateT, C_intT); -decl_voidfunc3(lua_xmove, plua_StateT, plua_StateT, C_intT); -decl_func2(lua_isnumber, C_intT, plua_StateT, C_intT); -decl_func2(lua_isstring, C_intT, plua_StateT, C_intT); -decl_func2(lua_iscfunction, C_intT, plua_StateT, C_intT); -decl_func2(lua_isinteger, C_intT, plua_StateT, C_intT); -decl_func2(lua_isuserdata, C_intT, plua_StateT, C_intT); -decl_func2(lua_type, C_intT, plua_StateT, C_intT); -decl_func2(lua_typename, C_pcharT, plua_StateT, C_intT); -decl_func3(lua_tonumberx, plua_NumberT, plua_StateT, C_intT, C_pintT); -decl_func3(lua_tointegerx, plua_IntegerT, plua_StateT, C_intT, C_pintT); -decl_func2(lua_toboolean, C_intT, plua_StateT, C_intT); -decl_func3(lua_tolstring, C_pcharT, plua_StateT, C_intT, C_psize_t); -decl_func2(lua_rawlen, C_size_t, plua_StateT, C_intT); -decl_func2(lua_tocfunction, plua_CFunctionT, plua_StateT, C_intT); -decl_func2(lua_touserdata, C_pcharT, plua_StateT, C_intT); -decl_func2(lua_tothread, plua_StateT, plua_StateT, C_intT); -decl_func2(lua_topointer, C_pcharT, plua_StateT, C_intT); -decl_voidfunc2(lua_arith, plua_StateT, C_intT); -decl_func3(lua_rawequal, C_intT, plua_StateT, C_intT, C_intT); -decl_func4(lua_compare, C_intT, plua_StateT, C_intT, C_intT, C_intT); -decl_voidfunc1(lua_pushnil, plua_StateT); -decl_voidfunc2(lua_pushnumber, plua_StateT, lua_NumberT); -decl_voidfunc2(lua_pushinteger, plua_StateT, lua_IntegerT); -decl_func3(lua_pushlstring, C_pcharT, plua_StateT, C_pcharT, C_size_t); -decl_func2(lua_pushstring, C_pcharT, plua_StateT, C_pcharT); -decl_func3(lua_pushvfstring, C_pcharT, plua_StateT, C_pcharT, C_pcharT); -decl_func2v(lua_pushfstring, C_pcharT, plua_StateT, C_pcharT); -decl_voidfunc3(lua_pushcclosure, plua_StateT, plua_CFunctionT, C_intT); -decl_voidfunc2(lua_pushboolean, plua_StateT, C_intT); -decl_voidfunc2(lua_pushlightuserdata, plua_StateT, C_pcharT); -decl_func1(lua_pushthread, C_intT, plua_StateT); -decl_func2(lua_getglobal, C_intT, plua_StateT, C_pcharT); -decl_func2(lua_gettable, C_intT, plua_StateT, C_intT); -decl_func3(lua_getfield, C_intT, plua_StateT, C_intT, C_pcharT); -decl_func3(lua_geti, C_intT, plua_StateT, C_intT, lua_IntegerT); -decl_func2(lua_rawget, C_intT, plua_StateT, C_intT); -decl_func3(lua_rawgeti, C_intT, plua_StateT, C_intT, lua_IntegerT); -decl_func3(lua_rawgetp, C_intT, plua_StateT, C_intT, C_pcharT); -decl_func3(lua_createtable, C_intT, plua_StateT, C_intT, C_intT); -decl_func2(lua_newuserdata, C_pcharT, plua_StateT, C_size_t); -decl_func2(lua_getmetatable, C_intT, plua_StateT, C_intT); -decl_func2(lua_getuservalue, C_intT, plua_StateT, C_intT); -decl_voidfunc2(lua_setglobal, plua_StateT, C_pcharT); -decl_voidfunc2(lua_settable, plua_StateT, C_intT); -decl_voidfunc3(lua_setfield, plua_StateT, C_intT, C_pcharT); -decl_voidfunc3(lua_seti, plua_StateT, C_intT, lua_IntegerT); -decl_voidfunc2(lua_rawset, plua_StateT, C_intT); -decl_voidfunc3(lua_rawseti, plua_StateT, C_intT, lua_IntegerT); -decl_voidfunc3(lua_rawsetp, plua_StateT, C_intT, C_pcharT); -decl_func2(lua_setmetatable, C_intT, plua_StateT, C_intT); -decl_voidfunc2(lua_setuservalue, plua_StateT, C_intT); -decl_func3(lua_gc, C_intT, plua_StateT, C_intT, C_intT); -decl_func1(lua_error, C_intT, plua_StateT); -decl_func2(lua_next, C_intT, plua_StateT, C_intT); -decl_voidfunc2(lua_concat, plua_StateT, C_intT); -decl_voidfunc2(lua_len, plua_StateT, C_intT); -decl_func2(lua_stringtonumber, C_size_t, plua_StateT, C_pcharT); - -decl_func3(luaL_checklstring, C_pcharT, plua_StateT, C_intT, C_psize_t); -decl_func2(luaL_checkinteger, lua_IntegerT, plua_StateT, C_intT); - -/* Sorted array of declared functions */ -static FunctionDeclaration builtin_functions[] = { - {"lua_absindex", lua_absindex_decl}, - {"lua_gettop", lua_gettop_decl}, - {"lua_settop", lua_settop_decl}, - {"lua_pushvalue", lua_pushvalue_decl}, - {"lua_rotate", lua_rotate_decl}, - {"lua_copy", lua_copy_decl}, - {"lua_checkstack", lua_checkstack_decl}, - {"lua_xmove", lua_xmove_decl}, - {"lua_isnumber", lua_isnumber_decl}, - {"lua_isstring", lua_isstring_decl}, - {"lua_iscfunction", lua_iscfunction_decl}, - {"lua_isinteger", lua_isinteger_decl}, - {"lua_isuserdata", lua_isuserdata_decl}, - {"lua_type", lua_type_decl}, - {"lua_typename", lua_typename_decl}, - {"lua_tonumberx", lua_tonumberx_decl}, - {"lua_tointegerx", lua_tointegerx_decl}, - {"lua_toboolean", lua_toboolean_decl}, - {"lua_tolstring", lua_tolstring_decl}, - {"lua_rawlen", lua_rawlen_decl}, - {"lua_tocfunction", lua_tocfunction_decl}, - {"lua_touserdata", lua_touserdata_decl}, - {"lua_tothread", lua_tothread_decl}, - {"lua_topointer", lua_topointer_decl}, - {"lua_arith", lua_arith_decl}, - {"lua_rawequal", lua_rawequal_decl}, - {"lua_compare", lua_compare_decl}, - {"lua_pushnil", lua_pushnil_decl}, - {"lua_pushnumber", lua_pushnumber_decl}, - {"lua_pushinteger", lua_pushinteger_decl}, - {"lua_pushlstring", lua_pushlstring_decl}, - {"lua_pushstring", lua_pushstring_decl}, - {"lua_pushvfstring", lua_pushvfstring_decl}, - {"lua_pushfstring", lua_pushfstring_decl}, - {"lua_pushcclosure", lua_pushcclosure_decl}, - {"lua_pushboolean", lua_pushboolean_decl}, - {"lua_pushlightuserdata", lua_pushlightuserdata_decl}, - {"lua_pushthread", lua_pushthread_decl}, - {"lua_getglobal", lua_getglobal_decl}, - {"lua_gettable", lua_gettable_decl}, - {"lua_getfield", lua_getfield_decl}, - {"lua_geti", lua_geti_decl}, - {"lua_rawget", lua_rawget_decl}, - {"lua_rawgeti", lua_rawgeti_decl}, - {"lua_rawgetp", lua_rawgetp_decl}, - {"lua_createtable", lua_createtable_decl}, - {"lua_newuserdata", lua_newuserdata_decl}, - {"lua_getmetatable", lua_getmetatable_decl}, - {"lua_getuservalue", lua_getuservalue_decl}, - {"lua_setglobal", lua_setglobal_decl}, - {"lua_settable", lua_settable_decl}, - {"lua_setfield", lua_setfield_decl}, - {"lua_seti", lua_seti_decl}, - {"lua_rawset", lua_rawset_decl}, - {"lua_rawseti", lua_rawseti_decl}, - {"lua_rawsetp", lua_rawsetp_decl}, - {"lua_setmetatable", lua_setmetatable_decl}, - {"lua_setuservalue", lua_setuservalue_decl}, - {"lua_gc", lua_gc_decl}, - {"lua_error", lua_error_decl}, - {"lua_next", lua_next_decl}, - {"lua_concat", lua_concat_decl}, - {"lua_len", lua_len_decl}, - {"lua_stringtonumber", lua_stringtonumber_decl}, - - {"luaL_checklstring", luaL_checklstring_decl}, - {"luaL_checkinteger", luaL_checkinteger_decl}, - {"printf", printf_decl}, - {nullptr, nullptr}}; - -/* - extern(function, name[, type]) - If type is not supplied then name must be one of the predefined - functions -*/ -static int func_addextern(lua_State *L) { - auto jit = RaviJIT(L); - MainFunctionHolder *f = check_LLVM_mainfunction(L, 1); - const char *name = luaL_checkstring(L, 2); - luaL_argcheck(L, f->compiled_func == nullptr, 1, "function already compiled"); - FunctionTypeHolder *tt = test_LLVM_functiontype(L, 3); - if (tt) { - llvm::Constant *c = f->func->module()->getOrInsertFunction(name, tt->type); - alloc_LLVM_constant(L, c); - return 1; - } - else { - /* TODO binary search */ - for (int i = 0; builtin_functions[i].name != nullptr; i++) { - if (strcmp(name, builtin_functions[i].name) == 0) { - return builtin_functions[i].f(L, jit, f->func); - } - } - } - return 0; -} - -static int irbuilder_stringconstant(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - const char *string = luaL_checkstring(L, 2); - alloc_LLVM_value(L, builder->builder->CreateGlobalStringPtr(string)); - return 1; -} - -static int context_nullconstant(lua_State *L) { - PointerTypeHolder *th = check_LLVM_pointertype(L, 2); - alloc_LLVM_value(L, llvm::ConstantPointerNull::get(th->type)); - return 1; -} - -/* - Get argument of the function -*/ -static int func_getarg(lua_State *L) { - llvm::Function *func = get_function(L, 1); - int argn = luaL_checkinteger(L, 2); - int results = 1; - if (argn <= func->arg_size()) { - auto B = func->arg_begin(); - auto E = func->arg_end(); - for (int i = 1; B != E; B++, i++) { - if (i == argn) { - alloc_LLVM_value(L, &(*B)); - break; - } - } - } - else { - results = 0; - } - return results; -} - -static int irbuilder_call(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Value *func = nullptr; - ConstantHolder *c = test_LLVM_constant(L, 2); - if (c) - func = c->constant; - else { - func = get_function(L, 2); - } - luaL_argcheck(L, lua_istable(L, 3), 3, "table expected"); - int len = luaL_len(L, 3); - std::vector elements; - for (int i = 1; i <= len; i++) { - lua_rawgeti(L, 3, i); - llvm::Value *v = get_value(L, -1); - elements.push_back(v); - lua_pop(L, 1); - } - bool tailcall = false; - if (lua_istable(L, 4)) l_table_get_bool(L, 4, "tailcall", &tailcall, false); - llvm::CallInst *inst = builder->builder->CreateCall(func, elements); - if (tailcall) inst->setTailCall(); - alloc_LLVM_instruction(L, inst); - return 1; -} - -static llvm::Type *get_type(lua_State *L, int idx) { - TypeHolder *th = test_LLVM_type(L, idx); - if (th) return th->type; - PointerTypeHolder *ph = test_LLVM_pointertype(L, idx); - if (ph) return ph->type; - StructTypeHolder *sh = test_LLVM_structtype(L, idx); - if (sh) return sh->type; - FunctionTypeHolder *fh = test_LLVM_functiontype(L, idx); - if (fh) return fh->type; - luaL_argerror(L, idx, "unrecognized type"); - return nullptr; -} - -static int func_alloca(lua_State *L) { - llvm::Function *func = get_function(L, 1); - llvm::Type *ty = get_type(L, 2); - llvm::Value *arraysize = nullptr; - const char *name = nullptr; - if (lua_gettop(L) >= 3) name = luaL_checkstring(L, 3); - if (lua_gettop(L) >= 4) arraysize = get_value(L, 4); - llvm::BasicBlock *block = &(*func->getBasicBlockList().begin()); - luaL_argcheck(L, block != nullptr, 1, "No basic block in function"); - llvm::IRBuilder<> builder(block, block->begin()); - llvm::Instruction *inst = builder.CreateAlloca(ty, arraysize, name); - alloc_LLVM_instruction(L, inst); - return 1; -} - -static int irbuilder_load(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Value *ptr = get_value(L, 2); - llvm::Instruction *inst = builder->builder->CreateLoad(ptr); - alloc_LLVM_instruction(L, inst); - return 1; -} - -static int irbuilder_store(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Value *value = get_value(L, 2); - llvm::Value *ptr = get_value(L, 3); - llvm::Instruction *inst = builder->builder->CreateStore(value, ptr); - alloc_LLVM_instruction(L, inst); - return 1; -} - -static int irbuilder_phi(lua_State *L) { - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); - llvm::Type *ty = get_type(L, 2); - unsigned int num_values = (unsigned int)luaL_checkinteger(L, 3); - const char *name = nullptr; - if (lua_gettop(L) >= 4) { name = luaL_checkstring(L, 4); } - llvm::PHINode *phi = builder->builder->CreatePHI(ty, num_values, name); - alloc_LLVM_phinode(L, phi); - return 1; -} - -static int phi_addincoming(lua_State *L) { - PhiNodeHolder *phi = check_LLVM_phinode(L, 1); - llvm::Value *value = get_value(L, 2); - BasicBlockHolder *block = check_LLVM_basicblock(L, 3); - phi->phi->addIncoming(value, block->b); - lua_pushinteger(L, phi->phi->getNumOperands()); - return 1; -} - -/* ops that take a value and value array as arguments */ -#define irbuilder_vva(op) \ - static int irbuilder_##op(lua_State *L) { \ - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \ - llvm::Value *c = get_value(L, 2); \ - luaL_argcheck(L, lua_istable(L, 3), 3, "table expected"); \ - int len = luaL_len(L, 3); \ - std::vector elements; \ - for (int i = 1; i <= len; i++) { \ - lua_rawgeti(L, 3, i); \ - llvm::Value *v = get_value(L, -1); \ - elements.push_back(v); \ - lua_pop(L, 1); \ - } \ - llvm::Value *result = builder->builder->Create##op(c, elements); \ - alloc_LLVM_value(L, result); \ - return 1; \ - } - -#define irbuilder_binop(op) \ - static int irbuilder_##op(lua_State *L) { \ - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \ - llvm::Value *lhs = get_value(L, 2); \ - llvm::Value *rhs = get_value(L, 3); \ - llvm::Value *result = builder->builder->Create##op(lhs, rhs); \ - alloc_LLVM_value(L, result); \ - return 1; \ - } - -#define irbuilder_unop(op) \ - static int irbuilder_##op(lua_State *L) { \ - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \ - llvm::Value *lhs = get_value(L, 2); \ - llvm::Value *result = builder->builder->Create##op(lhs); \ - alloc_LLVM_value(L, result); \ - return 1; \ - } - -#define irbuilder_convert(op) \ - static int irbuilder_##op(lua_State *L) { \ - IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \ - llvm::Value *lhs = get_value(L, 2); \ - llvm::Type *rhs = get_type(L, 3); \ - llvm::Value *result = builder->builder->Create##op(lhs, rhs); \ - alloc_LLVM_value(L, result); \ - return 1; \ - } - -irbuilder_vva(InBoundsGEP); -irbuilder_vva(GEP); - -irbuilder_binop(ICmpEQ); -irbuilder_binop(ICmpNE); -irbuilder_binop(ICmpUGT); -irbuilder_binop(ICmpUGE); -irbuilder_binop(ICmpULT); -irbuilder_binop(ICmpULE); -irbuilder_binop(ICmpSGT); -irbuilder_binop(ICmpSGE); -irbuilder_binop(ICmpSLT); -irbuilder_binop(ICmpSLE); -irbuilder_binop(FCmpOEQ); -irbuilder_binop(FCmpOGT); -irbuilder_binop(FCmpOGE); -irbuilder_binop(FCmpOLT); -irbuilder_binop(FCmpOLE); -irbuilder_binop(FCmpONE); -irbuilder_binop(FCmpORD); -irbuilder_binop(FCmpUNO); -irbuilder_binop(FCmpUEQ); -irbuilder_binop(FCmpUGT); -irbuilder_binop(FCmpUGE); -irbuilder_binop(FCmpULT); -irbuilder_binop(FCmpULE); -irbuilder_binop(FCmpUNE); - -irbuilder_binop(NSWAdd); -irbuilder_binop(NUWAdd); -irbuilder_binop(NSWSub); -irbuilder_binop(NUWSub); -irbuilder_binop(UDiv); -irbuilder_binop(ExactUDiv); -irbuilder_binop(SDiv); -irbuilder_binop(ExactSDiv); -irbuilder_binop(URem); -irbuilder_binop(SRem); - -irbuilder_binop(And); -irbuilder_binop(Or); -irbuilder_binop(Xor); - -irbuilder_binop(FAdd); -irbuilder_binop(FSub); -irbuilder_binop(FMul); -irbuilder_binop(FDiv); -irbuilder_binop(FRem); - -irbuilder_unop(Not); -irbuilder_unop(Neg); -irbuilder_unop(FNeg); - -irbuilder_convert(Trunc); -irbuilder_convert(ZExt); -irbuilder_convert(SExt); -irbuilder_convert(ZExtOrTrunc); -irbuilder_convert(SExtOrTrunc); -irbuilder_convert(FPToUI); -irbuilder_convert(FPToSI); -irbuilder_convert(UIToFP); -irbuilder_convert(SIToFP); -irbuilder_convert(FPTrunc); -irbuilder_convert(FPExt); -irbuilder_convert(PtrToInt); -irbuilder_convert(IntToPtr); -irbuilder_convert(BitCast); -irbuilder_convert(SExtOrBitCast); -irbuilder_convert(ZExtOrBitCast); -irbuilder_convert(TruncOrBitCast); -irbuilder_convert(PointerCast); -irbuilder_convert(FPCast); - -static const luaL_Reg llvmlib[] = { - {"context", get_llvm_context}, {"dump", dump_content}, {NULL, NULL}}; - -static const luaL_Reg structtype_methods[] = {{"setbody", struct_add_members}, - {NULL, NULL}}; - -static const luaL_Reg module_methods[] = { - {"newfunction", module_newfunction}, {"getfunction", module_getfunction}, - {"compileC", module_compile_C}, {"dump", dump_content}, - {"generatecode", module_generate_code}, {NULL, NULL}}; - -static const luaL_Reg main_function_methods[] = { - {"appendblock", func_append_basicblock}, - {"compile", func_compile}, - {"extern", func_addextern}, - {"arg", func_getarg}, - {"module", func_getmodule}, - {"alloca", func_alloca}, - {NULL, NULL}}; - -static const luaL_Reg function_methods[] = { - {"appendblock", func_append_basicblock}, - {"arg", func_getarg}, - {"alloca", func_alloca}, - {NULL, NULL}}; - -static const luaL_Reg context_methods[] = { - {"irbuilder", context_new_LLVM_irbuilder}, - {"types", context_get_types}, - {"structtype", context_new_struct_type}, - {"pointertype", context_new_pointer_type}, - {"functiontype", context_new_function_type}, - {"lua_CFunction", context_new_lua_CFunction}, - {"basicblock", context_new_basicblock}, - {"intconstant", context_intconstant}, - {"nullconstant", context_nullconstant}, - {"newmodule", context_new_module}, - {NULL, NULL}}; - -static const luaL_Reg phi_methods[] = {{"addincoming", phi_addincoming}, - {NULL, NULL}}; - -static const luaL_Reg irbuilder_methods[] = { - {"setinsertpoint", irbuilder_set_current_block}, - {"ret", irbuilder_retval}, - {"stringconstant", irbuilder_stringconstant}, - {"call", irbuilder_call}, - {"br", irbuilder_branch}, - {"condbr", irbuilder_condbranch}, - {"icmpeq", irbuilder_ICmpEQ}, - {"icmpne", irbuilder_ICmpNE}, - {"icmpugt", irbuilder_ICmpUGT}, - {"icmpuge", irbuilder_ICmpUGE}, - {"icmpult", irbuilder_ICmpULT}, - {"icmpule", irbuilder_ICmpULE}, - {"icmpsgt", irbuilder_ICmpSGT}, - {"icmpsge", irbuilder_ICmpSGE}, - {"icmpslt", irbuilder_ICmpSLT}, - {"icmpsle", irbuilder_ICmpSLE}, - {"fcmpoeq", irbuilder_FCmpOEQ}, - {"fcmpogt", irbuilder_FCmpOGT}, - {"fcmpoge", irbuilder_FCmpOGE}, - {"fcmpolt", irbuilder_FCmpOLT}, - {"fcmpole", irbuilder_FCmpOLE}, - {"fcmpone", irbuilder_FCmpONE}, - {"fcmpord", irbuilder_FCmpORD}, - {"fcmpuno", irbuilder_FCmpUNO}, - {"fcmpueq", irbuilder_FCmpUEQ}, - {"fcmpugt", irbuilder_FCmpUGT}, - {"fcmpuge", irbuilder_FCmpUGE}, - {"fcmpult", irbuilder_FCmpULT}, - {"fcmpule", irbuilder_FCmpULE}, - {"fcmpune", irbuilder_FCmpUNE}, - {"nswadd", irbuilder_NSWAdd}, - {"nuwadd", irbuilder_NUWAdd}, - {"nswsub", irbuilder_NSWSub}, - {"nuwsub", irbuilder_NUWSub}, - {"udiv", irbuilder_UDiv}, - {"exactudiv", irbuilder_ExactUDiv}, - {"sdiv", irbuilder_SDiv}, - {"exactsdiv", irbuilder_ExactSDiv}, - {"neg", irbuilder_Neg}, - {"urem", irbuilder_URem}, - {"srem", irbuilder_SRem}, - {"and", irbuilder_And}, - {"or", irbuilder_Or}, - {"xor", irbuilder_Xor}, - {"not", irbuilder_Not}, - {"fadd", irbuilder_FAdd}, - {"fsub", irbuilder_FSub}, - {"fmul", irbuilder_FMul}, - {"fdiv", irbuilder_FDiv}, - {"frem", irbuilder_FRem}, - {"fneg", irbuilder_FNeg}, - {"gep", irbuilder_GEP}, - {"inboundsgep", irbuilder_InBoundsGEP}, - {"trunc", irbuilder_Trunc}, - {"zext", irbuilder_ZExt}, - {"sext", irbuilder_SExt}, - {"zextortrunc", irbuilder_ZExtOrTrunc}, - {"sextortrunc", irbuilder_SExtOrTrunc}, - {"fptoui", irbuilder_FPToUI}, - {"fptosi", irbuilder_FPToSI}, - {"uitofp", irbuilder_UIToFP}, - {"sitofp", irbuilder_SIToFP}, - {"fptrunc", irbuilder_FPTrunc}, - {"fpext", irbuilder_FPExt}, - {"ptrtoint", irbuilder_PtrToInt}, - {"inttoptr", irbuilder_IntToPtr}, - {"bitcast", irbuilder_BitCast}, - {"sextorbitcast", irbuilder_SExtOrBitCast}, - {"zextorbitcast", irbuilder_ZExtOrBitCast}, - {"truncorbitcast", irbuilder_TruncOrBitCast}, - {"pointercast", irbuilder_PointerCast}, - {"fpcast", irbuilder_FPCast}, - {"load", irbuilder_load}, - {"store", irbuilder_store}, - {"phi", irbuilder_phi}, - {NULL, NULL}}; - -LUAMOD_API int raviopen_llvmluaapi(lua_State *L) { - luaL_newmetatable(L, LLVM_context); - lua_pushstring(L, LLVM_context); - lua_setfield(L, -2, "type"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, context_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_module); - lua_pushstring(L, LLVM_module); - lua_setfield(L, -2, "type"); - lua_pushcfunction(L, collect_LLVM_module); - lua_setfield(L, -2, "__gc"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, module_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_irbuilder); - lua_pushstring(L, LLVM_irbuilder); - lua_setfield(L, -2, "type"); - lua_pushcfunction(L, collect_LLVM_irbuilder); - lua_setfield(L, -2, "__gc"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, irbuilder_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_mainfunction); - lua_pushstring(L, LLVM_mainfunction); - lua_setfield(L, -2, "type"); - lua_pushcfunction(L, collect_LLVM_mainfunction); - lua_setfield(L, -2, "__gc"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, main_function_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_function); - lua_pushstring(L, LLVM_function); - lua_setfield(L, -2, "type"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, function_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_type); - lua_pushstring(L, LLVM_type); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_value); - lua_pushstring(L, LLVM_value); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_structtype); - lua_pushstring(L, LLVM_structtype); - lua_setfield(L, -2, "type"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, structtype_methods, 0); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_pointertype); - lua_pushstring(L, LLVM_pointertype); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_functiontype); - lua_pushstring(L, LLVM_functiontype); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_basicblock); - lua_pushstring(L, LLVM_basicblock); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_constant); - lua_pushstring(L, LLVM_constant); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_instruction); - lua_pushstring(L, LLVM_instruction); - lua_setfield(L, -2, "type"); - lua_pop(L, 1); - - luaL_newmetatable(L, LLVM_phinode); - lua_pushstring(L, LLVM_phinode); - lua_setfield(L, -2, "type"); - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, phi_methods, 0); - lua_pop(L, 1); - - luaL_newlib(L, llvmlib); - return 1; -} - -#ifdef __cplusplus -} -#endif