add docs plus fix delete bug

Dibyendu Majumdar 9 years ago
parent cc518ebf73
commit e9abdb44ff

@ -14,6 +14,7 @@ Contents:
ravi-overview
lua-parser
ravi-internals
llvm-notes
ravi-jit-overview
ravi-jit-initial
ravi-jit-infra

@ -0,0 +1,160 @@
LLVM Notes
==========
The notes below apply to LLVM 3.5.1 unless noted otherwise. All reflect my understanding - so if anything here is incorrect please log an issue and I will correct.
Structs and Unions
------------------
LLVM does not support defining union types so we need to basically use a ``struct`` of appropriate size and cast it as we need. The main thing to be careful about is to ensure that the ``struct`` is of the same size as the ``union``.
An example is::
///*
//** Information about a call.
//** When a thread yields, 'func' is adjusted to pretend that the
//** top function has only the yielded values in its stack; in that
//** case, the actual 'func' value is saved in field 'extra'.
//** When a function calls another with a continuation, 'extra' keeps
//** the function index so that, in case of errors, the continuation
//** function can be called with the correct top.
//*/
// typedef struct CallInfo {
// StkId func; /* function index in the stack */
// StkId top; /* top for this function */
// struct CallInfo *previous, *next; /* dynamic call link */
// union {
// struct { /* only for Lua functions */
// StkId base; /* base for this function */
// const Instruction *savedpc;
// } l;
// struct { /* only for C functions */
// lua_KFunction k; /* continuation in case of yields */
// ptrdiff_t old_errfunc;
// lua_KContext ctx; /* context info. in case of yields */
// } c;
// } u;
// ptrdiff_t extra;
// short nresults; /* expected number of results from this function */
// lu_byte callstatus;
//} CallInfo;
Above the union ``u`` has two members of unequal size. To handle this I created the following two sub-types of equal size - note the extra dummy field in the first type::
elements.clear();
elements.push_back(StkIdT); /* base */
elements.push_back(pInstructionT); /* savedpc */
elements.push_back(
C_ptrdiff_t); /* dummy to make this same size as the other member */
CallInfo_lT = llvm::StructType::create(elements);
elements.clear();
elements.push_back(plua_KFunctionT); /* k */
elements.push_back(C_ptrdiff_t); /* old_errfunc */
elements.push_back(lua_KContextT); /* ctx */
CallInfo_cT = llvm::StructType::create(elements);
Then as I intend to use the ``u.l`` field more often, I used the following definition for ``CallInfo``::
CallInfoT = llvm::StructType::create(context, "ravi.CallInfo");
pCallInfoT = llvm::PointerType::get(CallInfoT, 0);
elements.clear();
elements.push_back(StkIdT); /* func */
elements.push_back(StkIdT); /* top */
elements.push_back(pCallInfoT); /* previous */
elements.push_back(pCallInfoT); /* next */
elements.push_back(
CallInfo_lT); /* u.l - as we will typically access the lua call details
*/
elements.push_back(C_ptrdiff_t); /* extra */
elements.push_back(llvm::Type::getInt16Ty(context)); /* nresults */
elements.push_back(lu_byteT); /* callstatus */
CallInfoT->setBody(elements);
JIT Compilation Error on Windows
--------------------------------
On Windows when we attempt to JIT compile we get an error saying incompatible object format
Reading posts on mailining lists I found that the issue is that COEFF
format is not supported and therefore we need to set -elf as the object
format::
#include "llvm/Support/Host.h"
/* some code */
#ifdef _WIN32
auto triple = llvm::sys::getProcessTriple();
module->setTargetTriple(triple + "-elf");
#endif
Memory Management
-----------------
It appears that most things in LLVM are owned by the parent object and when the parent object is deleted the children go too. So in my code the main objects I delete are the ``ExecutionEngine`` and ``Module``. Once a module is associated with an engine then only the engine needs to be explicitly deleted is my understanding.
It doesn't help that the tutorial available does not attempt to delete objects / release memory!
MCJIT Engines, Modules and Functions
------------------------------------
Functions live inside Modules but once a Module is finalized (compiled) then no further functions can be added to it. Although an ``MCJIT`` instance (engine) can support multiples modules, the recommendation is to ensure each module is assigned its own engine. The rationale for this is not explained.
Struct Assign
-------------
My understanding is that to perform assignment of a struct value, one must call the intrinsic ``memcpy`` function. Example of code that does this::
llvm::Value *src;
llvm::Value *dest;
// First get the declaration for the inttrinsic memcpy
llvm::SmallVector<llvm::Type *, 3> vec;
vec.push_back(def->types->C_pcharT); /* i8 */
vec.push_back(def->types->C_pcharT); /* i8 */
vec.push_back(def->types->C_intT);
llvm::Function *f = llvm::Intrinsic::getDeclaration(
def->raviF->module(), llvm::Intrinsic::memcpy, vec);
lua_assert(f);
// Cast src and dest to i8*
llvm::Value *dest_ptr =
def->builder->CreateBitCast(dest, def->types->C_pcharT);
llvm::Value *src_ptr = def->builder->CreateBitCast(src, def->types->C_pcharT);
// Create call to intrinsic memcpy
values_.clear();
values_.push_back(dest_ptr);
values_.push_back(src_ptr);
values_.push_back(llvm::ConstantInt::get(def->types->C_intT, sizeof(TValue)));
values_.push_back(
llvm::ConstantInt::get(def->types->C_intT, sizeof(L_Umaxalign)));
values_.push_back(def->types->kFalse);
def->builder->CreateCall(f, values_);
Note that the call to memcpy supply an alignment.
Accessing ``extern`` functions from JIT compiled code
-----------------------------------------------------
If the JITed function needs to access ``extern`` functions that are statically linked and not exported as dynamic symbols (e.g. in Visual C++) then we need some extra steps.
From reading posts on the subject it appears that the way to do this is to add a global mapping in the ``ExecutionEngine`` by calling the
``addGlobalMapping()`` method. However this doesn't work with MCJIT due to a bug! So we need to use a workaround. Apparently there are two
solutions:
* Create a custom memory manager that resolves the ``extern`` functions.
* Add the symbol to the global symbols by calling ``llvm::sys::DynamicLibrary::AddSymbol()``.
I am using the latter approach for now.
GEP instruction
---------------
The GEP instruction cannot compute addresses of fields in a pointer member - as the pointer needs to be 'loaded' first. This is explained in the `GEP FAQ <http://llvm.org/docs/GetElementPtr.html#id6>`_.
Links
-----
* `Mapping High Level Constructs to LLVM IR <http://llvm.lyngvig.org/Articles/Mapping-High-Level-Constructs-to-LLVM-IR>`_
* `IRBuilder Sample <https://github.com/eliben/llvm-clang-samples/blob/master/src_llvm/experimental/build_llvm_ir.cpp>`_
* `Using MCJIT with Kaleidoscope <http://blog.llvm.org/2013/07/using-mcjit-with-kaleidoscope-tutorial.html>`_
* `Object format issue on Windows <http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-December/068407.html>`_
* `ExecutionEngine::addGlobalMapping() bug in MCJIT <http://llvm.org/bugs/show_bug.cgi?id=20656>`_
* `LLVM Notes <http://nondot.org/sabre/LLVMNotes/>`_

@ -0,0 +1,162 @@
LLVM Compilation hooks in Ravi
==============================
The current approach is Ravi is that a Lua function can be compiled at the function level. (Note that this is the plan - I am working on the implementation).
In terms of changes to support this - we essentially have following. First we have a bunch of C functions - think of these are the compiler API::
#ifdef __cplusplus
extern "C" {
#endif
struct lua_State;
struct Proto;
/* Initialise the JIT engine */
int raviV_initjit(struct lua_State *L);
/* Shutdown the JIT engine */
void raviV_close(struct lua_State *L);
/* Compile the given function if possible */
int raviV_compile(struct lua_State *L, struct Proto *p);
/* Free the JIT structures associated with the prototype */
void raviV_freeproto(struct lua_State *L, struct Proto *p);
#ifdef __cplusplus
}
#endif
Next the ``Proto`` struct definition has some extra fields::
typedef struct RaviJITProto {
lu_byte jit_status; // 0=not compiled, 1=can't compile, 2=compiled, 3=freed
void *jit_data;
lua_CFunction jit_function;
} RaviJITProto;
/*
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg;
lu_byte maxstacksize; /* maximum stack used by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of 'p' */
int sizelocvars;
int linedefined;
int lastlinedefined;
TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines (debug information) */
LocVar *locvars; /* information about local variables (debug information) */
Upvaldesc *upvalues; /* upvalue information */
struct LClosure *cache; /* last created closure with this prototype */
TString *source; /* used for debug information */
GCObject *gclist;
/* RAVI */
RaviJITProto ravi_jit;
} Proto;
The ``ravi_jit`` member is initialized in ``lfunc.c``::
Proto *luaF_newproto (lua_State *L) {
GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto));
Proto *f = gco2p(o);
f->k = NULL;
/* code ommitted */
f->ravi_jit.jit_data = NULL;
f->ravi_jit.jit_function = NULL;
f->ravi_jit.jit_status = 0; /* not compiled */
return f;
}
The corresponding function to free is::
void luaF_freeproto (lua_State *L, Proto *f) {
raviV_freeproto(L, f);
luaM_freearray(L, f->code, f->sizecode);
luaM_freearray(L, f->p, f->sizep);
luaM_freearray(L, f->k, f->sizek);
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
luaM_freearray(L, f->locvars, f->sizelocvars);
luaM_freearray(L, f->upvalues, f->sizeupvalues);
luaM_free(L, f);
}
When a Lua Function is called it goes through ``luaD_precall()`` in ``ldo.c``. This has been modified to invoke the compiler / use compiled version::
/*
** returns true if function has been executed (C function)
*/
int luaD_precall (lua_State *L, StkId func, int nresults) {
lua_CFunction f;
CallInfo *ci;
int n; /* number of arguments (Lua) or returns (C) */
ptrdiff_t funcr = savestack(L, func);
switch (ttype(func)) {
/* omitted */
case LUA_TLCL: { /* Lua function: prepare its call */
CallInfo *prevci = L->ci; /* RAVI - for validation */
StkId base;
Proto *p = clLvalue(func)->p;
n = cast_int(L->top - func) - 1; /* number of real arguments */
luaD_checkstack(L, p->maxstacksize);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
if (!p->is_vararg) {
func = restorestack(L, funcr);
base = func + 1;
}
else {
base = adjust_varargs(L, p, n);
func = restorestack(L, funcr); /* previous call can change stack */
}
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
ci->u.l.base = base;
ci->top = base + p->maxstacksize;
lua_assert(ci->top <= L->stack_last);
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
L->top = ci->top;
luaC_checkGC(L); /* stack grow uses memory */
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
if (p->ravi_jit.jit_status == 0) {
/* not compiled */
raviV_compile(L, p);
}
if (p->ravi_jit.jit_status == 2) {
/* compiled */
lua_assert(p->ravi_jit.jit_function != NULL);
(*p->ravi_jit.jit_function)(L);
lua_assert(L->ci == prevci);
ci = L->ci;
lua_assert(isLua(ci));
lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
return 1;
}
return 0;
}
default: { /* not a function */
/* omitted */
}
}
}
Note that the above returns 1 if compiled function is called so that the behaviour in ``lvm.c`` is similar to that when a C function is called.

@ -12,7 +12,7 @@ Primary reason for Ravi's existence is that it needs to be implemented using tec
Status
------
Project kicked off Feb 2015. I am new to this so progress will be slow and painful. I would like to get this compiler built and working by first half of 2015. As I make progress I will document the results here.
Project kicked off Feb 2015. I am new to this so progress will be slow. I would like to get this compiler built and working by first half of 2015. As I make progress I will document the results here.
Preparing for LLVM
------------------
@ -28,7 +28,7 @@ After modifying Ravi's ``CMakeLists.txt`` I invoked the cmake config as follows:
On Ubuntu I found that the official LLVM distributions don't work with CMake. The CMake config files appear to be broken.
So I ended up downloading and building LLVM 3.5.1 from source and that worked. I used the same approach as on Windows - i.e., set ``CMAKE_INSTALL_PREFIX`` using ``cmake-gui`` and that was about it.
So I ended up downloading and building LLVM 3.5.1 from source and that worked. I used the same approach as on Windows - i.e., set ``CMAKE_INSTALL_PREFIX`` using ``cmake-gui`` to ``~/LLVM`` and that was about it.
The command to create makefiles was as follows::

@ -0,0 +1,707 @@
Lua Types in LLVM
=================
We need to map Lua types to equivalent type definitions in LLVM. In Ravi we do hold all the type definitions in a struct as shown below::
struct LuaLLVMTypes {
llvm::Type *C_intptr_t;
llvm::Type *C_size_t;
llvm::Type *C_ptrdiff_t;
llvm::Type *lua_NumberT;
llvm::Type *lua_IntegerT;
llvm::Type *lua_UnsignedT;
llvm::Type *lua_KContextT;
llvm::FunctionType *lua_CFunctionT;
llvm::PointerType *plua_CFunctionT;
llvm::FunctionType *lua_KFunctionT;
llvm::PointerType *plua_KFunctionT;
llvm::FunctionType *lua_HookT;
llvm::PointerType *plua_HookT;
llvm::FunctionType *lua_AllocT;
llvm::PointerType *plua_AllocT;
llvm::Type *l_memT;
llvm::Type *lu_memT;
llvm::Type *lu_byteT;
llvm::Type *L_UmaxalignT;
llvm::Type *C_pcharT;
llvm::Type *C_intT;
llvm::StructType *lua_StateT;
llvm::PointerType *plua_StateT;
llvm::StructType *global_StateT;
llvm::PointerType *pglobal_StateT;
llvm::StructType *ravi_StateT;
llvm::PointerType *pravi_StateT;
llvm::StructType *GCObjectT;
llvm::PointerType *pGCObjectT;
llvm::StructType *ValueT;
llvm::StructType *TValueT;
llvm::PointerType *pTValueT;
llvm::StructType *TStringT;
llvm::PointerType *pTStringT;
llvm::PointerType *ppTStringT;
llvm::StructType *UdataT;
llvm::StructType *TableT;
llvm::PointerType *pTableT;
llvm::StructType *UpvaldescT;
llvm::PointerType *pUpvaldescT;
llvm::Type *ravitype_tT;
llvm::StructType *LocVarT;
llvm::PointerType *pLocVarT;
llvm::Type *InstructionT;
llvm::PointerType *pInstructionT;
llvm::StructType *LClosureT;
llvm::PointerType *pLClosureT;
llvm::PointerType *ppLClosureT;
llvm::PointerType *pppLClosureT;
llvm::StructType *RaviJITProtoT;
llvm::PointerType *pRaviJITProtoT;
llvm::StructType *ProtoT;
llvm::PointerType *pProtoT;
llvm::PointerType *ppProtoT;
llvm::StructType *UpValT;
llvm::PointerType *pUpValT;
llvm::StructType *CClosureT;
llvm::PointerType *pCClosureT;
llvm::StructType *TKeyT;
llvm::PointerType *pTKeyT;
llvm::StructType *NodeT;
llvm::PointerType *pNodeT;
llvm::StructType *lua_DebugT;
llvm::PointerType *plua_DebugT;
llvm::StructType *lua_longjumpT;
llvm::PointerType *plua_longjumpT;
llvm::StructType *MbufferT;
llvm::StructType *stringtableT;
llvm::PointerType *StkIdT;
llvm::StructType *CallInfoT;
llvm::StructType *CallInfo_cT;
llvm::StructType *CallInfo_lT;
llvm::PointerType *pCallInfoT;
llvm::FunctionType *jitFunctionT;
llvm::FunctionType *luaD_poscallT;
};
The actual definition of the types above is shown below::
static_assert(std::is_floating_point<lua_Number>::value &&
sizeof(lua_Number) == sizeof(double),
"lua_Number is not a double");
lua_NumberT = llvm::Type::getDoubleTy(context);
static_assert(std::is_integral<lua_Integer>::value,
"lua_Integer is not an integer type");
lua_IntegerT = llvm::Type::getIntNTy(context, sizeof(lua_Integer) * 8);
static_assert(sizeof(lua_Integer) == sizeof(lua_Unsigned),
"lua_Integer and lua_Unsigned are of different size");
lua_UnsignedT = lua_IntegerT;
C_intptr_t = llvm::Type::getIntNTy(context, sizeof(intptr_t) * 8);
C_size_t = llvm::Type::getIntNTy(context, sizeof(size_t) * 8);
C_ptrdiff_t = llvm::Type::getIntNTy(context, sizeof(ptrdiff_t) * 8);
C_intT = llvm::Type::getIntNTy(context, sizeof(int) * 8);
static_assert(sizeof(size_t) == sizeof(lu_mem),
"lu_mem size is not same as size_t");
lu_memT = C_size_t;
static_assert(sizeof(ptrdiff_t) == sizeof(l_mem),
"l_mem size is not same as ptrdiff_t");
l_memT = C_ptrdiff_t;
static_assert(sizeof(L_Umaxalign) == sizeof(double),
"L_Umaxalign is not same size as double");
L_UmaxalignT = llvm::Type::getDoubleTy(context);
lu_byteT = llvm::Type::getInt8Ty(context);
C_pcharT = llvm::Type::getInt8PtrTy(context);
InstructionT = C_intT;
pInstructionT = llvm::PointerType::get(InstructionT, 0);
lua_StateT = llvm::StructType::create(context, "ravi.lua_State");
plua_StateT = llvm::PointerType::get(lua_StateT, 0);
lua_KContextT = C_ptrdiff_t;
std::vector<llvm::Type *> elements;
elements.push_back(plua_StateT);
lua_CFunctionT = llvm::FunctionType::get(C_intT, elements, false);
plua_CFunctionT = llvm::PointerType::get(lua_CFunctionT, 0);
jitFunctionT = lua_CFunctionT;
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(C_intT);
elements.push_back(lua_KContextT);
lua_KFunctionT = llvm::FunctionType::get(C_intT, elements, false);
plua_KFunctionT = llvm::PointerType::get(lua_KFunctionT, 0);
elements.clear();
elements.push_back(llvm::Type::getInt8PtrTy(context));
elements.push_back(llvm::Type::getInt8PtrTy(context));
elements.push_back(C_size_t);
elements.push_back(C_size_t);
lua_AllocT = llvm::FunctionType::get(llvm::Type::getInt8PtrTy(context),
elements, false);
plua_AllocT = llvm::PointerType::get(lua_AllocT, 0);
lua_DebugT = llvm::StructType::create(context, "ravi.lua_Debug");
plua_DebugT = llvm::PointerType::get(lua_DebugT, 0);
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(plua_DebugT);
lua_HookT = llvm::FunctionType::get(llvm::Type::getInt8PtrTy(context),
elements, false);
plua_HookT = llvm::PointerType::get(lua_HookT, 0);
// struct GCObject {
// GCObject *next;
// lu_byte tt;
// lu_byte marked
// };
GCObjectT = llvm::StructType::create(context, "ravi.GCObject");
pGCObjectT = llvm::PointerType::get(GCObjectT, 0);
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
GCObjectT->setBody(elements);
static_assert(sizeof(Value) == sizeof(lua_Number),
"Value type is larger than lua_Number");
// In LLVM unions should be set to the largest member
// So in the case of a Value this is the double type
// union Value {
// GCObject *gc; /* collectable objects */
// void *p; /* light userdata */
// int b; /* booleans */
// lua_CFunction f; /* light C functions */
// lua_Integer i; /* integer numbers */
// lua_Number n; /* float numbers */
// };
ValueT = llvm::StructType::create(context, "ravi.Value");
elements.clear();
elements.push_back(lua_NumberT);
ValueT->setBody(elements);
// struct TValue {
// union Value value_;
// int tt_;
// };
TValueT = llvm::StructType::create(context, "ravi.TValue");
elements.clear();
elements.push_back(ValueT);
elements.push_back(C_intT);
TValueT->setBody(elements);
pTValueT = llvm::PointerType::get(TValueT, 0);
StkIdT = pTValueT;
///*
//** Header for string value; string bytes follow the end of this structure
//** (aligned according to 'UTString'; see next).
//*/
// typedef struct TString {
// GCObject *next;
// lu_byte tt;
// lu_byte marked
// lu_byte extra; /* reserved words for short strings; "has hash" for longs
// */
// unsigned int hash;
// size_t len; /* number of characters in string */
// struct TString *hnext; /* linked list for hash table */
// } TString;
///*
//** Ensures that address after this type is always fully aligned.
//*/
// typedef union UTString {
// L_Umaxalign dummy; /* ensures maximum alignment for strings */
// TString tsv;
//} UTString;
TStringT = llvm::StructType::create(context, "ravi.TString");
pTStringT = llvm::PointerType::get(TStringT, 0);
ppTStringT = llvm::PointerType::get(pTStringT, 0);
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* extra */
elements.push_back(C_intT); /* hash */
elements.push_back(C_size_t); /* len */
elements.push_back(pTStringT); /* hnext */
TStringT->setBody(elements);
// Table
TableT = llvm::StructType::create(context, "ravi.Table");
pTableT = llvm::PointerType::get(TableT, 0);
///*
//** Header for userdata; memory area follows the end of this structure
//** (aligned according to 'UUdata'; see next).
//*/
// typedef struct Udata {
// GCObject *next;
// lu_byte tt;
// lu_byte marked
// lu_byte ttuv_; /* user value's tag */
// struct Table *metatable;
// size_t len; /* number of bytes */
// union Value user_; /* user value */
//} Udata;
UdataT = llvm::StructType::create(context, "ravi.Udata");
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* ttuv_ */
elements.push_back(pTableT); /* metatable */
elements.push_back(C_size_t); /* len */
elements.push_back(ValueT); /* user_ */
UdataT->setBody(elements);
///*
//** Description of an upvalue for function prototypes
//*/
// typedef struct Upvaldesc {
// TString *name; /* upvalue name (for debug information) */
// lu_byte instack; /* whether it is in stack */
// lu_byte idx; /* index of upvalue (in stack or in outer function's list)
// */
//}Upvaldesc;
UpvaldescT = llvm::StructType::create(context, "ravi.Upvaldesc");
elements.clear();
elements.push_back(pTStringT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
UpvaldescT->setBody(elements);
pUpvaldescT = llvm::PointerType::get(UpvaldescT, 0);
///*
//** Description of a local variable for function prototypes
//** (used for debug information)
//*/
// typedef struct LocVar {
// TString *varname;
// int startpc; /* first point where variable is active */
// int endpc; /* first point where variable is dead */
// ravitype_t ravi_type; /* RAVI type of the variable - RAVI_TANY if unknown
// */
//} LocVar;
ravitype_tT = llvm::Type::getIntNTy(context, sizeof(ravitype_t) * 8);
LocVarT = llvm::StructType::create(context, "ravi.LocVar");
elements.clear();
elements.push_back(pTStringT); /* varname */
elements.push_back(C_intT); /* startpc */
elements.push_back(C_intT); /* endpc */
elements.push_back(ravitype_tT); /* ravi_type */
LocVarT->setBody(elements);
pLocVarT = llvm::PointerType::get(LocVarT, 0);
LClosureT = llvm::StructType::create(context, "ravi.LClosure");
pLClosureT = llvm::PointerType::get(LClosureT, 0);
ppLClosureT = llvm::PointerType::get(pLClosureT, 0);
pppLClosureT = llvm::PointerType::get(ppLClosureT, 0);
RaviJITProtoT = llvm::StructType::create(context, "ravi.RaviJITProto");
pRaviJITProtoT = llvm::PointerType::get(RaviJITProtoT, 0);
///*
//** Function Prototypes
//*/
// typedef struct Proto {
// CommonHeader;
// lu_byte numparams; /* number of fixed parameters */
// lu_byte is_vararg;
// lu_byte maxstacksize; /* maximum stack used by this function */
// int sizeupvalues; /* size of 'upvalues' */
// int sizek; /* size of 'k' */
// int sizecode;
// int sizelineinfo;
// int sizep; /* size of 'p' */
// int sizelocvars;
// int linedefined;
// int lastlinedefined;
// TValue *k; /* constants used by the function */
// Instruction *code;
// struct Proto **p; /* functions defined inside the function */
// int *lineinfo; /* map from opcodes to source lines (debug information) */
// LocVar *locvars; /* information about local variables (debug information)
// */
// Upvaldesc *upvalues; /* upvalue information */
// struct LClosure *cache; /* last created closure with this prototype */
// TString *source; /* used for debug information */
// GCObject *gclist;
// /* RAVI */
// RaviJITProto *ravi_jit;
//} Proto;
ProtoT = llvm::StructType::create(context, "ravi.Proto");
pProtoT = llvm::PointerType::get(ProtoT, 0);
ppProtoT = llvm::PointerType::get(pProtoT, 0);
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* numparams */
elements.push_back(lu_byteT); /* is_vararg */
elements.push_back(lu_byteT); /* maxstacksize */
elements.push_back(C_intT); /* sizeupvalues */
elements.push_back(C_intT); /* sizek */
elements.push_back(C_intT); /* sizecode */
elements.push_back(C_intT); /* sizelineinfo */
elements.push_back(C_intT); /* sizep */
elements.push_back(C_intT); /* sizelocvars */
elements.push_back(C_intT); /* linedefined */
elements.push_back(C_intT); /* lastlinedefined */
elements.push_back(pTValueT); /* k */
elements.push_back(pInstructionT); /* code */
elements.push_back(ppProtoT); /* p */
elements.push_back(llvm::PointerType::get(C_intT, 0)); /* lineinfo */
elements.push_back(pLocVarT); /* locvars */
elements.push_back(pUpvaldescT); /* upvalues */
elements.push_back(pLClosureT); /* cache */
elements.push_back(pTStringT); /* source */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(pRaviJITProtoT); /* ravi_jit */
ProtoT->setBody(elements);
///*
//** Lua Upvalues
//*/
// typedef struct UpVal UpVal;
UpValT = llvm::StructType::create(context, "ravi.UpVal");
pUpValT = llvm::PointerType::get(UpValT, 0);
///*
//** Closures
//*/
//#define ClosureHeader \
//CommonHeader; lu_byte nupvalues; GCObject *gclist
// typedef struct CClosure {
// ClosureHeader;
// lua_CFunction f;
// TValue upvalue[1]; /* list of upvalues */
//} CClosure;
CClosureT = llvm::StructType::create(context, "ravi.CClosure");
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* nupvalues */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(plua_CFunctionT); /* f */
elements.push_back(llvm::ArrayType::get(TValueT, 1));
CClosureT->setBody(elements);
pCClosureT = llvm::PointerType::get(CClosureT, 0);
// typedef struct LClosure {
// ClosureHeader;
// struct Proto *p;
// UpVal *upvals[1]; /* list of upvalues */
//} LClosure;
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* nupvalues */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(pProtoT); /* p */
elements.push_back(llvm::ArrayType::get(pUpValT, 1));
LClosureT->setBody(elements);
///*
//** Tables
//*/
// typedef union TKey {
// struct {
// TValuefields;
// int next; /* for chaining (offset for next node) */
// } nk;
// TValue tvk;
//} TKey;
TKeyT = llvm::StructType::create(context, "ravi.TKey");
elements.clear();
elements.push_back(ValueT);
elements.push_back(C_intT);
elements.push_back(C_intT); /* next */
TKeyT->setBody(elements);
pTKeyT = llvm::PointerType::get(TKeyT, 0);
// typedef struct Node {
// TValue i_val;
// TKey i_key;
//} Node;
NodeT = llvm::StructType::create(context, "ravi.Node");
elements.clear();
elements.push_back(TValueT); /* i_val */
elements.push_back(TKeyT); /* i_key */
NodeT->setBody(elements);
pNodeT = llvm::PointerType::get(NodeT, 0);
// typedef struct Table {
// CommonHeader;
// lu_byte flags; /* 1<<p means tagmethod(p) is not present */
// lu_byte lsizenode; /* log2 of size of 'node' array */
// unsigned int sizearray; /* size of 'array' array */
// TValue *array; /* array part */
// Node *node;
// Node *lastfree; /* any free position is before this position */
// struct Table *metatable;
// GCObject *gclist;
// ravitype_t ravi_array_type; /* RAVI specialization */
// unsigned int ravi_array_len; /* RAVI len specialization */
//} Table;
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* flags */
elements.push_back(lu_byteT); /* lsizenode */
elements.push_back(C_intT); /* sizearray */
elements.push_back(pTValueT); /* array part */
elements.push_back(pNodeT); /* node */
elements.push_back(pNodeT); /* lastfree */
elements.push_back(pTableT); /* metatable */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(ravitype_tT); /* ravi_array_type */
elements.push_back(C_intT); /* ravi_array_len */
TableT->setBody(elements);
// struct lua_longjmp; /* defined in ldo.c */
lua_longjumpT = llvm::StructType::create(context, "ravi.lua_longjmp");
plua_longjumpT = llvm::PointerType::get(lua_longjumpT, 0);
// lzio.h
// typedef struct Mbuffer {
// char *buffer;
// size_t n;
// size_t buffsize;
//} Mbuffer;
MbufferT = llvm::StructType::create(context, "ravi.Mbuffer");
elements.clear();
elements.push_back(llvm::Type::getInt8PtrTy(context)); /* buffer */
elements.push_back(C_size_t); /* n */
elements.push_back(C_size_t); /* buffsize */
MbufferT->setBody(elements);
// typedef struct stringtable {
// TString **hash;
// int nuse; /* number of elements */
// int size;
//} stringtable;
stringtableT = llvm::StructType::create(context, "ravi.stringtable");
elements.clear();
elements.push_back(ppTStringT); /* hash */
elements.push_back(C_intT); /* nuse */
elements.push_back(C_intT); /* size */
stringtableT->setBody(elements);
///*
//** Information about a call.
//** When a thread yields, 'func' is adjusted to pretend that the
//** top function has only the yielded values in its stack; in that
//** case, the actual 'func' value is saved in field 'extra'.
//** When a function calls another with a continuation, 'extra' keeps
//** the function index so that, in case of errors, the continuation
//** function can be called with the correct top.
//*/
// typedef struct CallInfo {
// StkId func; /* function index in the stack */
// StkId top; /* top for this function */
// struct CallInfo *previous, *next; /* dynamic call link */
// union {
// struct { /* only for Lua functions */
// StkId base; /* base for this function */
// const Instruction *savedpc;
// } l;
// struct { /* only for C functions */
// lua_KFunction k; /* continuation in case of yields */
// ptrdiff_t old_errfunc;
// lua_KContext ctx; /* context info. in case of yields */
// } c;
// } u;
// ptrdiff_t extra;
// short nresults; /* expected number of results from this function */
// lu_byte callstatus;
//} CallInfo;
elements.clear();
elements.push_back(StkIdT); /* base */
elements.push_back(pInstructionT); /* savedpc */
elements.push_back(
C_ptrdiff_t); /* dummy to make this same size as the other member */
CallInfo_lT = llvm::StructType::create(elements);
elements.clear();
elements.push_back(plua_KFunctionT); /* k */
elements.push_back(C_ptrdiff_t); /* old_errfunc */
elements.push_back(lua_KContextT); /* ctx */
CallInfo_cT = llvm::StructType::create(elements);
CallInfoT = llvm::StructType::create(context, "ravi.CallInfo");
pCallInfoT = llvm::PointerType::get(CallInfoT, 0);
elements.clear();
elements.push_back(StkIdT); /* func */
elements.push_back(StkIdT); /* top */
elements.push_back(pCallInfoT); /* previous */
elements.push_back(pCallInfoT); /* next */
elements.push_back(
CallInfo_lT); /* u.l - as we will typically access the lua call details
*/
elements.push_back(C_ptrdiff_t); /* extra */
elements.push_back(llvm::Type::getInt16Ty(context)); /* nresults */
elements.push_back(lu_byteT); /* callstatus */
CallInfoT->setBody(elements);
// typedef struct ravi_State ravi_State;
ravi_StateT = llvm::StructType::create(context, "ravi.ravi_State");
pravi_StateT = llvm::PointerType::get(ravi_StateT, 0);
///*
//** 'global state', shared by all threads of this state
//*/
// typedef struct global_State {
// lua_Alloc frealloc; /* function to reallocate memory */
// void *ud; /* auxiliary data to 'frealloc' */
// lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
// l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
// lu_mem GCmemtrav; /* memory traversed by the GC */
// lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
// stringtable strt; /* hash table for strings */
// TValue l_registry;
// unsigned int seed; /* randomized seed for hashes */
// lu_byte currentwhite;
// lu_byte gcstate; /* state of garbage collector */
// lu_byte gckind; /* kind of GC running */
// lu_byte gcrunning; /* true if GC is running */
// GCObject *allgc; /* list of all collectable objects */
// GCObject **sweepgc; /* current position of sweep in list */
// GCObject *finobj; /* list of collectable objects with finalizers */
// GCObject *gray; /* list of gray objects */
// GCObject *grayagain; /* list of objects to be traversed atomically */
// GCObject *weak; /* list of tables with weak values */
// GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
// GCObject *allweak; /* list of all-weak tables */
// GCObject *tobefnz; /* list of userdata to be GC */
// GCObject *fixedgc; /* list of objects not to be collected */
// struct lua_State *twups; /* list of threads with open upvalues */
// Mbuffer buff; /* temporary buffer for string concatenation */
// unsigned int gcfinnum; /* number of finalizers to call in each GC step */
// int gcpause; /* size of pause between successive GCs */
// int gcstepmul; /* GC 'granularity' */
// lua_CFunction panic; /* to be called in unprotected errors */
// struct lua_State *mainthread;
// const lua_Number *version; /* pointer to version number */
// TString *memerrmsg; /* memory-error message */
// TString *tmname[TM_N]; /* array with tag-method names */
// struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
// /* RAVI */
// ravi_State *ravi_state;
//} global_State;
global_StateT = llvm::StructType::create(context, "ravi.global_State");
pglobal_StateT = llvm::PointerType::get(global_StateT, 0);
///*
//** 'per thread' state
//*/
// struct lua_State {
// CommonHeader;
// lu_byte status;
// StkId top; /* first free slot in the stack */
// global_State *l_G;
// CallInfo *ci; /* call info for current function */
// const Instruction *oldpc; /* last pc traced */
// StkId stack_last; /* last free slot in the stack */
// StkId stack; /* stack base */
// UpVal *openupval; /* list of open upvalues in this stack */
// GCObject *gclist;
// struct lua_State *twups; /* list of threads with open upvalues */
// struct lua_longjmp *errorJmp; /* current error recover point */
// CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
// lua_Hook hook;
// ptrdiff_t errfunc; /* current error handling function (stack index) */
// int stacksize;
// int basehookcount;
// int hookcount;
// unsigned short nny; /* number of non-yieldable calls in stack */
// unsigned short nCcalls; /* number of nested C calls */
// lu_byte hookmask;
// lu_byte allowhook;
//};
elements.clear();
elements.push_back(pGCObjectT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT);
elements.push_back(lu_byteT); /* status */
elements.push_back(StkIdT); /* top */
elements.push_back(pglobal_StateT); /* l_G */
elements.push_back(pCallInfoT); /* ci */
elements.push_back(pInstructionT); /* oldpc */
elements.push_back(StkIdT); /* stack_last */
elements.push_back(StkIdT); /* stack */
elements.push_back(pUpValT); /* openupval */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(plua_StateT); /* twups */
elements.push_back(plua_longjumpT); /* errorJmp */
elements.push_back(CallInfoT); /* base_ci */
elements.push_back(plua_HookT); /* hook */
elements.push_back(C_ptrdiff_t); /* errfunc */
elements.push_back(C_intT); /* stacksize */
elements.push_back(C_intT); /* basehookcount */
elements.push_back(C_intT); /* hookcount */
elements.push_back(llvm::Type::getInt16Ty(context)); /* nny */
elements.push_back(llvm::Type::getInt16Ty(context)); /* nCcalls */
elements.push_back(lu_byteT); /* hookmask */
elements.push_back(lu_byteT); /* allowhook */
lua_StateT->setBody(elements);
// int luaD_poscall (lua_State *L, StkId firstResult)
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(StkIdT);
luaD_poscallT = llvm::FunctionType::get(C_intT, elements, false);

@ -126,6 +126,7 @@ Proto *luaF_newproto (lua_State *L) {
void luaF_freeproto (lua_State *L, Proto *f) {
raviV_freeproto(L, f);
luaM_freearray(L, f->code, f->sizecode);
luaM_freearray(L, f->p, f->sizep);
luaM_freearray(L, f->k, f->sizek);

@ -247,6 +247,7 @@ static void close_state (lua_State *L) {
luaZ_freebuffer(L, &g->buff);
freestack(L);
lua_assert(gettotalbytes(g) == sizeof(LG));
raviV_close(L);
(*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
}
@ -343,7 +344,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
LUA_API void lua_close (lua_State *L) {
L = G(L)->mainthread; /* only the main thread can be closed */
lua_lock(L);
raviV_close(L);
close_state(L);
}

@ -1572,7 +1572,7 @@ int raviV_compile(struct lua_State *L, struct Proto *p) {
void raviV_freeproto(struct lua_State *L, struct Proto *p) {
if (p->ravi_jit.jit_status == 2) /* compiled */ {
ravi::RaviJITFunction *f = (ravi::RaviJITFunction *)p->ravi_jit.jit_data;
ravi::RaviJITFunction *f = reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
delete f;
p->ravi_jit.jit_status = 3;

Loading…
Cancel
Save