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<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);
-
-
diff --git a/readthedocs/ravi-mir-instructions.rst b/readthedocs/ravi-mir-instructions.rst
index b6dc940..4d8ac43 100644
--- a/readthedocs/ravi-mir-instructions.rst
+++ b/readthedocs/ravi-mir-instructions.rst
@@ -1,8 +1,6 @@
Instructions for Building With MIR JIT support
==============================================
-Please note that currently `MIR `_ JIT support is only available on Linux X86-64 platforms.
-
Building with MIR support is straightforward as MIR is included in Ravi::
mkdir buildmir
@@ -11,3 +9,10 @@ Building with MIR support is straightforward as MIR is included in Ravi::
make install
That's it.
+
+For Windows, try this::
+
+ mkdir buildmir
+ cd buildmir
+ cmake -DCMAKE_INSTALL_PREFIX=/Software/ravi -DCMAKE_BUILD_TYPE=Release -DMIR_JIT=ON ..
+ cmake --build . --config Release
diff --git a/readthedocs/ravi-overview.rst b/readthedocs/ravi-overview.rst
index 39c1681..9fd15ec 100644
--- a/readthedocs/ravi-overview.rst
+++ b/readthedocs/ravi-overview.rst
@@ -5,7 +5,7 @@ Ravi Programming Language
:target: https://travis-ci.org/dibyendumajumdar/ravi
Ravi is a dialect of `Lua `_ with limited optional static typing and
-features `MIR `_ and `LLVM `_ powered JIT compilers.
+features `MIR `_ powered JIT compilers.
The name Ravi comes from the Sanskrit word for the Sun.
Interestingly a precursor to Lua was `Sol `_ which had support for
static types; Sol means the Sun in Portugese.
@@ -35,8 +35,7 @@ Features
* Compatibility with Lua 5.3 (see Compatibility section below)
* Generational GC from Lua 5.4
* ``defer`` statement for releasing resources
-* Compact JIT backend `MIR `_; only Linux and x86-64 supported for now.
-* `LLVM `_ supported as alternative JIT backend.
+* Compact JIT backend `MIR `_.
* A `distribution with batteries `_.
* A `Visual Studio Code debugger extension `_ - interpreted mode debugger.
@@ -44,7 +43,6 @@ Documentation
=============
* For the Lua extensions in Ravi see the `Reference Manual `_.
* `MIR JIT Build instructions `_.
-* `LLVM JIT Build instructions `_.
* Also see `Ravi Documentation `_.
* and the slides I presented at the `Lua 2015 Workshop `_.
@@ -99,6 +97,7 @@ When JIT compilation is enabled there are following additional constraints:
* Ravi will only execute JITed code from the main Lua thread; any secondary threads (coroutines) execute in interpreter mode.
* In JITed code tailcalls are implemented as regular calls so unlike the interpreter VM which supports infinite tail recursion JIT compiled code only supports tail recursion to a depth of about 110 (issue #17)
+* Debug api and hooks are not supported in JIT mode
History
=======
@@ -115,11 +114,13 @@ History
- Created `Ravi with batteries `_.
* 2019
- New language feature - `defer` statement
- - New JIT backend `MIR `_.
-
-* 2020 (Plan)
- - `New optimizing byte code generator based on new parser / type checker `_
+ - New JIT backend `MIR `_.
+* 2020
+ - `New parser / type checker / compiler `_
- Generational GC back-ported from Lua 5.4
+ - Support for `LLVM backend `_ archived
+* 2021 (Plan)
+ - Integrated AOT and JIT compilation support
- Ravi 1.0 release
License
diff --git a/src/ravi_llvmarith1.cpp b/src/ravi_llvmarith1.cpp
deleted file mode 100644
index 8a93546..0000000
--- a/src/ravi_llvmarith1.cpp
+++ /dev/null
@@ -1,374 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-// This file contains LLVM IR generation for Ravi's arithmetic
-// op codes - these are enhanced type specific op codes not part of
-// standard Lua
-
-namespace ravi {
-
-// R(A) := -R(B), floating point
-// NOT yet used
-void RaviCodeGenerator::emit_UNMF(RaviFunctionDef *def, int A, int B, int pc) {
- (void)pc;
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Instruction *lhs = emit_load_reg_n(def, rb);
- llvm::Value *result = def->builder->CreateFNeg(lhs);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := -R(B), integer
-// NOT yet used
-void RaviCodeGenerator::emit_UNMI(RaviFunctionDef *def, int A, int B, int pc) {
- (void)pc;
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Instruction *lhs = emit_load_reg_i(def, rb);
- llvm::Value *result = def->builder->CreateNeg(lhs, "", false, true);
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) + RK(C), all floating
-void RaviCodeGenerator::emit_ADDFF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_ADDFF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFAdd(rb, rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) + RK(C), float+int
-void RaviCodeGenerator::emit_ADDFI(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_ADDFI, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result = def->builder->CreateFAdd(
- rb, def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) + RK(C), int+int
-void RaviCodeGenerator::emit_ADDII(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_ADDII, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result =
- def->builder->CreateAdd(rb, rc, "OP_RAVI_ADDII_result", false, true);
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) - RK(C), float-float
-void RaviCodeGenerator::emit_SUBFF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_SUBFF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFSub(rb, rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) - RK(C), float-int
-void RaviCodeGenerator::emit_SUBFI(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_SUBFI, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result = def->builder->CreateFSub(
- rb, def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) - RK(C), int-float
-void RaviCodeGenerator::emit_SUBIF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_SUBIF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFSub(
- def->builder->CreateSIToFP(rb, def->types->lua_NumberT), rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) - RK(C), int-int
-void RaviCodeGenerator::emit_SUBII(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_SUBII, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result =
- def->builder->CreateSub(rb, rc, "OP_RAVI_SUBII_result", false, true);
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) * RK(C), float*float
-void RaviCodeGenerator::emit_MULFF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_MULFF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFMul(rb, rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) * RK(C), float*int
-void RaviCodeGenerator::emit_MULFI(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_MULFI, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result = def->builder->CreateFMul(
- rb, def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) * RK(C), int*int
-void RaviCodeGenerator::emit_MULII(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_MULII, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result =
- def->builder->CreateMul(rb, rc, "OP_RAVI_MULII_result", false, true);
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) / RK(C), float/float
-void RaviCodeGenerator::emit_DIVFF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_DIVFF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFDiv(rb, rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) / RK(C), float/int
-void RaviCodeGenerator::emit_DIVFI(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_DIVFI, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_n(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result = def->builder->CreateFDiv(
- rb, def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) / RK(C), int/float
-void RaviCodeGenerator::emit_DIVIF(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_DIVIF, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_n(def, C);
- llvm::Value *result = def->builder->CreateFDiv(
- def->builder->CreateSIToFP(rb, def->types->lua_NumberT), rc);
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// R(A) := RK(B) / RK(C), int/int but result is float
-void RaviCodeGenerator::emit_DIVII(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- emit_debug_trace(def, OP_RAVI_DIVII, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *rc = emit_load_register_or_constant_i(def, C);
- llvm::Value *result = def->builder->CreateFDiv(
- def->builder->CreateSIToFP(rb, def->types->lua_NumberT),
- def->builder->CreateSIToFP(rc, def->types->lua_NumberT));
- emit_store_reg_n_withtype(def, result, ra);
-}
-
-// Bitwise AND, OR and XOR when both operands are known to be
-// integers
-void RaviCodeGenerator::emit_BITWISE_BINARY_OP(RaviFunctionDef *def, OpCode op,
- int A, int B, int C, int pc) {
- emit_debug_trace(def, op, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
-
- llvm::Value *lhs = emit_load_register_or_constant_i(def, B);
- llvm::Value *rhs = emit_load_register_or_constant_i(def, C);
-
- llvm::Value *result = NULL;
-
- switch (op) {
- case OP_RAVI_BAND_II:
- result = def->builder->CreateAnd(lhs, rhs, "OP_RAVI_BAND_II_result");
- break;
- case OP_RAVI_BOR_II:
- result = def->builder->CreateOr(lhs, rhs, "OP_RAVI_BOR_II_result");
- break;
- case OP_RAVI_BXOR_II:
- result = def->builder->CreateXor(lhs, rhs, "OP_RAVI_BXOR_II_result");
- break;
- default:
- fprintf(stderr, "unexpected value of opcode %d\n", (int)op);
- abort();
- }
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-/* number of bits in an integer */
-#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
-
-// Handle the case when we have a constant RHS and the LHS is an integer
-void RaviCodeGenerator::emit_bitwise_shiftl(RaviFunctionDef *def,
- llvm::Value *ra, int B,
- lua_Integer y) {
- if (y < 0) { /* shift right? */
- if (y <= -NBITS)
- emit_store_reg_i_withtype(
- def, llvm::ConstantInt::get(def->types->lua_IntegerT, 0), ra);
- else {
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *result = def->builder->CreateLShr(
- rb, llvm::ConstantInt::get(def->types->lua_IntegerT, -y));
- emit_store_reg_i_withtype(def, result, ra);
- }
- }
- else {
- if (y >= NBITS)
- emit_store_reg_i_withtype(
- def, llvm::ConstantInt::get(def->types->lua_IntegerT, 0), ra);
- else {
- llvm::Value *rb = emit_load_register_or_constant_i(def, B);
- llvm::Value *result = def->builder->CreateShl(
- rb, llvm::ConstantInt::get(def->types->lua_IntegerT, y));
- emit_store_reg_i_withtype(def, result, ra);
- }
- }
-}
-
-void RaviCodeGenerator::emit_BITWISE_SHIFT_OP(RaviFunctionDef *def, OpCode op,
- int A, int B, int C, int pc) {
- bool traced = emit_debug_trace(def, op, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
-
- // If the RHS is a constant and we know that LHS is
- // and integer then we can optimize the code generation
- if (op == OP_RAVI_SHL_II && ISK(C)) {
- lua_Integer y = def->p->k[INDEXK(C)].value_.i;
- emit_bitwise_shiftl(def, ra, B, y);
- }
- else if (op == OP_RAVI_SHR_II && ISK(C)) {
- lua_Integer y = def->p->k[INDEXK(C)].value_.i;
- emit_bitwise_shiftl(def, ra, B, -y);
- }
- else {
- // RHS is not a constant
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
-
- // Since the Lua OP_SHL and OP_SHR bytecodes
- // could invoke metamethods we need to set
- // 'savedpc'
- switch (op) {
- case OP_SHL:
- if (!traced) emit_update_savedpc(def, pc);
- case OP_RAVI_SHL_II:
- CreateCall4(def->builder, def->raviV_op_shlF, def->L, ra, rb, rc);
- break;
- case OP_SHR:
- if (!traced) emit_update_savedpc(def, pc);
- case OP_RAVI_SHR_II:
- CreateCall4(def->builder, def->raviV_op_shrF, def->L, ra, rb, rc);
- break;
- default:
- fprintf(stderr, "unexpected value of opcode %d\n", (int)op);
- abort();
- }
- }
-}
-
-// R(A) := ~R(B); known integer operand
-void RaviCodeGenerator::emit_BNOT_I(RaviFunctionDef *def, int A, int B,
- int pc) {
- emit_debug_trace(def, OP_RAVI_BNOT_I, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *lhs = emit_load_register_or_constant_i(def, B);
- llvm::Value *rhs = llvm::ConstantInt::get(def->types->lua_IntegerT, -1);
- llvm::Value *result = def->builder->CreateXor(lhs, rhs, "");
- emit_store_reg_i_withtype(def, result, ra);
-}
-
-void RaviCodeGenerator::emit_BOR_BXOR_BAND(RaviFunctionDef *def, OpCode op,
- int A, int B, int C, int pc) {
- bool traced = emit_debug_trace(def, op, pc);
- // Below may invoke metamethod so we set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
- CreateCall4(def->builder,
- op == OP_BOR
- ? def->raviV_op_borF
- : (op == OP_BAND ? def->raviV_op_bandF : def->raviV_op_bxorF),
- def->L, ra, rb, rc);
-}
-
-void RaviCodeGenerator::emit_BNOT(RaviFunctionDef *def, int A, int B, int pc) {
- bool traced = emit_debug_trace(def, OP_BNOT, pc);
- // Below may invoke metamethod so we set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register(def, B);
- CreateCall3(def->builder, def->raviV_op_bnotF, def->L, ra, rb);
-}
-}
\ No newline at end of file
diff --git a/src/ravi_llvmarith2.cpp b/src/ravi_llvmarith2.cpp
deleted file mode 100644
index 130d0db..0000000
--- a/src/ravi_llvmarith2.cpp
+++ /dev/null
@@ -1,1145 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-// This file contains LLVM IR generation for standard Lua arithmetic op codes
-
-namespace ravi {
-
-// OP_ADD, OP_SUB, OP_MUL and OP_DIV
-// Code size priority so go via function calls
-void RaviCodeGenerator::emit_ARITH_calls(RaviFunctionDef *def, int A, int B,
- int C, OpCode op, TMS tms, int pc) {
- emit_debug_trace(def, op, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
- switch (op) {
- case OP_ADD:
- CreateCall4(def->builder, def->raviV_op_addF, def->L, ra, rb, rc);
- break;
- case OP_SUB:
- CreateCall4(def->builder, def->raviV_op_subF, def->L, ra, rb, rc);
- break;
- case OP_MUL:
- CreateCall4(def->builder, def->raviV_op_mulF, def->L, ra, rb, rc);
- break;
- case OP_DIV:
- CreateCall4(def->builder, def->raviV_op_divF, def->L, ra, rb, rc);
- break;
- default: lua_assert(0);
- }
-}
-
-// OP_ADD, OP_SUB, OP_MUL and OP_DIV
-void RaviCodeGenerator::emit_ARITH_intpriority(RaviFunctionDef *def, int A,
- int B, int C, OpCode op, TMS tms,
- int pc) {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // lua_Number nb; lua_Number nc;
- // if (ttisinteger(rb) && ttisinteger(rc)) {
- // lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- // setivalue(ra, intop(+, ib, ic));
- //}
- // else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- // setfltvalue(ra, luai_numadd(L, nb, nc));
- //}
- // else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *nb = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nb");
- llvm::Value *nc = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nc");
-
- bool traced = emit_debug_trace(def, op, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
- llvm::Value *rc_type = emit_load_type(def, rc);
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *try_meta =
- llvm::BasicBlock::Create(def->jitState->context(), "try_meta");
- llvm::BasicBlock *done_block =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
-
- if (op != OP_DIV) {
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMINT, "rb.is.integer");
- llvm::Value *cmp2 =
- emit_is_value_of_type(def, rc_type, LUA__TNUMINT, "rc.is.integer");
-
- llvm::Value *andvalue = def->builder->CreateAnd(cmp1, cmp2);
-
- // Check if both RB and RC are integers
- llvm::BasicBlock *then_block = llvm::BasicBlock::Create(
- def->jitState->context(), "if.integer", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.integer");
- def->builder->CreateCondBr(andvalue, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Both are integers
- llvm::Instruction *lhs = emit_load_reg_i(def, rb);
- llvm::Instruction *rhs = emit_load_reg_i(def, rc);
-
- llvm::Value *result = nullptr;
- switch (op) {
- case OP_ADD:
- result = def->builder->CreateAdd(lhs, rhs, "", false, true);
- break;
- case OP_SUB:
- result = def->builder->CreateSub(lhs, rhs, "", false, true);
- break;
- case OP_MUL:
- result = def->builder->CreateMul(lhs, rhs, "", false, true);
- break;
- default: lua_assert(0);
- }
-
- emit_store_reg_i_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Not integer
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
- }
-
- // Is RB a float?
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *convert_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rb");
- llvm::BasicBlock *test_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "test.rc");
- llvm::BasicBlock *load_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rb");
-
- // If RB is floating then load RB, else convert RB
- auto brinst1 = def->builder->CreateCondBr(cmp1, load_rb, convert_rb);
- attach_branch_weights(def, brinst1, 100, 0);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_rb);
- def->builder->SetInsertPoint(convert_rb);
-
- // Call luaV_tonumber_()
- llvm::Value *rb_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rb, nb);
- cmp1 =
- def->builder->CreateICmpEQ(rb_isnum, def->types->kInt[1], "rb.float.ok");
-
- // If not number then go to meta block
- // Else proceed to test RC
- def->builder->CreateCondBr(cmp1, test_rc, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rb);
- def->builder->SetInsertPoint(load_rb);
-
- // Copy RB to local nb
- auto src = emit_load_reg_n(def, rb);
- emit_store_local_n(def, src, nb);
-
- def->builder->CreateBr(test_rc);
-
- def->f->getBasicBlockList().push_back(test_rc);
- def->builder->SetInsertPoint(test_rc);
-
- // Is RC a float?
- cmp1 = emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rc.is.float");
-
- llvm::BasicBlock *convert_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rc");
- llvm::BasicBlock *load_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rc");
-
- // If RC is float load RC
- // else try to convert RC
- auto brinst2 = def->builder->CreateCondBr(cmp1, load_rc, convert_rc);
- attach_branch_weights(def, brinst2, 100, 0);
-
- def->f->getBasicBlockList().push_back(convert_rc);
- def->builder->SetInsertPoint(convert_rc);
-
- // Call luaV_tonumber_()
- llvm::Value *rc_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rc, nc);
- cmp1 =
- def->builder->CreateICmpEQ(rc_isnum, def->types->kInt[1], "rc.float.ok");
-
- // If not number then go to meta block
- // else both RB and RC float so go to op
- def->builder->CreateCondBr(cmp1, float_op, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rc);
- def->builder->SetInsertPoint(load_rc);
-
- // Copy RC to local;
- src = emit_load_reg_n(def, rc);
- emit_store_local_n(def, src, nc);
-
- def->builder->CreateBr(float_op);
-
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- llvm::Instruction *lhs = emit_load_local_n(def, nb);
- llvm::Instruction *rhs = emit_load_local_n(def, nc);
-
- llvm::Value *result = nullptr;
- // Add and set RA
- switch (op) {
- case OP_ADD: result = def->builder->CreateFAdd(lhs, rhs); break;
- case OP_SUB: result = def->builder->CreateFSub(lhs, rhs); break;
- case OP_MUL: result = def->builder->CreateFMul(lhs, rhs); break;
- case OP_DIV: result = def->builder->CreateFDiv(lhs, rhs); break;
- default: lua_assert(0);
- }
-
- emit_store_reg_n_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Neither integer nor float so try meta
- def->f->getBasicBlockList().push_back(try_meta);
- def->builder->SetInsertPoint(try_meta);
-
- // Before invoking metamethod set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- CreateCall5(def->builder, def->luaT_trybinTMF, def->L, rb, rc, ra,
- def->types->kInt[tms]);
- def->builder->CreateBr(done_block);
-
- def->f->getBasicBlockList().push_back(done_block);
- def->builder->SetInsertPoint(done_block);
-}
-
-// OP_ADD, OP_SUB, OP_MUL and OP_DIV
-// This version prioritizes floating point arith over integer arith
-// Also slow path is slower as it goes via function calls
-void RaviCodeGenerator::emit_ARITH_floatpriority(RaviFunctionDef *def, int A,
- int B, int C, OpCode op,
- TMS tms, int pc) {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // lua_Number nb; lua_Number nc;
- // if (ttisfloat(rb)) {
- // if (ttisfloat(rc)) {
- // nb = fltvalue(rb); nc = fltvalue(rc);
- // setfltvalue(ra, luai_numadd(L, nb, nc));
- // }
- // else if (ttisinteger(rc)) {
- // nb = fltvalue(rb); nc = cast_num(ivalue(rc));
- // setfltvalue(ra, luai_numadd(L, nb, nc));
- // }
- // else slowpath
- //}
- // else if (ttisinteger(rb)) {
- // if (ttisfloat(rc)) {
- // nb = cast_num(ivalue(rb)); nc = fltvalue(rc);
- // setfltvalue(ra, luai_numadd(L, nb, nc));
- // }
- // else if (ttisinteger(rc)) {
- // lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- // setivalue(ra, intop(+, ib, ic));
- // }
- // else slowpath
- // else slowpath
-
- bool traced = emit_debug_trace(def, op, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
- llvm::Value *rc_type = emit_load_type(def, rc);
-
- // PART A - Is RB floating?
-
- llvm::Value *rb_is_float =
- emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *done =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
- llvm::BasicBlock *slowpath =
- llvm::BasicBlock::Create(def->jitState->context(), "slowpath");
-
- llvm::BasicBlock *check_rc_is_float =
- llvm::BasicBlock::Create(def->jitState->context(), "check.rc.is.float");
- llvm::BasicBlock *check_rb_is_int =
- llvm::BasicBlock::Create(def->jitState->context(), "check.rb.is.int");
-
- // If RB is floating, check RC else check RB is int
- auto brinst1 = def->builder->CreateCondBr(rb_is_float, check_rc_is_float,
- check_rb_is_int);
- attach_branch_weights(def, brinst1, 5, 2);
-
- // Check if rc is float
- def->f->getBasicBlockList().push_back(check_rc_is_float);
- def->builder->SetInsertPoint(check_rc_is_float);
-
- llvm::Value *rc_is_float =
- emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rb.float.is.rc.float");
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *rb_float_check_rc_is_int = llvm::BasicBlock::Create(
- def->jitState->context(), "rb.float.check.rc.int");
-
- // RB is floating - so check if RC is floating
- auto brinst2 = def->builder->CreateCondBr(rc_is_float, float_op,
- rb_float_check_rc_is_int);
- attach_branch_weights(def, brinst2, 10, 3);
-
- // Both rb and rc are floats
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- llvm::Instruction *lhs = emit_load_reg_n(def, rb);
- llvm::Instruction *rhs = emit_load_reg_n(def, rc);
-
- llvm::Value *result = nullptr;
- // Add and set RA
- switch (op) {
- case OP_ADD: result = def->builder->CreateFAdd(lhs, rhs); break;
- case OP_SUB: result = def->builder->CreateFSub(lhs, rhs); break;
- case OP_MUL: result = def->builder->CreateFMul(lhs, rhs); break;
- case OP_DIV: result = def->builder->CreateFDiv(lhs, rhs); break;
- default: lua_assert(0);
- }
- emit_store_reg_n_withtype(def, result, ra);
-
- // We are done
- def->builder->CreateBr(done);
-
- // RB is float - but RC is not, so check if RC is int
- def->f->getBasicBlockList().push_back(rb_float_check_rc_is_int);
- def->builder->SetInsertPoint(rb_float_check_rc_is_int);
-
- llvm::Value *rb_float_is_rc_int =
- emit_is_value_of_type(def, rc_type, LUA__TNUMINT, "rb.float.is.rc.int");
-
- llvm::BasicBlock *float_int_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.int.op");
-
- // RB is floating, check if RC in int
- auto brinst3 =
- def->builder->CreateCondBr(rb_float_is_rc_int, float_int_op, slowpath);
- attach_branch_weights(def, brinst3, 100, 0);
-
- // RB is float - but RC is int
- def->f->getBasicBlockList().push_back(float_int_op);
- def->builder->SetInsertPoint(float_int_op);
-
- lhs = emit_load_reg_n(def, rb);
- rhs = emit_load_reg_i(def, rc);
-
- result = nullptr;
- // Add and set RA
- switch (op) {
- case OP_ADD:
- result = def->builder->CreateFAdd(
- lhs, def->builder->CreateSIToFP(rhs, def->types->lua_NumberT));
- break;
- case OP_SUB:
- result = def->builder->CreateFSub(
- lhs, def->builder->CreateSIToFP(rhs, def->types->lua_NumberT));
- break;
- case OP_MUL:
- result = def->builder->CreateFMul(
- lhs, def->builder->CreateSIToFP(rhs, def->types->lua_NumberT));
- break;
- case OP_DIV:
- result = def->builder->CreateFDiv(
- lhs, def->builder->CreateSIToFP(rhs, def->types->lua_NumberT));
- break;
- default: lua_assert(0);
- }
- emit_store_reg_n_withtype(def, result, ra);
-
- // We are done
- def->builder->CreateBr(done);
-
- // PART B - This section starts by checking whether RB is integer
-
- def->f->getBasicBlockList().push_back(check_rb_is_int);
- def->builder->SetInsertPoint(check_rb_is_int);
-
- llvm::Value *rb_is_int =
- emit_is_value_of_type(def, rb_type, LUA__TNUMINT, "rb.is.integer");
-
- llvm::BasicBlock *rb_int_check_rc_int =
- llvm::BasicBlock::Create(def->jitState->context(), "rb.int.check.rc.int");
- llvm::BasicBlock *rb_int_check_rc_float = llvm::BasicBlock::Create(
- def->jitState->context(), "rb.int.check.rc.float");
-
- // Check if RB is INT
- auto brinst4 =
- def->builder->CreateCondBr(rb_is_int, rb_int_check_rc_int, slowpath);
- attach_branch_weights(def, brinst4, 100, 0);
-
- // RB is int, check if RC is also int
- def->f->getBasicBlockList().push_back(rb_int_check_rc_int);
- def->builder->SetInsertPoint(rb_int_check_rc_int);
-
- llvm::Value *rb_int_is_rc_int =
- emit_is_value_of_type(def, rc_type, LUA__TNUMINT, "rb.int.is.rc.int");
-
- llvm::BasicBlock *int_int_op =
- llvm::BasicBlock::Create(def->jitState->context(), "int.int.op");
-
- // Check if RC is INT
- auto brinst5 = def->builder->CreateCondBr(rb_int_is_rc_int, int_int_op,
- rb_int_check_rc_float);
- attach_branch_weights(def, brinst5, 10, 3);
-
- // RB is int, RC int
- def->f->getBasicBlockList().push_back(int_int_op);
- def->builder->SetInsertPoint(int_int_op);
-
- // Both are integers
- lhs = emit_load_reg_i(def, rb);
- rhs = emit_load_reg_i(def, rc);
-
- result = nullptr;
- switch (op) {
- case OP_ADD:
- result = def->builder->CreateAdd(lhs, rhs, "", false, true);
- break;
- case OP_SUB:
- result = def->builder->CreateSub(lhs, rhs, "", false, true);
- break;
- case OP_MUL:
- result = def->builder->CreateMul(lhs, rhs, "", false, true);
- break;
- case OP_DIV:
- result = def->builder->CreateFDiv(
- def->builder->CreateSIToFP(lhs, def->types->lua_NumberT),
- def->builder->CreateSIToFP(rhs, def->types->lua_NumberT));
- break;
- default: lua_assert(0);
- }
-
- if (op != OP_DIV)
- emit_store_reg_i_withtype(def, result, ra);
- else
- emit_store_reg_n_withtype(def, result, ra);
-
- def->builder->CreateBr(done);
-
- // RB is int, check if RC is float
- def->f->getBasicBlockList().push_back(rb_int_check_rc_float);
- def->builder->SetInsertPoint(rb_int_check_rc_float);
-
- llvm::Value *rb_int_is_rc_float =
- emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rb.int.is.rc.float");
-
- llvm::BasicBlock *int_float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "int.float.op");
-
- // RB is int, check if RC is float
- auto brinst6 =
- def->builder->CreateCondBr(rb_int_is_rc_float, int_float_op, slowpath);
- attach_branch_weights(def, brinst6, 100, 0);
-
- // RB is int, RC is float
- def->f->getBasicBlockList().push_back(int_float_op);
- def->builder->SetInsertPoint(int_float_op);
-
- lhs = emit_load_reg_i(def, rb);
- rhs = emit_load_reg_n(def, rc);
-
- result = nullptr;
- // Add and set RA
- switch (op) {
- case OP_ADD:
- result = def->builder->CreateFAdd(
- def->builder->CreateSIToFP(lhs, def->types->lua_NumberT), rhs);
- break;
- case OP_SUB:
- result = def->builder->CreateFSub(
- def->builder->CreateSIToFP(lhs, def->types->lua_NumberT), rhs);
- break;
- case OP_MUL:
- result = def->builder->CreateFMul(
- def->builder->CreateSIToFP(lhs, def->types->lua_NumberT), rhs);
- break;
- case OP_DIV:
- result = def->builder->CreateFDiv(
- def->builder->CreateSIToFP(lhs, def->types->lua_NumberT), rhs);
- break;
- default: lua_assert(0);
- }
- emit_store_reg_n_withtype(def, result, ra);
-
- // We are done
- def->builder->CreateBr(done);
-
- def->f->getBasicBlockList().push_back(slowpath);
- def->builder->SetInsertPoint(slowpath);
-
- // Set savedpc as following may invoke metamethod
- if (!traced) emit_update_savedpc(def, pc);
-
- switch (op) {
- case OP_ADD:
- CreateCall4(def->builder, def->raviV_op_addF, def->L, ra, rb, rc);
- break;
- case OP_SUB:
- CreateCall4(def->builder, def->raviV_op_subF, def->L, ra, rb, rc);
- break;
- case OP_MUL:
- CreateCall4(def->builder, def->raviV_op_mulF, def->L, ra, rb, rc);
- break;
- case OP_DIV:
- CreateCall4(def->builder, def->raviV_op_divF, def->L, ra, rb, rc);
- break;
- default: lua_assert(0);
- }
-
- def->builder->CreateBr(done);
-
- def->f->getBasicBlockList().push_back(done);
- def->builder->SetInsertPoint(done);
-}
-
-// OP_MOD
-void RaviCodeGenerator::emit_MOD(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // lua_Number nb; lua_Number nc;
- // if (ttisinteger(rb) && ttisinteger(rc)) {
- // lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- // setivalue(ra, luaV_mod(L, ib, ic));
- //}
- // else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- // lua_Number m;
- // luai_nummod(L, nb, nc, m);
- // setfltvalue(ra, m);
- //}
- // else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *nb = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nb");
- llvm::Value *nc = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nc");
-
- bool traced = emit_debug_trace(def, OP_MOD, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
- llvm::Value *rc_type = emit_load_type(def, rc);
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *try_meta =
- llvm::BasicBlock::Create(def->jitState->context(), "try_meta");
- llvm::BasicBlock *done_block =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
-
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMINT, "rb.is.integer");
- llvm::Value *cmp2 =
- emit_is_value_of_type(def, rc_type, LUA__TNUMINT, "rc.is.integer");
-
- llvm::Value *andvalue = def->builder->CreateAnd(cmp1, cmp2);
-
- // Check if both RB and RC are integers
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.integer", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.integer");
- def->builder->CreateCondBr(andvalue, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Both are integers
- llvm::Instruction *lhs = emit_load_reg_i(def, rb);
- llvm::Instruction *rhs = emit_load_reg_i(def, rc);
-
- llvm::Value *result =
- CreateCall3(def->builder, def->luaV_modF, def->L, lhs, rhs);
- emit_store_reg_i_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Not integer
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-
- // Is RB a float?
- cmp1 = emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *convert_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rb");
- llvm::BasicBlock *test_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "test.rc");
- llvm::BasicBlock *load_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rb");
-
- // If RB is floating then load RB, else convert RB
- def->builder->CreateCondBr(cmp1, load_rb, convert_rb);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_rb);
- def->builder->SetInsertPoint(convert_rb);
-
- // Call luaV_tonumber_()
- llvm::Value *rb_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rb, nb);
- cmp1 =
- def->builder->CreateICmpEQ(rb_isnum, def->types->kInt[1], "rb.float.ok");
-
- // If not number then go to meta block
- // Else proceed to test RC
- def->builder->CreateCondBr(cmp1, test_rc, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rb);
- def->builder->SetInsertPoint(load_rb);
-
- // Copy RB to local nb
- auto src = emit_load_reg_n(def, rb);
- emit_store_local_n(def, src, nb);
-
- def->builder->CreateBr(test_rc);
-
- def->f->getBasicBlockList().push_back(test_rc);
- def->builder->SetInsertPoint(test_rc);
-
- // Is RC a float?
- cmp1 = emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rc.is.float");
-
- llvm::BasicBlock *convert_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rc");
- llvm::BasicBlock *load_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rc");
-
- // If RC is float load RC
- // else try to convert RC
- def->builder->CreateCondBr(cmp1, load_rc, convert_rc);
-
- def->f->getBasicBlockList().push_back(convert_rc);
- def->builder->SetInsertPoint(convert_rc);
-
- // Call luaV_tonumber_()
- llvm::Value *rc_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rc, nc);
- cmp1 =
- def->builder->CreateICmpEQ(rc_isnum, def->types->kInt[1], "rc.float.ok");
-
- // If not number then go to meta block
- // else both RB and RC float so go to op
- def->builder->CreateCondBr(cmp1, float_op, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rc);
- def->builder->SetInsertPoint(load_rc);
-
- // Copy RC to local;
- src = emit_load_reg_n(def, rc);
- emit_store_local_n(def, src, nc);
-
- def->builder->CreateBr(float_op);
-
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- lhs = emit_load_local_n(def, nb);
- rhs = emit_load_local_n(def, nc);
-
-#if LLVM_VERSION_MAJOR >= 9
- llvm::Value *fmod_result = CreateCall2(def->builder, def->fmodFunc.getCallee(), lhs, rhs);
-#else
- llvm::Value *fmod_result = CreateCall2(def->builder, def->fmodFunc, lhs, rhs);
-#endif
-
- // if ((m)*(b) < 0) (m) += (b);
- llvm::Value *mb = def->builder->CreateFMul(fmod_result, rhs);
-
- // If m*b < 0
- cmp1 = def->builder->CreateFCmpOLT(
- mb, llvm::ConstantFP::get(def->types->lua_NumberT, 0.0));
- llvm::BasicBlock *mb_lt0_then =
- llvm::BasicBlock::Create(def->jitState->context(), "mb.lt.zero", def->f);
- llvm::BasicBlock *mb_lt0_else =
- llvm::BasicBlock::Create(def->jitState->context(), "mb.not.lt.zero");
- llvm::BasicBlock *mb_lt0_done =
- llvm::BasicBlock::Create(def->jitState->context(), "mb.not.lt.end");
-
- def->builder->CreateCondBr(cmp1, mb_lt0_then, mb_lt0_else);
- def->builder->SetInsertPoint(mb_lt0_then);
-
- result = def->builder->CreateFAdd(fmod_result, rhs);
- emit_store_local_n(def, result, nb);
- def->builder->CreateBr(mb_lt0_done);
-
- def->f->getBasicBlockList().push_back(mb_lt0_else);
- def->builder->SetInsertPoint(mb_lt0_else);
-
- emit_store_local_n(def, fmod_result, nb);
- def->builder->CreateBr(mb_lt0_done);
-
- def->f->getBasicBlockList().push_back(mb_lt0_done);
- def->builder->SetInsertPoint(mb_lt0_done);
-
- lhs = emit_load_local_n(def, nb);
-
- emit_store_reg_n_withtype(def, lhs, ra);
-
- def->builder->CreateBr(done_block);
-
- // Neither integer nor float so try meta
- def->f->getBasicBlockList().push_back(try_meta);
- def->builder->SetInsertPoint(try_meta);
-
- // before invoking metamethod set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- CreateCall5(def->builder, def->luaT_trybinTMF, def->L, rb, rc, ra,
- def->types->kInt[TM_MOD]);
- def->builder->CreateBr(done_block);
-
- def->f->getBasicBlockList().push_back(done_block);
- def->builder->SetInsertPoint(done_block);
-}
-
-// OP_IDIV
-void RaviCodeGenerator::emit_IDIV(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // lua_Number nb; lua_Number nc;
- // if (ttisinteger(rb) && ttisinteger(rc)) {
- // lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
- // setivalue(ra, luaV_idiv(L, ib, ic));
- //}
- // else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- // setfltvalue(ra, luai_numidiv(L, nb, nc));
- //}
- // else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *nb = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nb");
- llvm::Value *nc = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nc");
-
- bool traced = emit_debug_trace(def, OP_IDIV, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
- llvm::Value *rc_type = emit_load_type(def, rc);
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *try_meta =
- llvm::BasicBlock::Create(def->jitState->context(), "try_meta");
- llvm::BasicBlock *done_block =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
-
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMINT, "rb.is.integer");
- llvm::Value *cmp2 =
- emit_is_value_of_type(def, rc_type, LUA__TNUMINT, "rc.is.integer");
-
- llvm::Value *andvalue = def->builder->CreateAnd(cmp1, cmp2);
-
- // Check if both RB and RC are integers
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.integer", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.integer");
- def->builder->CreateCondBr(andvalue, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Both are integers
- llvm::Instruction *lhs = emit_load_reg_i(def, rb);
- llvm::Instruction *rhs = emit_load_reg_i(def, rc);
-
- llvm::Value *result =
- CreateCall3(def->builder, def->luaV_idivF, def->L, lhs, rhs);
- emit_store_reg_i_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Not integer
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-
- // Is RB a float?
- cmp1 = emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *convert_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rb");
- llvm::BasicBlock *test_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "test.rc");
- llvm::BasicBlock *load_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rb");
-
- // If RB is floating then load RB, else convert RB
- def->builder->CreateCondBr(cmp1, load_rb, convert_rb);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_rb);
- def->builder->SetInsertPoint(convert_rb);
-
- // Call luaV_tonumber_()
- llvm::Value *rb_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rb, nb);
- cmp1 =
- def->builder->CreateICmpEQ(rb_isnum, def->types->kInt[1], "rb.float.ok");
-
- // If not number then go to meta block
- // Else proceed to test RC
- def->builder->CreateCondBr(cmp1, test_rc, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rb);
- def->builder->SetInsertPoint(load_rb);
-
- // Copy RB to local nb
- auto src = emit_load_reg_n(def, rb);
- emit_store_local_n(def, src, nb);
-
- def->builder->CreateBr(test_rc);
-
- def->f->getBasicBlockList().push_back(test_rc);
- def->builder->SetInsertPoint(test_rc);
-
- // Is RC a float?
- cmp1 = emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rc.is.float");
-
- llvm::BasicBlock *convert_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rc");
- llvm::BasicBlock *load_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rc");
-
- // If RC is float load RC
- // else try to convert RC
- def->builder->CreateCondBr(cmp1, load_rc, convert_rc);
-
- def->f->getBasicBlockList().push_back(convert_rc);
- def->builder->SetInsertPoint(convert_rc);
-
- // Call luaV_tonumber_()
- llvm::Value *rc_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rc, nc);
- cmp1 =
- def->builder->CreateICmpEQ(rc_isnum, def->types->kInt[1], "rc.float.ok");
-
- // If not number then go to meta block
- // else both RB and RC float so go to op
- def->builder->CreateCondBr(cmp1, float_op, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rc);
- def->builder->SetInsertPoint(load_rc);
-
- // Copy RC to local;
- src = emit_load_reg_n(def, rc);
- emit_store_local_n(def, src, nc);
-
- def->builder->CreateBr(float_op);
-
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- lhs = emit_load_local_n(def, nb);
- rhs = emit_load_local_n(def, nc);
-
- result = def->builder->CreateFDiv(lhs, rhs);
- llvm::Value *floor_result = def->builder->CreateCall(def->floorFunc, result);
-
- emit_store_reg_n_withtype(def, floor_result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Neither integer nor float so try meta
- def->f->getBasicBlockList().push_back(try_meta);
- def->builder->SetInsertPoint(try_meta);
-
- // before invoking metamethod set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- CreateCall5(def->builder, def->luaT_trybinTMF, def->L, rb, rc, ra,
- def->types->kInt[TM_IDIV]);
- def->builder->CreateBr(done_block);
-
- def->f->getBasicBlockList().push_back(done_block);
- def->builder->SetInsertPoint(done_block);
-}
-
-// OP_POW
-void RaviCodeGenerator::emit_POW(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // lua_Number nb; lua_Number nc;
- // if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
- // setfltvalue(ra, luai_numpow(L, nb, nc));
- //}
- // else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *nb = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nb");
- llvm::Value *nc = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nc");
-
- bool traced = emit_debug_trace(def, OP_POW, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- llvm::Value *rc = emit_gep_register_or_constant(def, C);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
- llvm::Value *rc_type = emit_load_type(def, rc);
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *try_meta =
- llvm::BasicBlock::Create(def->jitState->context(), "try_meta");
- llvm::BasicBlock *done_block =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
-
- // Is RB a float?
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *convert_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rb");
- llvm::BasicBlock *test_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "test.rc");
- llvm::BasicBlock *load_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rb");
-
- // If RB is floating then load RB, else convert RB
- def->builder->CreateCondBr(cmp1, load_rb, convert_rb);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_rb);
- def->builder->SetInsertPoint(convert_rb);
-
- // Call luaV_tonumber_()
- llvm::Value *rb_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rb, nb);
- cmp1 =
- def->builder->CreateICmpEQ(rb_isnum, def->types->kInt[1], "rb.float.ok");
-
- // If not number then go to meta block
- // Else proceed to test RC
- def->builder->CreateCondBr(cmp1, test_rc, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rb);
- def->builder->SetInsertPoint(load_rb);
-
- // Copy RB to local nb
- auto src = emit_load_reg_n(def, rb);
- emit_store_local_n(def, src, nb);
-
- def->builder->CreateBr(test_rc);
-
- def->f->getBasicBlockList().push_back(test_rc);
- def->builder->SetInsertPoint(test_rc);
-
- // Is RC a float?
- cmp1 = emit_is_value_of_type(def, rc_type, LUA__TNUMFLT, "rc.is.float");
-
- llvm::BasicBlock *convert_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rc");
- llvm::BasicBlock *load_rc =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rc");
-
- // If RC is float load RC
- // else try to convert RC
- def->builder->CreateCondBr(cmp1, load_rc, convert_rc);
-
- def->f->getBasicBlockList().push_back(convert_rc);
- def->builder->SetInsertPoint(convert_rc);
-
- // Call luaV_tonumber_()
- llvm::Value *rc_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rc, nc);
- cmp1 =
- def->builder->CreateICmpEQ(rc_isnum, def->types->kInt[1], "rc.float.ok");
-
- // If not number then go to meta block
- // else both RB and RC float so go to op
- def->builder->CreateCondBr(cmp1, float_op, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rc);
- def->builder->SetInsertPoint(load_rc);
-
- // Copy RC to local;
- src = emit_load_reg_n(def, rc);
- emit_store_local_n(def, src, nc);
-
- def->builder->CreateBr(float_op);
-
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- llvm::Instruction *lhs = emit_load_local_n(def, nb);
- llvm::Instruction *rhs = emit_load_local_n(def, nc);
-
-#if LLVM_VERSION_MAJOR >= 9
- llvm::Value *pow_result = CreateCall2(def->builder, def->powFunc.getCallee(), lhs, rhs);
-#else
- llvm::Value *pow_result = CreateCall2(def->builder, def->powFunc, lhs, rhs);
-#endif
-
- emit_store_reg_n_withtype(def, pow_result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Neither integer nor float so try meta
- def->f->getBasicBlockList().push_back(try_meta);
- def->builder->SetInsertPoint(try_meta);
-
- // Before invoking metamethod set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- CreateCall5(def->builder, def->luaT_trybinTMF, def->L, rb, rc, ra,
- def->types->kInt[TM_POW]);
- def->builder->CreateBr(done_block);
-
- def->f->getBasicBlockList().push_back(done_block);
- def->builder->SetInsertPoint(done_block);
-}
-
-void RaviCodeGenerator::emit_UNM(RaviFunctionDef *def, int A, int B, int pc) {
- // TValue *rb = RB(i);
- // lua_Number nb;
- // if (ttisinteger(rb)) {
- // lua_Integer ib = ivalue(rb);
- // setivalue(ra, intop(-, 0, ib));
- //}
- // else if (tonumber(rb, &nb)) {
- // setfltvalue(ra, luai_numunm(L, nb));
- //}
- // else {
- // Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
- //}
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *nb = TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nb");
-
- bool traced = emit_debug_trace(def, OP_UNM, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
-
- llvm::Value *rb_type = emit_load_type(def, rb);
-
- llvm::BasicBlock *float_op =
- llvm::BasicBlock::Create(def->jitState->context(), "float.op");
- llvm::BasicBlock *try_meta =
- llvm::BasicBlock::Create(def->jitState->context(), "try_meta");
- llvm::BasicBlock *done_block =
- llvm::BasicBlock::Create(def->jitState->context(), "done");
-
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rb_type, LUA__TNUMINT, "rb.is.integer");
-
- // Check if both RB and RC are integers
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.integer", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.integer");
- def->builder->CreateCondBr(cmp1, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Both are integers
- llvm::Instruction *lhs = emit_load_reg_i(def, rb);
- llvm::Value *result = def->builder->CreateNeg(lhs, "", false, true);
-
- emit_store_reg_i_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Not integer
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-
- // Is RB a float?
- cmp1 = emit_is_value_of_type(def, rb_type, LUA__TNUMFLT, "rb.is.float");
-
- llvm::BasicBlock *convert_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.rb");
- llvm::BasicBlock *load_rb =
- llvm::BasicBlock::Create(def->jitState->context(), "load.rb");
-
- // If RB is floating then load RB, else convert RB
- def->builder->CreateCondBr(cmp1, load_rb, convert_rb);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_rb);
- def->builder->SetInsertPoint(convert_rb);
-
- // Call luaV_tonumber_()
- llvm::Value *rb_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, rb, nb);
- cmp1 =
- def->builder->CreateICmpEQ(rb_isnum, def->types->kInt[1], "rb.float.ok");
-
- // If not number then go to meta block
- // Else proceed to test RC
- def->builder->CreateCondBr(cmp1, float_op, try_meta);
-
- def->f->getBasicBlockList().push_back(load_rb);
- def->builder->SetInsertPoint(load_rb);
-
- // Copy RB to local nb
- auto src = emit_load_reg_n(def, rb);
- emit_store_local_n(def, src, nb);
-
- def->builder->CreateBr(float_op);
-
- def->f->getBasicBlockList().push_back(float_op);
- def->builder->SetInsertPoint(float_op);
-
- lhs = emit_load_local_n(def, nb);
-
- result = def->builder->CreateFNeg(lhs);
-
- emit_store_reg_n_withtype(def, result, ra);
-
- def->builder->CreateBr(done_block);
-
- // Neither integer nor float so try meta
- def->f->getBasicBlockList().push_back(try_meta);
- def->builder->SetInsertPoint(try_meta);
-
- // before invoking metamethod set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- CreateCall5(def->builder, def->luaT_trybinTMF, def->L, rb, rb, ra,
- def->types->kInt[TM_UNM]);
- def->builder->CreateBr(done_block);
-
- def->f->getBasicBlockList().push_back(done_block);
- def->builder->SetInsertPoint(done_block);
-}
-}
\ No newline at end of file
diff --git a/src/ravi_llvmcall.cpp b/src/ravi_llvmcall.cpp
deleted file mode 100644
index aa52b50..0000000
--- a/src/ravi_llvmcall.cpp
+++ /dev/null
@@ -1,189 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-namespace ravi {
-
-// OP_JMP
-void RaviCodeGenerator::emit_JMP(RaviFunctionDef *def, int A, int sBx, int pc) {
-
- //#define dojump(ci,i,e)
- // { int a = GETARG_A(i);
- // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
- // ci->u.l.savedpc += GETARG_sBx(i) + e; }
- //
- // dojump(ci, i, 0);
-
- assert(def->jmp_targets[sBx].jmp1);
-
- // If the current block is already terminated we
- // need to create a new block
- if (def->builder->GetInsertBlock()->getTerminator()) {
- llvm::BasicBlock *jmp_block = llvm::BasicBlock::Create(
- def->jitState->context(), "OP_JMP_bridge", def->f);
- def->builder->SetInsertPoint(jmp_block);
- }
-
- bool traced = emit_debug_trace(def, OP_JMP, pc);
-
- // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
- if (A > 0) {
- emit_load_base(def);
- // base + a - 1
- llvm::Value *val = emit_gep_register(def, A - 1);
-#ifdef RAVI_DEFER_STATEMENT
- if (!traced)
- emit_update_savedpc(def, pc);
- // Call luaF_close
- CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
-#else
- CreateCall2(def->builder, def->luaF_closeF, def->L, val);
-#endif
- }
-
- // Do the actual jump
- def->builder->CreateBr(def->jmp_targets[sBx].jmp1);
-
- // Start new block
- llvm::BasicBlock *block = llvm::BasicBlock::Create(def->jitState->context(),
- "OP_JMP_postjmp", def->f);
- def->builder->SetInsertPoint(block);
-}
-
-// Handle OP_CALL
-// Note that Lua assumes that functions called via OP_CALL
-// are Lua functions and secondly that once OP_CALL completes the
-// current function will continue within the same luaV_execute()
-// call. However in a JIT case each JIT function is a different call
-// so we need to take care of the behaviour differences between
-// OP_CALL and external calls
-void RaviCodeGenerator::emit_CALL(RaviFunctionDef *def, int A, int B, int C,
- int pc) {
-
- // int nresults = c - 1;
- // if (b != 0)
- // L->top = ra + b; /* else previous instruction set top */
- // int c = luaD_precall(L, ra, nresults, 1); /* C or JITed function? */
- // if (c) {
- // if (c == 1 && nresults >= 0)
- // L->top = ci->top; /* adjust results if C function */
- // }
- // else { /* Lua function */
- // int b = luaV_execute(L);
- // if (b) L->top = ci->top;
- // }
- bool traced = emit_debug_trace(def, OP_CALL, pc);
- // Set savedpc before the call
- if (!traced) emit_update_savedpc(def, pc);
- emit_load_base(def);
-
- // int nresults = c - 1;
- int nresults = C - 1;
-
- // if (b != 0)
- if (B != 0) {
- // L->top = ra + b; /* else previous instruction set top */
- emit_set_L_top_toreg(def, A + B);
- }
-
- // luaD_precall() returns following
- // 1 - C function called, results to be adjusted
- // 2 - JITed Lua function called, no action
- // 0 - Run interpreter on Lua function, if returns != 0 then update L->top
-
- // int c = luaD_precall(L, ra, nresults, op_call); /* C or JITed function? */
- // The last parameter to luaD_precall() tells it that
- // this is an OP_CALL
- llvm::Value *ra = emit_gep_register(def, A);
- llvm::Value *precall_result =
- CreateCall4(def->builder, def->luaD_precallF, def->L, ra,
- llvm::ConstantInt::get(def->types->C_intT, nresults),
- def->types->kInt[1]);
-
- // If luaD_precall() returns 0 then we need to interpret the
- // Lua function
- llvm::Value *do_Lua_interp =
- def->builder->CreateICmpEQ(precall_result, def->types->kInt[0]);
-
- llvm::BasicBlock *then_block = llvm::BasicBlock::Create(
- def->jitState->context(), "OP_CALL_if_Lua_interp_function", def->f);
- llvm::BasicBlock *else_block = llvm::BasicBlock::Create(
- def->jitState->context(), "OP_CALL_if_not_Lua_interp_function");
- llvm::BasicBlock *end_block =
- llvm::BasicBlock::Create(def->jitState->context(), "OP_CALL_done");
- def->builder->CreateCondBr(do_Lua_interp, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Lua function, not compiled, so call luaV_execute
- llvm::Value *b = def->builder->CreateCall(def->luaV_executeF, def->L);
-
- // If the return value is non zero then we need to refresh L->top = ci->top
- llvm::Value *b_not_zero = def->builder->CreateICmpNE(b, def->types->kInt[0]);
-
- llvm::BasicBlock *if_b_block = llvm::BasicBlock::Create(
- def->jitState->context(), "OP_CALL_if_need_reset_L_top", def->f);
- def->builder->CreateCondBr(b_not_zero, if_b_block, end_block);
- def->builder->SetInsertPoint(if_b_block);
-
- // Set L->top = ci->top
- emit_refresh_L_top(def, def->ci_val);
-
- // We are done
- def->builder->CreateBr(end_block);
-
- // Handle the C function or JIT case
- // function already executed by luaD_precall()
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-
- if (nresults >= 0) {
- // In case the precall returned 1 then a C function was
- // called so we need to update L->top
- // if (c == 1 && nresults >= 0)
- // L->top = ci->top; /* adjust results if C function */
- llvm::Value *precall_C =
- def->builder->CreateICmpEQ(precall_result, def->types->kInt[1]);
-
- llvm::BasicBlock *then1_block = llvm::BasicBlock::Create(
- def->jitState->context(), "OP_CALL_if_C_function_returned_values",
- def->f);
- def->builder->CreateCondBr(precall_C, then1_block, end_block);
- def->builder->SetInsertPoint(then1_block);
-
- emit_refresh_L_top(def, def->ci_val);
- }
- def->builder->CreateBr(end_block);
- def->f->getBasicBlockList().push_back(end_block);
- def->builder->SetInsertPoint(end_block);
-}
-
-#ifdef RAVI_DEFER_STATEMENT
-void RaviCodeGenerator::emit_DEFER(RaviFunctionDef *def, int A, int pc) {
- emit_debug_trace(def, OP_RAVI_DEFER, pc);
- emit_load_base(def);
- llvm::Value *ra = emit_gep_register(def, A);
- CreateCall2(def->builder, def->raviV_op_deferF, def->L, ra);
-}
-#endif
-
-}
\ No newline at end of file
diff --git a/src/ravi_llvmcodegen.cpp b/src/ravi_llvmcodegen.cpp
deleted file mode 100644
index 4bf6a68..0000000
--- a/src/ravi_llvmcodegen.cpp
+++ /dev/null
@@ -1,2084 +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.
- ******************************************************************************/
-#include
-#include
-#include
-
-namespace ravi {
-
-RaviBranchDef::RaviBranchDef()
- : jmp1(nullptr),
- jmp2(nullptr),
- jmp3(nullptr),
- jmp4(nullptr),
- ilimit(nullptr),
- istep(nullptr),
- iidx(nullptr),
- flimit(nullptr),
- fstep(nullptr),
- fidx(nullptr) {}
-
-RaviCodeGenerator::RaviCodeGenerator(RaviJITState *jitState)
- : jitState_(jitState), id_(1) {
- temp_[0] = 0;
-}
-
-const char *RaviCodeGenerator::unique_function_name() {
- // Create unique name for the compiled function
- // Lua functions are nameless so a compiled function has no name
- // as far as Lua is concerned
- snprintf(temp_, sizeof temp_, "ravif%d", id_++);
- return temp_;
-}
-
-llvm::CallInst *RaviCodeGenerator::CreateCall1(llvm::IRBuilder<> *builder,
- llvm::Value *func,
- llvm::Value *arg1) {
- llvm::SmallVector values;
- values.push_back(arg1);
- return builder->CreateCall(func, values);
-}
-
-llvm::CallInst *RaviCodeGenerator::CreateCall2(llvm::IRBuilder<> *builder,
- llvm::Value *func,
- llvm::Value *arg1,
- llvm::Value *arg2) {
- llvm::SmallVector values;
- values.push_back(arg1);
- values.push_back(arg2);
- return builder->CreateCall(func, values);
-}
-
-llvm::CallInst *RaviCodeGenerator::CreateCall3(llvm::IRBuilder<> *builder,
- llvm::Value *func,
- llvm::Value *arg1,
- llvm::Value *arg2,
- llvm::Value *arg3) {
- llvm::SmallVector values;
- values.push_back(arg1);
- values.push_back(arg2);
- values.push_back(arg3);
- return builder->CreateCall(func, values);
-}
-
-llvm::CallInst *RaviCodeGenerator::CreateCall4(
- llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1,
- llvm::Value *arg2, llvm::Value *arg3, llvm::Value *arg4) {
- llvm::SmallVector values;
- values.push_back(arg1);
- values.push_back(arg2);
- values.push_back(arg3);
- values.push_back(arg4);
- return builder->CreateCall(func, values);
-}
-
-llvm::CallInst *RaviCodeGenerator::CreateCall5(
- llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1,
- llvm::Value *arg2, llvm::Value *arg3, llvm::Value *arg4,
- llvm::Value *arg5) {
- llvm::SmallVector values;
- values.push_back(arg1);
- values.push_back(arg2);
- values.push_back(arg3);
- values.push_back(arg4);
- values.push_back(arg5);
- return builder->CreateCall(func, values);
-}
-
-void RaviCodeGenerator::attach_branch_weights(RaviFunctionDef *def,
- llvm::Instruction *ins,
- uint32_t true_branch,
- uint32_t false_branch) {
-#if RAVI_USE_LLVM_BRANCH_WEIGHTS
- ins->setMetadata(llvm::LLVMContext::MD_prof,
- def->jitState->types()->mdbuilder.createBranchWeights(
- true_branch, false_branch));
-#else
- (void)def;
- (void)ins;
- (void)true_branch;
- (void)false_branch;
-#endif
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
- llvm::Value *s, int arg1) {
- llvm::SmallVector values;
- values.push_back(def->types->kInt[arg1]);
- return def->builder->CreateInBoundsGEP(s, values, name);
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
- llvm::Value *s, int arg1, int arg2) {
- llvm::SmallVector values;
- values.push_back(def->types->kInt[arg1]);
- values.push_back(def->types->kInt[arg2]);
- return def->builder->CreateInBoundsGEP(s, values, name);
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
- llvm::Value *s, int arg1, int arg2,
- int arg3) {
- llvm::SmallVector values;
- values.push_back(def->types->kInt[arg1]);
- values.push_back(def->types->kInt[arg2]);
- values.push_back(def->types->kInt[arg3]);
- return def->builder->CreateInBoundsGEP(s, values, name);
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
- llvm::Value *ptr, llvm::Value *offset,
- int arg1) {
- llvm::SmallVector values;
- values.push_back(offset);
- values.push_back(def->types->kInt[arg1]);
- return def->builder->CreateInBoundsGEP(ptr, values, name);
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
- llvm::Value *ptr, llvm::Value *offset,
- int arg1, int arg2) {
- llvm::SmallVector values;
- values.push_back(offset);
- values.push_back(def->types->kInt[arg1]);
- values.push_back(def->types->kInt[arg2]);
- return def->builder->CreateInBoundsGEP(ptr, values, name);
-}
-
-llvm::Value *RaviCodeGenerator::emit_array_get(RaviFunctionDef *def,
- llvm::Value *ptr, int offset) {
- // emit code for &ptr[offset]
- return def->builder->CreateInBoundsGEP(
- ptr, llvm::ConstantInt::get(def->types->C_intT, offset));
-}
-
-// emit code for LClosure *cl = clLvalue(ci->func);
-llvm::Instruction *RaviCodeGenerator::emit_gep_ci_func_value_gc_asLClosure(
- RaviFunctionDef *def) {
- // clLvalue() is a macros that expands to (LClosure *)ci->func->value_.gc
- // via a complex series of macros and unions
- // fortunately as func is at the beginning of the CallInfo
- // structure we can just cast ci to LClosure***
- // This insight is based on code generated by Clang
- llvm::Value *pppLuaClosure =
- def->builder->CreateBitCast(def->ci_val, def->types->pppLClosureT);
-
- // Load pointer to LClosure**
- llvm::Instruction *ppLuaClosure = def->builder->CreateLoad(pppLuaClosure);
- ppLuaClosure->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_funcT);
-
- // Load pointer to LClosure*
- llvm::Instruction *cl_ptr = def->builder->CreateLoad(ppLuaClosure);
- cl_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_func_LClosureT);
-
- return cl_ptr;
-}
-
-// Retrieve the proto->sizep
-// sizep is a count of the number of closures defined
-// in the function
-llvm::Instruction *RaviCodeGenerator::emit_load_proto_sizep(
- RaviFunctionDef *def) {
- llvm::Value *psize_ptr = emit_gep(def, "sizep", def->proto_ptr, 0, 10);
- llvm::Instruction *psize = def->builder->CreateLoad(psize_ptr);
- psize->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Proto_sizepT);
- return psize;
-}
-
-// Updates the savedpc pointer in the call frame
-// The savedpc is unimportant for the JIT but it is relied upon
-// by the debug interface. So we need to set this in order for the
-// debug api to work. Rather than setting it on every bytecode instruction
-// we have a dual approach. By default the JIT code only sets this prior to
-// function calls - this enables better stack traces for example, and ad-hoc
-// calls to debug api. An optional setting in the JIT compiler also
-// enables this to be updated per bytecode instruction - this is only
-// required if someone wishes to set a line hook. The second option
-// is very expensive and will inhibit optimizations, hence it is optional
-// See issue #15
-void RaviCodeGenerator::emit_update_savedpc(RaviFunctionDef *def, int pc) {
- // Get proto->code
- llvm::Value *proto_code_ptr = emit_gep(def, "code", def->proto_ptr, 0, 15);
- llvm::Instruction *code_ptr = def->builder->CreateLoad(proto_code_ptr);
- code_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_Proto_codeT);
- // Need to set savedpc to the next instruction (pc+1) rather than current as
- // that is
- // what the VM does in interpreted mode
- llvm::Value *code_offset_ptr = emit_array_get(def, code_ptr, pc + 1);
- llvm::Value *savedpc_ptr = emit_gep(def, "savedpc", def->ci_val, 0, 4, 1);
- llvm::Instruction *ins =
- def->builder->CreateStore(code_offset_ptr, savedpc_ptr);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_savedpcT);
-}
-
-// Generate code to reload the function's stack 'base'
-// pointer - the VM needs to do this after any bytecode that
-// may invoke a Lua function and thereby resize the stack; which
-// would invalidate the current 'base' pointer
-void RaviCodeGenerator::emit_load_base(RaviFunctionDef *def) {
- // Load pointer to base
- llvm::Instruction *base_ptr = def->builder->CreateLoad(def->Ci_base);
- base_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_luaState_ci_baseT);
- def->base_ptr = base_ptr;
-}
-
-// emit code to obtain address of register at location A
-llvm::Value *RaviCodeGenerator::emit_gep_register(RaviFunctionDef *def, int A) {
- llvm::Value *dest;
- if (A == 0) {
- // If A is 0 we can use the base pointer which is &base[0]
- dest = def->base_ptr;
- }
- else {
- // emit &base[A]
- dest = emit_array_get(def, def->base_ptr, A);
- }
- return dest;
-}
-
-// Emit code to obtain address of a constant
-llvm::Value *RaviCodeGenerator::emit_gep_constant(RaviFunctionDef *def,
- int Bx) {
- // Load pointer to k
- llvm::Value *k_ptr = def->k_ptr;
- llvm::Value *src;
- if (Bx == 0) {
- // If Bx is 0 we can use the base pointer which is &k[0]
- src = k_ptr;
- }
- else {
- // emit &k[Bx]
- src = emit_array_get(def, k_ptr, Bx);
- }
- return src;
-}
-
-// Loads the value at register or constant at location B -
-// if the value is an integer constant
-// then returns a constant literal
-llvm::Value *RaviCodeGenerator::emit_load_register_or_constant_i(
- RaviFunctionDef *def, int B) {
- if (ISK(B) && def->p->k[INDEXK(B)].tt_ == LUA_TNUMINT) {
- TValue *Konst = &def->p->k[INDEXK(B)];
- return llvm::ConstantInt::get(def->types->lua_IntegerT, Konst->value_.i);
- }
- else {
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- return emit_load_reg_i(def, rb);
- }
-}
-
-// Loads the value at register B - if the value is an number constant
-// then returns a constant literal
-llvm::Value *RaviCodeGenerator::emit_load_register_or_constant_n(
- RaviFunctionDef *def, int B) {
- if (ISK(B) && def->p->k[INDEXK(B)].tt_ == LUA_TNUMFLT) {
- TValue *Konst = &def->p->k[INDEXK(B)];
- return llvm::ConstantFP::get(def->types->lua_NumberT, Konst->value_.n);
- }
- else {
- llvm::Value *rb = emit_gep_register_or_constant(def, B);
- return emit_load_reg_n(def, rb);
- }
-}
-
-// emit code to load the lua_Number value from register (TValue)
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_n(RaviFunctionDef *def,
- llvm::Value *rb) {
- llvm::Value *rb_n = def->builder->CreateBitCast(rb, def->types->plua_NumberT);
- // llvm::Value *rb_n = emit_gep(def, "value.value_.n", rb, 0, 0, 0);
- llvm::Instruction *lhs = def->builder->CreateLoad(rb_n);
- lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
- return lhs;
-}
-
-// emit code to load the lua_Integer value from register (TValue)
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_i(RaviFunctionDef *def,
- llvm::Value *rb) {
- llvm::Value *rb_n =
- def->builder->CreateBitCast(rb, def->types->plua_IntegerT);
- llvm::Instruction *lhs = def->builder->CreateLoad(rb_n);
- lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
- return lhs;
-}
-
-// emit code to load the boolean value from register (TValue)
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_b(RaviFunctionDef *def,
- llvm::Value *rb) {
- llvm::Value *rb_n = def->builder->CreateBitCast(rb, def->types->C_pintT);
- llvm::Instruction *lhs = def->builder->CreateLoad(rb_n);
- lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
- return lhs;
-}
-
-// emit code to load the table value from register (TValue)
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_h(RaviFunctionDef *def,
- llvm::Value *rb) {
- llvm::Value *rb_h = def->builder->CreateBitCast(rb, def->types->ppTableT);
- llvm::Instruction *h = def->builder->CreateLoad(rb_h);
- h->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_hT);
- return h;
-}
-
-// emit code to load the RaviArray value from register (TValue)
-llvm::Instruction* RaviCodeGenerator::emit_load_reg_arr(RaviFunctionDef* def,
- llvm::Value* rb) {
- llvm::Value* rb_h = def->builder->CreateBitCast(rb, def->types->ppRaviArrayT);
- llvm::Instruction* h = def->builder->CreateLoad(rb_h);
- h->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_hT);
- return h;
-}
-
-// Gets the size of the hash table
-// This is the sizenode() macro in lobject.h
-llvm::Value *RaviCodeGenerator::emit_table_get_hashsize(RaviFunctionDef *def,
- llvm::Value *t) {
- // Obtain the lsizenode of the hash table
- llvm::Value *lsizenode_ptr = emit_gep(def, "lsizenode", t, 0, 4);
- llvm::Instruction *lsizenode = def->builder->CreateLoad(lsizenode_ptr);
- lsizenode->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_Table_lsizenode);
- // convert to integer (lsizenode is a byte)
- llvm::Value *intsize =
- def->builder->CreateZExt(lsizenode, def->types->C_intT);
- // #define twoto(x) (1<<(x))
- // #define sizenode(t) (twoto((t)->lsizenode))
- llvm::Value *size = def->builder->CreateShl(def->types->kInt[1], intsize);
- return size;
-}
-
-// Gets the location of the hash node for given string key
-// return value is the offset into the node array
-llvm::Value *RaviCodeGenerator::emit_table_get_hashstr(RaviFunctionDef *def,
- llvm::Value *table,
- TString *key) {
-#if RAVI_USE_NEWHASH
- unsigned int hash = key->hash;
- llvm::Value *hmask_ptr = emit_gep(def, "hmask", table, 0, 11);
- llvm::Instruction *hmask = def->builder->CreateLoad(hmask_ptr);
- hmask->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_hmask);
- llvm::Value *offset = def->builder->CreateAnd(
- llvm::ConstantInt::get(def->types->C_intT, hash), hmask);
-#else
- llvm::Value *size = emit_table_get_hashsize(def, table);
- unsigned int hash = key->hash;
- // #define lmod(s,size) (cast(int, (s) & ((size)-1)))
- llvm::Value *sizeminusone =
- def->builder->CreateNSWSub(size, def->types->kInt[1]);
- llvm::Value *offset = def->builder->CreateAnd(
- llvm::ConstantInt::get(def->types->C_intT, hash), sizeminusone);
-#endif
- return offset;
-}
-
-// Gets access to the Table's node array (t->node)
-llvm::Value *RaviCodeGenerator::emit_table_get_nodearray(RaviFunctionDef *def,
- llvm::Value *table) {
- // Get access to the node array
- llvm::Value *node_ptr = emit_gep(def, "node", table, 0, 7);
- llvm::Instruction *node = def->builder->CreateLoad(node_ptr);
- node->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_node);
- return node;
-}
-
-// Given a pointer to table's node array (node = t->node) and
-// the location of the hashed key (index), this method retrieves the
-// type of the value stored at the node - return value is of type int
-// and is the type information stored in TValue->tt field.
-llvm::Value *RaviCodeGenerator::emit_table_get_keytype(RaviFunctionDef *def,
- llvm::Value *node,
- llvm::Value *index) {
- llvm::Value *ktype_ptr = emit_gep(def, "keytype", node, index, 1, 1);
- llvm::Instruction *ktype = def->builder->CreateLoad(ktype_ptr);
- ktype->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT);
- return ktype;
-}
-
-// Given a pointer to table's node array (node = t->node) and
-// the location of the hashed key (index), this method retrieves the
-// the string value stored at the node - return value is of type TString*
-llvm::Value *RaviCodeGenerator::emit_table_get_strkey(RaviFunctionDef *def,
- llvm::Value *node,
- llvm::Value *index) {
- llvm::Value *value_ptr = emit_gep(def, "keyvalue", node, index, 1, 0);
- llvm::Value *sptr =
- def->builder->CreateBitCast(value_ptr, def->types->ppTStringT);
- llvm::Instruction *keyvalue = def->builder->CreateLoad(sptr);
- keyvalue->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_ppointerT);
- return keyvalue;
-}
-
-// Given a pointer to table's node array (node = t->node) and
-// the location of the hashed key (index), this method retrieves the
-// the pointer to value stored at the node - return value is of type TValue*
-llvm::Value *RaviCodeGenerator::emit_table_get_value(RaviFunctionDef *def,
- llvm::Value *node,
- llvm::Value *index) {
- return emit_gep(def, "nodeval", node, index, 0);
-}
-
-// Gets the size of the table's array part
-llvm::Value *RaviCodeGenerator::emit_table_get_arraysize(RaviFunctionDef *def,
- llvm::Value *table) {
- // Obtain the lsizenode of the hash table
- llvm::Value *sizearray_ptr = emit_gep(def, "sizearray", table, 0, 5);
- llvm::Instruction *sizearray = def->builder->CreateLoad(sizearray_ptr);
- sizearray->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_Table_sizearray);
- return sizearray;
-}
-
-llvm::Value *RaviCodeGenerator::emit_table_get_array(RaviFunctionDef *def,
- llvm::Value *table) {
- // Get access to the node array
- llvm::Value *array_ptr = emit_gep(def, "array", table, 0, 6);
- llvm::Instruction *arry = def->builder->CreateLoad(array_ptr);
- arry->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_array);
- return arry;
-}
-
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_s(RaviFunctionDef *def,
- llvm::Value *rb) {
- llvm::Value *rb_s = def->builder->CreateBitCast(rb, def->types->ppTStringT);
- llvm::Instruction *s = def->builder->CreateLoad(rb_s);
- // Following TBAA is okay as the field type is a pointer
- s->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_hT);
- return s;
-}
-
-/* Loads the data pointer as lua_Number[] from a RaviArray object */
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_h_floatarray(
- RaviFunctionDef *def, llvm::Instruction *h) {
- llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 7);
- llvm::Value *darray_ptr =
- def->builder->CreateBitCast(data_ptr, def->types->pplua_NumberT);
- llvm::Instruction *darray = def->builder->CreateLoad(darray_ptr);
- darray->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_RaviArray_dataT);
- return darray;
-}
-
-/* Loads the data pointer as lua_Integer[] from a RaviArray object */
-llvm::Instruction *RaviCodeGenerator::emit_load_reg_h_intarray(
- RaviFunctionDef *def, llvm::Instruction *h) {
- llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 7);
- llvm::Value *darray_ptr =
- def->builder->CreateBitCast(data_ptr, def->types->pplua_IntegerT);
- llvm::Instruction *darray = def->builder->CreateLoad(darray_ptr);
- darray->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_RaviArray_dataT);
- return darray;
-}
-
-void RaviCodeGenerator::emit_store_reg_n(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- llvm::Value *ra_n =
- def->builder->CreateBitCast(dest_ptr, def->types->plua_NumberT);
- // llvm::Value *ra_n = emit_gep(def, "value.value_.n", dest_ptr, 0, 0, 0);
- llvm::Instruction *store = def->builder->CreateStore(result, ra_n);
- store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
-}
-
-void RaviCodeGenerator::emit_store_reg_n_withtype(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- emit_store_reg_n(def, result, dest_ptr);
- emit_store_type_(def, dest_ptr, LUA_TNUMFLT);
-}
-
-void RaviCodeGenerator::emit_store_reg_i(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- llvm::Value *ra_n =
- def->builder->CreateBitCast(dest_ptr, def->types->plua_IntegerT);
- llvm::Instruction *store = def->builder->CreateStore(result, ra_n);
- store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
-}
-
-void RaviCodeGenerator::emit_store_reg_i_withtype(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- emit_store_reg_i(def, result, dest_ptr);
- emit_store_type_(def, dest_ptr, LUA_TNUMINT);
-}
-
-void RaviCodeGenerator::emit_store_reg_b(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- llvm::Value *ra_n =
- def->builder->CreateBitCast(dest_ptr, def->types->C_pintT);
- llvm::Instruction *store = def->builder->CreateStore(result, ra_n);
- store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
-}
-
-void RaviCodeGenerator::emit_store_reg_b_withtype(RaviFunctionDef *def,
- llvm::Value *result,
- llvm::Value *dest_ptr) {
- emit_store_reg_b(def, result, dest_ptr);
- emit_store_type_(def, dest_ptr, LUA_TBOOLEAN);
-}
-
-void RaviCodeGenerator::emit_store_type_(RaviFunctionDef *def,
- llvm::Value *value, int type) {
- lua_assert(type == LUA_TNUMFLT || type == LUA_TNUMINT ||
- type == LUA_TBOOLEAN || type == LUA_TNIL);
- llvm::Value *desttype = emit_gep(def, "dest.tt", value, 0, 1);
- llvm::Instruction *store = def->builder->CreateStore(
- llvm::ConstantInt::get(def->types->lua_LuaTypeT, type),
- desttype);
- store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT);
-}
-
-llvm::Instruction *RaviCodeGenerator::emit_load_type(RaviFunctionDef *def,
- llvm::Value *value) {
- llvm::Value *tt_ptr = emit_gep(def, "value.tt.ptr", value, 0, 1);
- llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "value.tt");
- tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT);
- return tt;
-}
-
-llvm::Value *RaviCodeGenerator::emit_is_value_of_type(RaviFunctionDef *def,
- llvm::Value *value_type,
- LuaTypeCode lua_type,
- const char *varname) {
- return def->builder->CreateICmpEQ(
- value_type, llvm::ConstantInt::get(def->types->lua_LuaTypeT, lua_type),
- varname);
-}
-
-llvm::Value *RaviCodeGenerator::emit_is_not_value_of_type(
- RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_type,
- const char *varname) {
- return def->builder->CreateICmpNE(
- value_type, llvm::ConstantInt::get(def->types->lua_LuaTypeT, lua_type),
- varname);
-}
-
-// Compare without variants i.e. ttnov(value_type) == lua_type
-llvm::Value *RaviCodeGenerator::emit_is_not_value_of_type_class(
- RaviFunctionDef *def, llvm::Value *value_type, int lua_type,
- const char *varname) {
- llvm::Value *novariant_type = def->builder->CreateAnd(
- value_type, llvm::ConstantInt::get(def->types->lua_LuaTypeT, 0x000F));
- return def->builder->CreateICmpNE(
- novariant_type,
- llvm::ConstantInt::get(def->types->lua_LuaTypeT, lua_type), varname);
-}
-
-/* This loads the RaviArray type value from the tt field maintained in the
- GC part. However this tt is 8-bit value and needs to be converted to
- the 16-bit value used in TValue objects */
-//llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraytype(
-// RaviFunctionDef *def, llvm::Value *value) {
-// llvm::Value *tt_ptr = emit_gep(def, "raviarray.type_ptr", value, 0, 1);
-// llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.type");
-// // FIXME promote to 16 bit and set collectible bit
-// tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_typeT);
-// return tt;
-//}
-
-llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraylength(
- RaviFunctionDef *def, llvm::Value *value) {
- llvm::Value *tt_ptr = emit_gep(def, "raviarray.len_ptr", value, 0, 4);
- llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.len");
- tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_lenT);
- return tt;
-}
-
-// Tests following:
-// ((t) == NULL) || ((t)->flags & (1u<builder->CreateLoad(metatable_ptr, "table.metatable");
- metatable->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_Table_metatable);
- llvm::Value *null_constant =
- llvm::ConstantPointerNull::get(def->types->pTableT);
- llvm::Value *is_null = def->builder->CreateICmpEQ(
- def->builder->CreatePtrToInt(null_constant, def->types->C_intptr_t),
- def->builder->CreatePtrToInt(metatable, def->types->C_intptr_t));
-
- // Is metatable->flags & (1<builder->CreateLoad(flags_ptr, "table.flags");
- flags->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_flags);
- llvm::Value *no_event = def->builder->CreateICmpNE(
- def->builder->CreateAnd(
- flags, llvm::ConstantInt::get(def->types->lu_byteT, 1u << event)),
- llvm::ConstantInt::get(def->types->lu_byteT, 0));
-
- llvm::Value *metaabsent =
- def->builder->CreateOr(is_null, no_event, "metatable.isnull.or.no.event");
- return metaabsent;
-}
-
-// Store lua_Number or lua_Integer
-llvm::Instruction *RaviCodeGenerator::emit_store_local_n(RaviFunctionDef *def,
- llvm::Value *src,
- llvm::Value *dest) {
- llvm::Instruction *ins = def->builder->CreateStore(src, dest);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_plonglongT);
- return ins;
-}
-
-// Load lua_Number or lua_Integer
-llvm::Instruction *RaviCodeGenerator::emit_load_local_n(RaviFunctionDef *def,
- llvm::Value *src) {
- llvm::Instruction *ins = def->builder->CreateLoad(src);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_plonglongT);
- return ins;
-}
-
-// Store int
-llvm::Instruction *RaviCodeGenerator::emit_store_local_int(RaviFunctionDef *def,
- llvm::Value *src,
- llvm::Value *dest) {
- llvm::Instruction *ins = def->builder->CreateStore(src, dest);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_pintT);
- return ins;
-}
-
-// Load int
-llvm::Instruction *RaviCodeGenerator::emit_load_local_int(RaviFunctionDef *def,
- llvm::Value *src) {
- llvm::Instruction *ins = def->builder->CreateLoad(src);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_pintT);
- return ins;
-}
-
-// emit code to obtain address of register or constant at location B
-llvm::Value *RaviCodeGenerator::emit_gep_register_or_constant(
- RaviFunctionDef *def, int B) {
- // Load pointer to k
- llvm::Value *k_ptr = def->k_ptr;
- llvm::Value *rb;
- // Get pointer to register B
- llvm::Value *base_or_k = ISK(B) ? k_ptr : def->base_ptr;
- int b = ISK(B) ? INDEXK(B) : B;
- if (b == 0) { rb = base_or_k; }
- else {
- rb = emit_array_get(def, base_or_k, b);
- }
- return rb;
-}
-
-#if 0
-// Test if ci->jistatus is true, ci is of type CallInfo
-llvm::Value *RaviCodeGenerator::emit_is_jit_call(RaviFunctionDef *def,
- llvm::Value *ci) {
- // Get pointer to ci->jitstatus
- llvm::Value *ci_jitstatus_ptr = emit_gep(def, "ci_jit_status_ptr", ci, 0, 9);
-
- // Load ci->jitstatus
- llvm::Instruction *ci_jitstatus = def->builder->CreateLoad(ci_jitstatus_ptr);
- ci_jitstatus->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_jitstatusT);
-
- return def->builder->CreateICmpNE(
- ci_jitstatus, llvm::ConstantInt::get(def->types->lu_byteT, 0),
- "jit_call");
-}
-
-// Return (ci->callstatus & CIST_LUA) != 0
-llvm::Value *RaviCodeGenerator::emit_ci_is_Lua(RaviFunctionDef *def,
- llvm::Value *ci) {
- // Get pointer to ci->callstatus
- llvm::Value *ci_callstatus_ptr =
- emit_gep(def, "ci_call_status_ptr", ci, 0, 7);
-
- // Load ci->callstatus
- llvm::Instruction *ci_callstatus =
- def->builder->CreateLoad(ci_callstatus_ptr, "ci_call_status");
- ci_callstatus->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_callstatusT);
-
- llvm::Value *isLua = def->builder->CreateAnd(
- ci_callstatus, llvm::ConstantInt::get(def->types->C_shortT, CIST_LUA),
- "isLua");
- return def->builder->CreateICmpNE(
- isLua, llvm::ConstantInt::get(def->types->C_shortT, 0));
-}
-#endif
-
-llvm::Value *RaviCodeGenerator::emit_load_ci(RaviFunctionDef *def) {
- llvm::Value *L_ci = emit_gep(def, "L_ci", def->L, 0, 6);
-
- llvm::Instruction *ci_val = def->builder->CreateLoad(L_ci);
- ci_val->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_CallInfoT);
-
- return ci_val;
-}
-
-// L->top = ci->top
-void RaviCodeGenerator::emit_refresh_L_top(RaviFunctionDef *def,
- llvm::Value *ci_val) {
- // Get pointer to ci->top
- llvm::Value *citop = emit_gep(def, "ci_top", ci_val, 0, 1);
-
- // Load ci->top
- llvm::Instruction *citop_val = def->builder->CreateLoad(citop);
- citop_val->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_CallInfo_topT);
-
- // Get L->top
- llvm::Value *top = emit_gep(def, "L_top", def->L, 0, 4);
-
- // Assign ci>top to L->top
- auto ins = def->builder->CreateStore(citop_val, top);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep_L_top(RaviFunctionDef *def) {
- // Get pointer to L->top
- return emit_gep(def, "L.top", def->L, 0, 4);
-}
-
-// L->top = R(B)
-void RaviCodeGenerator::emit_set_L_top_toreg(RaviFunctionDef *def, int B) {
- // Get pointer to register at R(B)
- llvm::Value *ptr = emit_gep_register(def, B);
- // Get pointer to L->top
- llvm::Value *top = emit_gep_L_top(def);
- // Assign to L->top
- llvm::Instruction *ins = def->builder->CreateStore(ptr, top);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);
-}
-
-llvm::Instruction *RaviCodeGenerator::emit_tointeger(RaviFunctionDef *def,
- llvm::Value *reg) {
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *value =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "value");
- llvm::Value *reg_type = emit_load_type(def, reg);
-
- // Is reg an integer?
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, reg_type, LUA__TNUMINT, "reg.is.integer");
-
- llvm::BasicBlock *convert_reg =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.reg");
- llvm::BasicBlock *copy_reg =
- llvm::BasicBlock::Create(def->jitState->context(), "copy.reg");
- llvm::BasicBlock *load_val =
- llvm::BasicBlock::Create(def->jitState->context(), "load.val");
- llvm::BasicBlock *failed_conversion = llvm::BasicBlock::Create(
- def->jitState->context(), "if.conversion.failed");
-
- // If reg is integer then copy reg, else convert reg
- auto brinst1 = def->builder->CreateCondBr(cmp1, copy_reg, convert_reg);
- attach_branch_weights(def, brinst1, 100, 0);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_reg);
- def->builder->SetInsertPoint(convert_reg);
-
- llvm::Value *var_isint =
- CreateCall2(def->builder, def->luaV_tointegerF, reg, value);
- llvm::Value *tobool = def->builder->CreateICmpEQ(
- var_isint, def->types->kInt[0], "conversion.failed");
-
- // Did conversion fail?
- def->builder->CreateCondBr(tobool, failed_conversion, load_val);
-
- // Conversion failed, so raise error
- def->f->getBasicBlockList().push_back(failed_conversion);
- def->builder->SetInsertPoint(failed_conversion);
- emit_raise_lua_error(def, "integer expected");
- def->builder->CreateBr(load_val);
-
- // Conversion OK
- def->f->getBasicBlockList().push_back(copy_reg);
- def->builder->SetInsertPoint(copy_reg);
-
- llvm::Value *i = emit_load_reg_i(def, reg);
- emit_store_local_int(def, i, value);
- def->builder->CreateBr(load_val);
-
- def->f->getBasicBlockList().push_back(load_val);
- def->builder->SetInsertPoint(load_val);
-
- return emit_load_local_int(def, value);
-}
-
-llvm::Instruction *RaviCodeGenerator::emit_tofloat(RaviFunctionDef *def,
- llvm::Value *reg) {
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *value =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "value");
- llvm::Value *reg_type = emit_load_type(def, reg);
-
- // Is reg an number?
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, reg_type, LUA__TNUMFLT, "reg.is.float");
-
- llvm::BasicBlock *convert_reg =
- llvm::BasicBlock::Create(def->jitState->context(), "convert.reg");
- llvm::BasicBlock *copy_reg =
- llvm::BasicBlock::Create(def->jitState->context(), "copy.reg");
- llvm::BasicBlock *load_val =
- llvm::BasicBlock::Create(def->jitState->context(), "load.val");
- llvm::BasicBlock *failed_conversion = llvm::BasicBlock::Create(
- def->jitState->context(), "if.conversion.failed");
-
- // If reg is integer then copy reg, else convert reg
- auto brinst1 = def->builder->CreateCondBr(cmp1, copy_reg, convert_reg);
- attach_branch_weights(def, brinst1, 100, 0);
-
- // Convert RB
- def->f->getBasicBlockList().push_back(convert_reg);
- def->builder->SetInsertPoint(convert_reg);
-
- llvm::Value *var_isfloat =
- CreateCall2(def->builder, def->luaV_tonumberF, reg, value);
- llvm::Value *tobool = def->builder->CreateICmpEQ(
- var_isfloat, def->types->kInt[0], "conversion.failed");
-
- // Did conversion fail?
- def->builder->CreateCondBr(tobool, failed_conversion, load_val);
-
- // Conversion failed, so raise error
- def->f->getBasicBlockList().push_back(failed_conversion);
- def->builder->SetInsertPoint(failed_conversion);
- emit_raise_lua_error(def, "number expected");
- def->builder->CreateBr(load_val);
-
- // Conversion OK
- def->f->getBasicBlockList().push_back(copy_reg);
- def->builder->SetInsertPoint(copy_reg);
-
- llvm::Value *i = emit_load_reg_n(def, reg);
- emit_store_local_n(def, i, value);
- def->builder->CreateBr(load_val);
-
- def->f->getBasicBlockList().push_back(load_val);
- def->builder->SetInsertPoint(load_val);
-
- return emit_load_local_n(def, value);
-}
-
-// (int)(L->top - ra)
-llvm::Value *RaviCodeGenerator::emit_num_stack_elements(RaviFunctionDef *def,
- llvm::Value *ra) {
- llvm::Value *L_top = emit_gep_L_top(def);
- llvm::Instruction *top_ptr = def->builder->CreateLoad(L_top, "L_top_ptr");
- llvm::Value *top_asint = def->builder->CreatePtrToInt(
- top_ptr, def->types->C_intptr_t, "L_top_ptr_as_int");
- llvm::Value *ra_asint =
- def->builder->CreatePtrToInt(ra, def->types->C_intptr_t, "ra_ptr_as_int");
- llvm::Value *diff =
- def->builder->CreateSub(top_asint, ra_asint, "L_top_minus_ra");
- // Because each value object is 16 bytes we need to divide by 16
- llvm::Value *n_elements = def->builder->CreateSDiv(
- diff, llvm::ConstantInt::get(def->types->C_intptr_t, sizeof(TValue)),
- "num_tvalue_elements", true);
- return def->builder->CreateTrunc(n_elements, def->types->C_intT,
- "num_stack_elements");
-}
-
-// Check if we can compile
-// The cases we can compile will increase over time
-bool RaviCodeGenerator::canCompile(Proto *p) {
- if (p->ravi_jit.jit_status == RAVI_JIT_CANT_COMPILE) return false;
- if (jitState_ == nullptr) {
- p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE;
- return false;
- }
- // const Instruction *code = p->code;
- // int pc, n = p->sizecode;
- // Loop over the byte codes; as Lua compiler inserts
- // an extra RETURN op we need to ignore the last op
- // for (pc = 0; pc < n; pc++) {
- // Instruction i = code[pc];
- // OpCode o = GET_OPCODE(i);
- // if (o == OP_EXTRAARG)
- // return false;
- // else if (o == OP_RAVI_UNMF || o == OP_RAVI_UNMI) {
- // fprintf(stderr, "Unexpected bytecode %d\n", o);
- // abort();
- // }
- //}
- return true;
-}
-
-std::unique_ptr RaviCodeGenerator::create_function(
- Proto *p, std::shared_ptr module, llvm::IRBuilder<> &builder,
- RaviFunctionDef *def) {
- LuaLLVMTypes *types = jitState_->types();
-
- std::unique_ptr func =
- std::unique_ptr(new RaviJITFunction(
- &p->ravi_jit.jit_function, module, types->jitFunctionT,
- llvm::Function::ExternalLinkage, unique_function_name()));
- if (!func) return func;
-
- llvm::Function *mainFunc = func->function();
- llvm::BasicBlock *entry =
- llvm::BasicBlock::Create(jitState_->context(), "entry", mainFunc);
- builder.SetInsertPoint(entry);
-
- auto argiter = mainFunc->arg_begin();
- llvm::Value *arg1 = &(*argiter);
- arg1->setName("L");
-
- def->jitState = jitState_;
- def->f = mainFunc;
- def->entry = entry;
- def->L = arg1;
- def->raviF = func.get();
- def->types = types;
- def->builder = &builder;
-
- return func;
-}
-
-#if 0
-void RaviCodeGenerator::emit_dump_stack(RaviFunctionDef *def, const char *str) {
- CreateCall2(def->builder, def->ravi_dump_stackF, def->L,
- def->builder->CreateGlobalStringPtr(str));
-}
-
-void RaviCodeGenerator::emit_dump_stacktop(RaviFunctionDef *def,
- const char *str) {
- CreateCall2(def->builder, def->ravi_dump_stacktopF, def->L,
- def->builder->CreateGlobalStringPtr(str));
-}
-#endif
-
-// Emit a call to ravi_debug_trace() function.
-// This function will set savedpc and also invoke
-// "line" hook if defined
-bool RaviCodeGenerator::emit_debug_trace(RaviFunctionDef *def, int opCode,
- int pc) {
- if (def->jitState->is_tracehook_enabled()) {
- CreateCall3(def->builder, def->ravi_debug_traceF, def->L,
- llvm::ConstantInt::get(def->types->C_intT, opCode),
- llvm::ConstantInt::get(def->types->C_intT, pc));
- return true;
- }
- return false;
-}
-
-void RaviCodeGenerator::emit_raise_lua_error(RaviFunctionDef *def,
- const char *str) {
- CreateCall2(def->builder, def->luaG_runerrorF, def->L,
- def->builder->CreateGlobalStringPtr(str));
-}
-
-void RaviCodeGenerator::debug_printf(RaviFunctionDef *def, const char *str) {
-#if LLVM_VERSION_MAJOR >= 9
- CreateCall1(def->builder, def->printfFunc.getCallee(),
- def->builder->CreateGlobalStringPtr(str));
-#else
- CreateCall1(def->builder, def->printfFunc,
- def->builder->CreateGlobalStringPtr(str));
-#endif
-}
-
-void RaviCodeGenerator::debug_printf1(RaviFunctionDef *def, const char *str,
- llvm::Value *arg1) {
-#if LLVM_VERSION_MAJOR >= 9
- CreateCall2(def->builder, def->printfFunc.getCallee(),
- def->builder->CreateGlobalStringPtr(str), arg1);
-#else
- CreateCall2(def->builder, def->printfFunc,
- def->builder->CreateGlobalStringPtr(str), arg1);
-#endif
-}
-
-void RaviCodeGenerator::debug_printf2(RaviFunctionDef *def, const char *str,
- llvm::Value *arg1, llvm::Value *arg2) {
-#if LLVM_VERSION_MAJOR >= 9
- CreateCall3(def->builder, def->printfFunc.getCallee(),
- def->builder->CreateGlobalStringPtr(str), arg1, arg2);
-#else
- CreateCall3(def->builder, def->printfFunc,
- def->builder->CreateGlobalStringPtr(str), arg1, arg2);
-#endif
-}
-
-void RaviCodeGenerator::debug_printf3(RaviFunctionDef *def, const char *str,
- llvm::Value *arg1, llvm::Value *arg2,
- llvm::Value *arg3) {
-#if LLVM_VERSION_MAJOR >= 9
- CreateCall4(def->builder, def->printfFunc.getCallee(),
- def->builder->CreateGlobalStringPtr(str), arg1, arg2, arg3);
-#else
- CreateCall4(def->builder, def->printfFunc,
- def->builder->CreateGlobalStringPtr(str), arg1, arg2, arg3);
-#endif
-}
-
-void RaviCodeGenerator::debug_printf4(RaviFunctionDef *def, const char *str,
- llvm::Value *arg1, llvm::Value *arg2,
- llvm::Value *arg3, llvm::Value *arg4) {
-#if LLVM_VERSION_MAJOR >= 9
- CreateCall5(def->builder, def->printfFunc.getCallee(),
- def->builder->CreateGlobalStringPtr(str), arg1, arg2, arg3, arg4);
-#else
- CreateCall5(def->builder, def->printfFunc,
- def->builder->CreateGlobalStringPtr(str), arg1, arg2, arg3, arg4);
-#endif
-}
-
-void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
- // Add extern declarations for Lua functions that we need to call
- def->luaT_trybinTMF = def->raviF->addExternFunction(
- def->types->luaT_trybinTMT, reinterpret_cast(&luaT_trybinTM),
- "luaT_trybinTM");
- def->luaD_callF = def->raviF->addExternFunction(
- def->types->luaD_callT, reinterpret_cast(&luaD_call),
- "luaD_call");
- def->luaD_poscallF = def->raviF->addExternFunction(
- def->types->luaD_poscallT, reinterpret_cast(&luaD_poscall),
- "luaD_poscall");
- def->luaD_precallF = def->raviF->addExternFunction(
- def->types->luaD_precallT, reinterpret_cast(&luaD_precall),
- "luaD_precall");
- def->luaF_closeF = def->raviF->addExternFunction(
- def->types->luaF_closeT, reinterpret_cast(&luaF_close),
- "luaF_close");
- def->luaG_runerrorF = def->raviF->addExternFunction(
- def->types->luaG_runerrorT, reinterpret_cast(&luaG_runerror),
- "luaG_runerror");
- def->luaG_runerrorF->setDoesNotReturn();
- def->luaV_equalobjF = def->raviF->addExternFunction(
- def->types->luaV_equalobjT, reinterpret_cast(&luaV_equalobj),
- "luaV_equalobj");
- def->luaV_lessthanF = def->raviF->addExternFunction(
- def->types->luaV_lessthanT, reinterpret_cast(&luaV_lessthan),
- "luaV_lessthan");
- def->luaV_lessequalF = def->raviF->addExternFunction(
- def->types->luaV_lessequalT, reinterpret_cast(&luaV_lessequal),
- "luaV_lessequal");
- def->luaV_forlimitF = def->raviF->addExternFunction(
- def->types->luaV_forlimitT, reinterpret_cast(&luaV_forlimit),
- "luaV_forlimit");
- def->luaV_tonumberF = def->raviF->addExternFunction(
- def->types->luaV_tonumberT, reinterpret_cast(&luaV_tonumber_),
- "luaV_tonumber_");
- def->luaV_tointegerF = def->raviF->addExternFunction(
- def->types->luaV_tointegerT, reinterpret_cast(&luaV_tointeger_),
- "luaV_tointeger_");
- def->luaV_executeF = def->raviF->addExternFunction(
- def->types->luaV_executeT, reinterpret_cast(&luaV_execute),
- "luaV_execute");
- def->luaV_settableF = def->raviF->addExternFunction(
- def->types->luaV_settableT, reinterpret_cast(&luaV_settable),
- "luaV_settable");
- def->luaV_gettableF = def->raviF->addExternFunction(
- def->types->luaV_gettableT, reinterpret_cast(&luaV_gettable),
- "luaV_gettable");
- def->luaH_getintF = def->raviF->addExternFunction(
- def->types->luaH_getintT, reinterpret_cast(&luaH_getint),
- "luaH_getint");
- def->luaH_setintF = def->raviF->addExternFunction(
- def->types->luaH_setintT, reinterpret_cast(&luaH_setint),
- "luaH_setint");
- def->luaH_getstrF = def->raviF->addExternFunction(
- def->types->luaH_getstrT, reinterpret_cast(&luaH_getstr),
- "luaH_getstr");
- def->luaH_getstrF->addFnAttr(llvm::Attribute::AttrKind::ReadOnly);
- // def->luaH_getstrF->setDoesNotAlias(1);
- // def->luaH_getstrF->setDoesNotCapture(1);
- // def->luaH_getstrF->setDoesNotAlias(2);
- // def->luaH_getstrF->setDoesNotCapture(2);
- def->luaV_finishgetF = def->raviF->addExternFunction(
- def->types->luaV_finishgetT, reinterpret_cast(&luaV_finishget),
- "luaV_finishget");
-
- def->raviV_op_loadnilF = def->raviF->addExternFunction(
- def->types->raviV_op_loadnilT,
- reinterpret_cast(&raviV_op_loadnil), "raviV_op_loadnil");
- def->raviV_op_newarrayintF = def->raviF->addExternFunction(
- def->types->raviV_op_newarrayintT,
- reinterpret_cast(&raviV_op_newarrayint), "raviV_op_newarrayint");
- def->raviV_op_newarrayfloatF = def->raviF->addExternFunction(
- def->types->raviV_op_newarrayfloatT,
- reinterpret_cast(&raviV_op_newarrayfloat),
- "raviV_op_newarrayfloat");
- def->raviV_op_newtableF = def->raviF->addExternFunction(
- def->types->raviV_op_newtableT,
- reinterpret_cast(&raviV_op_newtable), "raviV_op_newtable");
- def->raviV_op_setlistF = def->raviF->addExternFunction(
- def->types->raviV_op_setlistT,
- reinterpret_cast(&raviV_op_setlist), "raviV_op_setlist");
- def->luaV_modF = def->raviF->addExternFunction(
- def->types->luaV_modT, reinterpret_cast(&luaV_mod), "luaV_mod");
- def->luaV_idivF = def->raviF->addExternFunction(
- def->types->luaV_idivT, reinterpret_cast(&luaV_idiv), "luaV_idiv");
- def->luaV_objlenF = def->raviF->addExternFunction(
- def->types->luaV_objlenT, reinterpret_cast(&luaV_objlen),
- "luaV_objlen");
- def->luaC_upvalbarrierF = def->raviF->addExternFunction(
- def->types->luaC_upvalbarrierT,
- reinterpret_cast(&luaC_upvalbarrier_compat), "luaC_upvalbarrier_");
- def->raviV_op_concatF = def->raviF->addExternFunction(
- def->types->raviV_op_concatT, reinterpret_cast(&raviV_op_concat),
- "raviV_op_concat");
- def->raviV_op_closureF = def->raviF->addExternFunction(
- def->types->raviV_op_closureT,
- reinterpret_cast(&raviV_op_closure), "raviV_op_closure");
- def->raviV_op_varargF = def->raviF->addExternFunction(
- def->types->raviV_op_varargT, reinterpret_cast(&raviV_op_vararg),
- "raviV_op_vararg");
- def->raviH_set_intF = def->raviF->addExternFunction(
- def->types->raviH_set_intT, reinterpret_cast(&raviH_set_int),
- "raviH_set_int");
- def->raviH_set_floatF = def->raviF->addExternFunction(
- def->types->raviH_set_floatT, reinterpret_cast(&raviH_set_float),
- "raviH_set_float");
- def->raviV_op_shlF = def->raviF->addExternFunction(
- def->types->raviV_op_shlT, reinterpret_cast(&raviV_op_shl),
- "raviV_op_shl");
- def->raviV_op_shrF = def->raviF->addExternFunction(
- def->types->raviV_op_shrT, reinterpret_cast(&raviV_op_shr),
- "raviV_op_shr");
- def->raviV_op_borF = def->raviF->addExternFunction(
- def->types->raviV_op_borT, reinterpret_cast(&raviV_op_bor),
- "raviV_op_bor");
- def->raviV_op_bxorF = def->raviF->addExternFunction(
- def->types->raviV_op_bxorT, reinterpret_cast(&raviV_op_bxor),
- "raviV_op_bxor");
- def->raviV_op_bandF = def->raviF->addExternFunction(
- def->types->raviV_op_bandT, reinterpret_cast(&raviV_op_band),
- "raviV_op_band");
- def->raviV_op_bnotF = def->raviF->addExternFunction(
- def->types->raviV_op_bnotT, reinterpret_cast(&raviV_op_bnot),
- "raviV_op_bnot");
- def->raviV_op_addF = def->raviF->addExternFunction(
- def->types->raviV_op_addT, reinterpret_cast(&raviV_op_add),
- "raviV_op_add");
- def->raviV_op_subF = def->raviF->addExternFunction(
- def->types->raviV_op_subT, reinterpret_cast(&raviV_op_sub),
- "raviV_op_sub");
- def->raviV_op_mulF = def->raviF->addExternFunction(
- def->types->raviV_op_mulT, reinterpret_cast(&raviV_op_mul),
- "raviV_op_mul");
- def->raviV_op_divF = def->raviF->addExternFunction(
- def->types->raviV_op_divT, reinterpret_cast(&raviV_op_div),
- "raviV_op_div");
- def->raviV_op_setupvaliF = def->raviF->addExternFunction(
- def->types->raviV_op_setupvaliT,
- reinterpret_cast(&raviV_op_setupvali), "raviV_op_setupvali");
- def->raviV_op_setupvalfF = def->raviF->addExternFunction(
- def->types->raviV_op_setupvalfT,
- reinterpret_cast(&raviV_op_setupvalf), "raviV_op_setupvalf");
- def->raviV_op_setupvalaiF = def->raviF->addExternFunction(
- def->types->raviV_op_setupvalaiT,
- reinterpret_cast(&raviV_op_setupvalai), "raviV_op_setupvalai");
- def->raviV_op_setupvalafF = def->raviF->addExternFunction(
- def->types->raviV_op_setupvalafT,
- reinterpret_cast(&raviV_op_setupvalaf), "raviV_op_setupvalaf");
- def->raviV_op_setupvaltF = def->raviF->addExternFunction(
- def->types->raviV_op_setupvaltT,
- reinterpret_cast(&raviV_op_setupvalt), "raviV_op_setupvalt");
- def->raviV_settable_sskeyF = def->raviF->addExternFunction(
- def->types->raviV_settable_sskeyT,
- reinterpret_cast(&raviV_settable_sskey), "raviV_settable_sskey");
- def->raviV_gettable_sskeyF = def->raviF->addExternFunction(
- def->types->raviV_gettable_sskeyT,
- reinterpret_cast(&raviV_gettable_sskey), "raviV_gettable_sskey");
- def->raviV_settable_iF = def->raviF->addExternFunction(
- def->types->raviV_settable_iT,
- reinterpret_cast(&raviV_settable_i), "raviV_settable_i");
- def->raviV_gettable_iF = def->raviF->addExternFunction(
- def->types->raviV_gettable_iT,
- reinterpret_cast(&raviV_gettable_i), "raviV_gettable_i");
- def->raviV_op_totypeF = def->raviF->addExternFunction(
- def->types->raviV_op_totypeT, reinterpret_cast(&raviV_op_totype),
- "raviV_op_totype");
-#ifdef RAVI_DEFER_STATEMENT
- def->raviV_op_deferF = def->raviF->addExternFunction(
- def->types->raviV_op_deferT, reinterpret_cast(&raviV_op_defer),
- "raviV_op_defer");
-#endif
-#if 0
- // DEBUG routines
- def->ravi_dump_valueF = def->raviF->addExternFunction(
- def->types->ravi_dump_valueT, reinterpret_cast(&ravi_dump_value),
- "ravi_dump_value");
- def->ravi_dump_stackF = def->raviF->addExternFunction(
- def->types->ravi_dump_stackT, reinterpret_cast(&ravi_dump_stack),
- "ravi_dump_stack");
- def->ravi_dump_stacktopF = def->raviF->addExternFunction(
- def->types->ravi_dump_stacktopT,
- reinterpret_cast(&ravi_dump_stacktop), "ravi_dump_stacktop");
-#endif
- def->ravi_debug_traceF = def->raviF->addExternFunction(
- def->types->ravi_debug_traceT,
- reinterpret_cast(&raviV_debug_trace), "raviV_debug_trace");
-
- // Create printf declaration
- std::vector args;
- args.push_back(def->types->C_pcharT);
- // accepts a char*, is vararg, and returns int
- llvm::FunctionType *printfType =
- llvm::FunctionType::get(def->types->C_intT, args, true);
- def->printfFunc =
- def->raviF->module()->getOrInsertFunction("printf", printfType);
-
- // stdc fmod declaration
- args.clear();
- args.push_back(def->types->lua_NumberT);
- args.push_back(def->types->lua_NumberT);
- llvm::FunctionType *fmodType =
- llvm::FunctionType::get(def->types->lua_NumberT, args, false);
-#ifdef LUA_32BITS
- def->fmodFunc = def->raviF->module()->getOrInsertFunction("fmodf", fmodType);
-#else
- def->fmodFunc = def->raviF->module()->getOrInsertFunction("fmod", fmodType);
-#endif
- llvm::FunctionType *powType =
- llvm::FunctionType::get(def->types->lua_NumberT, args, false);
-#ifdef LUA_32BITS
- def->powFunc = def->raviF->module()->getOrInsertFunction("powf", powType);
-#else
- def->powFunc = def->raviF->module()->getOrInsertFunction("pow", powType);
-#endif
- // stdc floor declaration
- args.clear();
- args.push_back(def->types->lua_NumberT);
- llvm::FunctionType *floorType =
- llvm::FunctionType::get(def->types->lua_NumberT, args, false);
-#ifdef LUA_32BITS
- def->floorFunc =
- def->raviF->module()->getOrInsertFunction("floorf", floorType);
-#else
- def->floorFunc =
- def->raviF->module()->getOrInsertFunction("floor", floorType);
-#endif
-}
-
-void RaviCodeGenerator::link_block(RaviFunctionDef *def, int pc) {
- // If we are on a jump target then check if this is a forloop
- // target. Forloop targets are special as they use computed goto
- // to branch to one of 4 possible labels. That is why we test for
- // jmp2 below.
- // We need to check whether current block is already terminated -
- // this can be because of a return or break or goto within the forloop
- // body
- if (def->jmp_targets[pc].jmp2 &&
- !def->builder->GetInsertBlock()->getTerminator()) {
- // Handle special case for body of FORLOOP
- auto b = def->builder->CreateLoad(def->jmp_targets[pc].forloop_branch);
- auto idb = def->builder->CreateIndirectBr(b, 4);
- idb->addDestination(def->jmp_targets[pc].jmp1);
- idb->addDestination(def->jmp_targets[pc].jmp2);
- idb->addDestination(def->jmp_targets[pc].jmp3);
- idb->addDestination(def->jmp_targets[pc].jmp4);
- // As we have terminated the block the code below will not
- // add the branch instruction, but we still need to create the new
- // block which is handled below.
- }
- // If the current bytecode offset pc is on a jump target
- // then we need to insert the block we previously created in
- // scan_jump_targets()
- // and make it the current insert block; also if the previous block
- // is unterminated then we simply provide a branch from previous block to the
- // new block
- if (def->jmp_targets[pc].jmp1) {
- // We are on a jump target
- // Get the block we previously created scan_jump_targets
- llvm::BasicBlock *block = def->jmp_targets[pc].jmp1;
- if (!def->builder->GetInsertBlock()->getTerminator()) {
- // Previous block not terminated so branch to the
- // new block
- def->builder->CreateBr(block);
- }
- // Now add the new block and make it current
- def->f->getBasicBlockList().push_back(block);
- def->builder->SetInsertPoint(block);
- }
-}
-
-llvm::Value *RaviCodeGenerator::emit_gep_upvals(RaviFunctionDef *def,
- int offset) {
- return emit_gep(def, "upvals", def->p_LClosure, 0, 6, offset);
-}
-
-llvm::Instruction *RaviCodeGenerator::emit_load_pupval(RaviFunctionDef *def,
- llvm::Value *ppupval) {
- llvm::Instruction *ins = def->builder->CreateLoad(ppupval);
- ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_ppointerT);
- return ins;
-}
-
-// Load upval->v
-llvm::Instruction *RaviCodeGenerator::emit_load_upval_v(
- RaviFunctionDef *def, llvm::Instruction *pupval) {
- llvm::Value *p_v = emit_gep_upval_v(def, pupval);
- llvm::Instruction *v = def->builder->CreateLoad(p_v);
- v->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_UpVal_vT);
- return v;
-}
-
-// Get &upval->v
-llvm::Value *RaviCodeGenerator::emit_gep_upval_v(RaviFunctionDef *def,
- llvm::Instruction *pupval) {
- return emit_gep(def, "v", pupval, 0, 0);
-}
-
-// Get &upval->value -> result is TValue *
-llvm::Value *RaviCodeGenerator::emit_gep_upval_value(
- RaviFunctionDef *def, llvm::Instruction *pupval) {
-#ifdef RAVI_DEFER_STATEMENT
- return emit_gep(def, "value", pupval, 0, 3);
-#else
- return emit_gep(def, "value", pupval, 0, 2);
-#endif
-}
-
-bool RaviCodeGenerator::compile(lua_State *L, Proto *p,
- std::shared_ptr module,
- ravi_compile_options_t *options) {
- if (p->ravi_jit.jit_status == RAVI_JIT_COMPILED) return true;
-
- // Avoid recursive calls
- if (module->owner()->get_compiling_flag()) return false;
-
- bool doVerify = module->owner()->get_validation() != 0;
- bool omitArrayGetRangeCheck =
- options ? options->omit_array_get_range_check != 0 : 0;
-
- if (p->ravi_jit.jit_status != RAVI_JIT_NOT_COMPILED || !canCompile(p)) {
- // fprintf(stderr, "failed to compile!\n");
- return false;
- }
-
- llvm::LLVMContext &context = jitState_->context();
- llvm::IRBuilder<> builder(context);
-
- RaviFunctionDef definition = {0};
- RaviFunctionDef *def = &definition;
-
- auto f = create_function(p, module, builder, def);
- if (!f) {
- p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE; // can't compile
- return false;
- }
-
- // Set flag so we can avoid recursive calls
- module->owner()->set_compiling_flag(true);
-
- // The functions constants
- TValue *k = p->k;
-
- // Add extern declarations for Lua functions we need to call
- emit_extern_declarations(def);
- def->p = p;
-
- // Create BasicBlocks for all the jump targets in the Lua bytecode
- scan_jump_targets(def, p);
-
- // Get pointer to L->ci
- def->L_ci = emit_gep(def, "L_ci", def->L, 0, 6);
-
- // Load L->ci
- // This is the function's activation record / stack frame
- def->ci_val = builder.CreateLoad(def->L_ci);
- def->ci_val->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_luaState_ciT);
-
- // Get pointer to function's 'base' stack location
- // 'base' is the address relative to which all the
- // function registers are located
- def->Ci_base = emit_gep(def, "base", def->ci_val, 0, 4, 0);
-
- // We need to get hold of the constants table
- // which is located in the function definition
- // This is the line in lvm.c that says:
- // LClosure *cl = clLvalue(ci->func)
- def->p_LClosure = emit_gep_ci_func_value_gc_asLClosure(def);
-
- // Get pointer to the Proto* which is cl->p
- def->proto = emit_gep(def, "Proto", def->p_LClosure, 0, 5);
-
- // Load pointer to proto
- def->proto_ptr = builder.CreateLoad(def->proto);
- def->proto_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_LClosure_pT);
-
- // Obtain pointer to Proto->k
- def->proto_k = emit_gep(def, "k", def->proto_ptr, 0, 14);
-
- // Load pointer to k
- def->k_ptr = builder.CreateLoad(def->proto_k);
- def->k_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
- def->types->tbaa_Proto_kT);
-
- // emit_dump_stack(def, "Function entry-->");
-
- const Instruction *code = p->code;
- int pc, n = p->sizecode;
- for (pc = 0; pc < n; pc++) {
- link_block(def, pc);
- Instruction i = code[pc];
- OpCode op = GET_OPCODE(i);
- int A = GETARG_A(i);
- switch (op) {
- case OP_LOADK: {
- int Bx = GETARG_Bx(i);
- emit_LOADK(def, A, Bx, pc);
- } break;
- case OP_LOADKX: {
- // OP_LOADKX is followed by OP_EXTRAARG
- Instruction inst = code[++pc];
- int Ax = GETARG_Ax(inst);
- lua_assert(GET_OPCODE(inst) == OP_EXTRAARG);
- emit_LOADK(def, A, Ax, pc - 1);
- } break;
-
- case OP_CONCAT: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_CONCAT(def, A, B, C, pc);
- } break;
- case OP_CLOSURE: {
- int Bx = GETARG_Bx(i);
- emit_CLOSURE(def, A, Bx, pc);
- } break;
- case OP_VARARG: {
- int B = GETARG_B(i);
- emit_VARARG(def, A, B, pc);
- } break;
-
- case OP_LOADBOOL: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_LOADBOOL(def, A, B, C, pc + 2, pc);
- } break;
- case OP_MOVE: {
- int B = GETARG_B(i);
- emit_MOVE(def, A, B, pc);
- } break;
- case OP_RAVI_MOVEI: {
- int B = GETARG_B(i);
- emit_MOVEI(def, A, B, pc);
- } break;
- case OP_RAVI_MOVEF: {
- int B = GETARG_B(i);
- emit_MOVEF(def, A, B, pc);
- } break;
- case OP_RAVI_TOINT: {
- emit_TOINT(def, A, pc);
- } break;
- case OP_RAVI_TOFLT: {
- emit_TOFLT(def, A, pc);
- } break;
- case OP_RAVI_NEW_IARRAY: {
- emit_NEWARRAYINT(def, A, pc);
- } break;
- case OP_RAVI_NEW_FARRAY: {
- emit_NEWARRAYFLOAT(def, A, pc);
- } break;
- case OP_NEWTABLE: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_NEWTABLE(def, A, B, C, pc);
- } break;
- case OP_SETLIST: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- if (C == 0) {
- // OP_SETLIST is followed by OP_EXTRAARG
- Instruction inst = code[++pc];
- C = GETARG_Ax(inst);
- lua_assert(GET_OPCODE(inst) == OP_EXTRAARG);
- }
- emit_SETLIST(def, A, B, C, pc);
- } break;
- case OP_SELF:
- case OP_RAVI_SELF_SK: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- if (op == OP_RAVI_SELF_SK) { emit_SELF_SK(def, A, B, C, pc); }
- else {
- emit_SELF(def, A, B, C, pc);
- }
- } break;
- case OP_LEN: {
- int B = GETARG_B(i);
- emit_LEN(def, A, B, pc);
- } break;
-
- case OP_RETURN: {
- int B = GETARG_B(i);
- emit_RETURN(def, A, B, pc);
- } break;
- case OP_RAVI_EQ_II:
- case OP_RAVI_EQ_FF:
- case OP_RAVI_LT_II:
- case OP_RAVI_LT_FF:
- case OP_RAVI_LE_II:
- case OP_RAVI_LE_FF:
- case OP_LT:
- case OP_LE:
- case OP_EQ: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- OpCode compOperator = op;
- llvm::Constant *comparison_function =
- ((op == OP_EQ || op == OP_RAVI_EQ_II || op == OP_RAVI_EQ_FF)
- ? def->luaV_equalobjF
- : ((op == OP_LT || op == OP_RAVI_LT_II || op == OP_RAVI_LT_FF)
- ? def->luaV_lessthanF
- : def->luaV_lessequalF));
- // OP_EQ is followed by OP_JMP - we process this
- // along with OP_EQ
- pc++;
- i = code[pc];
- op = GET_OPCODE(i);
- lua_assert(op == OP_JMP);
- int sbx = GETARG_sBx(i);
- // j below is the jump target
- int j = sbx + pc + 1;
- emit_EQ(def, A, B, C, j, GETARG_A(i), comparison_function, compOperator,
- pc - 1);
- } break;
- case OP_TFORCALL: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- // OP_TFORCALL is followed by OP_TFORLOOP - we process this
- // along with OP_TFORCALL
- pc++;
- i = code[pc];
- op = GET_OPCODE(i);
- lua_assert(op == OP_TFORLOOP);
- int sbx = GETARG_sBx(i);
- // j below is the jump target
- int j = sbx + pc + 1;
- emit_TFORCALL(def, A, B, C, j, GETARG_A(i), pc - 1);
- } break;
- case OP_TFORLOOP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
- emit_TFORLOOP(def, A, j, pc);
- } break;
- case OP_NOT: {
- int B = GETARG_B(i);
- emit_NOT(def, A, B, pc);
- } break;
- case OP_RAVI_BNOT_I: {
- int B = GETARG_B(i);
- emit_BNOT_I(def, A, B, pc);
- } break;
- case OP_BNOT: {
- int B = GETARG_B(i);
- emit_BNOT(def, A, B, pc);
- } break;
- case OP_TEST: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- // OP_TEST is followed by OP_JMP - we process this
- // along with OP_EQ
- pc++;
- i = code[pc];
- op = GET_OPCODE(i);
- lua_assert(op == OP_JMP);
- int sbx = GETARG_sBx(i);
- // j below is the jump target
- int j = sbx + pc + 1;
- emit_TEST(def, A, B, C, j, GETARG_A(i), pc - 1);
- } break;
- case OP_TESTSET: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- // OP_TESTSET is followed by OP_JMP - we process this
- // along with OP_EQ
- pc++;
- i = code[pc];
- op = GET_OPCODE(i);
- lua_assert(op == OP_JMP);
- int sbx = GETARG_sBx(i);
- // j below is the jump target
- int j = sbx + pc + 1;
- emit_TESTSET(def, A, B, C, j, GETARG_A(i), pc - 1);
- } break;
-
- case OP_JMP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
- emit_JMP(def, A, j, pc);
- } break;
-
- case OP_RAVI_FORPREP_I1:
- case OP_RAVI_FORPREP_IP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
- emit_iFORPREP(def, A, j, op == OP_RAVI_FORPREP_I1, pc);
- } break;
- case OP_FORPREP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
-#if RAVI_CODEGEN_FORPREP2
- emit_FORPREP2(def, A, j, pc);
-#else
- emit_FORPREP(def, A, j, pc);
-#endif
- } break;
- case OP_RAVI_FORLOOP_I1:
- case OP_RAVI_FORLOOP_IP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
- emit_iFORLOOP(def, A, j, def->jmp_targets[pc], op == OP_RAVI_FORLOOP_I1,
- pc);
- } break;
- case OP_FORLOOP: {
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
-#if RAVI_CODEGEN_FORPREP2
- emit_FORLOOP2(def, A, j, def->jmp_targets[pc], pc);
-#else
- emit_FORLOOP(def, A, j, pc);
-#endif
- } break;
-
- case OP_LOADNIL: {
- int B = GETARG_B(i);
- emit_LOADNIL(def, A, B, pc);
- } break;
- case OP_RAVI_LOADFZ: {
- emit_LOADFZ(def, A, pc);
- } break;
- case OP_RAVI_LOADIZ: {
- emit_LOADIZ(def, A, pc);
- } break;
- case OP_TAILCALL:
- case OP_CALL: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_CALL(def, A, B, C, pc);
- } break;
-
- case OP_RAVI_SETFIELD:
- case OP_RAVI_TABLE_SETFIELD: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SETFIELD(def, A, B, C, pc);
- } break;
- case OP_RAVI_SETI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SETI(def, A, B, C, pc);
- } break;
- case OP_SETTABLE: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SETTABLE(def, A, B, C, pc);
- } break;
- case OP_RAVI_TABLE_GETFIELD: {
- int C = GETARG_C(i);
- int B = GETARG_B(i);
- lua_assert(ISK(C));
- TValue *kv = k + INDEXK(C);
- TString *key = tsvalue(kv);
- lua_assert(key->tt == LUA_TSHRSTR);
- emit_GETTABLE_S(def, A, B, C, pc, key);
- } break;
-
- case OP_RAVI_TABLE_SELF_SK: {
- int C = GETARG_C(i);
- int B = GETARG_B(i);
- lua_assert(ISK(C));
- TValue *kv = k + INDEXK(C);
- TString *key = tsvalue(kv);
- lua_assert(key->tt == LUA_TSHRSTR);
- emit_TABLE_SELF_SK(def, A, B, C, pc, key);
- } break;
- case OP_RAVI_GETI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_GETI(def, A, B, C, pc);
- } break;
- case OP_RAVI_GETFIELD: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- lua_assert(ISK(C));
- TValue *kv = k + INDEXK(C);
- TString *key = tsvalue(kv);
- lua_assert(key->tt == LUA_TSHRSTR);
- emit_GETFIELD(def, A, B, C, pc, key);
- } break;
- case OP_GETTABLE: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_GETTABLE(def, A, B, C, pc);
- } break;
- case OP_RAVI_IARRAY_GET: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_IARRAY_GET(def, A, B, C, omitArrayGetRangeCheck, pc);
- } break;
- case OP_RAVI_IARRAY_SETI:
- case OP_RAVI_IARRAY_SET: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_IARRAY_SET(def, A, B, C, op == OP_RAVI_IARRAY_SETI, pc);
- } break;
- case OP_RAVI_FARRAY_GET: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_FARRAY_GET(def, A, B, C, omitArrayGetRangeCheck, pc);
- } break;
- case OP_RAVI_FARRAY_SETF:
- case OP_RAVI_FARRAY_SET: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_FARRAY_SET(def, A, B, C, op == OP_RAVI_FARRAY_SETF, pc);
- } break;
- case OP_RAVI_TOTAB: {
- emit_TOARRAY(def, A, RAVI_TTABLE, "table expected", pc);
- } break;
- case OP_RAVI_TOIARRAY: {
- emit_TOARRAY(def, A, RAVI_TARRAYINT, "integer[] expected", pc);
- } break;
- case OP_RAVI_TOFARRAY: {
- emit_TOARRAY(def, A, RAVI_TARRAYFLT, "number[] expected", pc);
- } break;
- case OP_RAVI_TOSTRING: {
- emit_TOSTRING(def, A, pc);
- break;
- }
- case OP_RAVI_TOCLOSURE: {
- emit_TOCLOSURE(def, A, pc);
- break;
- }
- case OP_RAVI_TOTYPE: {
- int Bx = GETARG_Bx(i);
- emit_TOTYPE(def, A, Bx, pc);
- break;
- }
- case OP_RAVI_MOVEIARRAY: {
- int B = GETARG_B(i);
- emit_MOVEIARRAY(def, A, B, pc);
- } break;
- case OP_RAVI_MOVEFARRAY: {
- int B = GETARG_B(i);
- emit_MOVEFARRAY(def, A, B, pc);
- } break;
- case OP_RAVI_MOVETAB: {
- int B = GETARG_B(i);
- emit_MOVETAB(def, A, B, pc);
- } break;
-
- case OP_RAVI_GETTABUP_SK: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_GETTABUP_SK(def, A, B, C, pc);
- } break;
- case OP_GETTABUP: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_GETTABUP(def, A, B, C, pc);
- } break;
- case OP_GETUPVAL: {
- int B = GETARG_B(i);
- emit_GETUPVAL(def, A, B, pc);
- } break;
- case OP_SETTABUP: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SETTABUP(def, A, B, C, pc);
- } break;
- case OP_SETUPVAL: {
- int B = GETARG_B(i);
- emit_SETUPVAL(def, A, B, pc);
- } break;
-
- case OP_RAVI_SETUPVALI: {
- int B = GETARG_B(i);
- emit_SETUPVAL_Specific(def, A, B, pc, OP_RAVI_SETUPVALI,
- def->raviV_op_setupvaliF);
- } break;
- case OP_RAVI_SETUPVALF: {
- int B = GETARG_B(i);
- emit_SETUPVAL_Specific(def, A, B, pc, OP_RAVI_SETUPVALF,
- def->raviV_op_setupvalfF);
- } break;
- case OP_RAVI_SETUPVAL_IARRAY: {
- int B = GETARG_B(i);
- emit_SETUPVAL_Specific(def, A, B, pc, OP_RAVI_SETUPVAL_IARRAY,
- def->raviV_op_setupvalaiF);
- } break;
- case OP_RAVI_SETUPVAL_FARRAY: {
- int B = GETARG_B(i);
- emit_SETUPVAL_Specific(def, A, B, pc, OP_RAVI_SETUPVAL_FARRAY,
- def->raviV_op_setupvalafF);
- } break;
- case OP_RAVI_SETUPVALT: {
- int B = GETARG_B(i);
- emit_SETUPVAL_Specific(def, A, B, pc, OP_RAVI_SETUPVALT,
- def->raviV_op_setupvaltF);
- } break;
-
- case OP_RAVI_BXOR_II:
- case OP_RAVI_BOR_II:
- case OP_RAVI_BAND_II: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_BITWISE_BINARY_OP(def, op, A, B, C, pc);
- } break;
-
- case OP_BAND:
- case OP_BOR:
- case OP_BXOR: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_BOR_BXOR_BAND(def, op, A, B, C, pc);
- } break;
-
- case OP_SHR:
- case OP_SHL:
- case OP_RAVI_SHL_II:
- case OP_RAVI_SHR_II: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_BITWISE_SHIFT_OP(def, op, A, B, C, pc);
- } break;
-
- case OP_ADD: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ARITH(def, A, B, C, OP_ADD, TM_ADD, pc);
- } break;
- case OP_RAVI_ADDFF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ADDFF(def, A, B, C, pc);
- } break;
- case OP_RAVI_ADDFI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ADDFI(def, A, B, C, pc);
- } break;
- case OP_RAVI_ADDII: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ADDII(def, A, B, C, pc);
- } break;
-
- case OP_SUB: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ARITH(def, A, B, C, OP_SUB, TM_SUB, pc);
- } break;
- case OP_RAVI_SUBFF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SUBFF(def, A, B, C, pc);
- } break;
- case OP_RAVI_SUBFI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SUBFI(def, A, B, C, pc);
- } break;
- case OP_RAVI_SUBIF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SUBIF(def, A, B, C, pc);
- } break;
- case OP_RAVI_SUBII: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_SUBII(def, A, B, C, pc);
- } break;
-
- case OP_MUL: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ARITH(def, A, B, C, OP_MUL, TM_MUL, pc);
- } break;
- case OP_RAVI_MULFF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_MULFF(def, A, B, C, pc);
- } break;
- case OP_RAVI_MULFI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_MULFI(def, A, B, C, pc);
- } break;
- case OP_RAVI_MULII: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_MULII(def, A, B, C, pc);
- } break;
-
- case OP_DIV: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_ARITH(def, A, B, C, OP_DIV, TM_DIV, pc);
- } break;
- case OP_RAVI_DIVFF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_DIVFF(def, A, B, C, pc);
- } break;
- case OP_RAVI_DIVFI: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_DIVFI(def, A, B, C, pc);
- } break;
- case OP_RAVI_DIVIF: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_DIVIF(def, A, B, C, pc);
- } break;
- case OP_RAVI_DIVII: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_DIVII(def, A, B, C, pc);
- } break;
-
- case OP_MOD: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_MOD(def, A, B, C, pc);
- } break;
- case OP_IDIV: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_IDIV(def, A, B, C, pc);
- } break;
- case OP_POW: {
- int B = GETARG_B(i);
- int C = GETARG_C(i);
- emit_POW(def, A, B, C, pc);
- } break;
- case OP_UNM: {
- int B = GETARG_B(i);
- emit_UNM(def, A, B, pc);
- } break;
-#ifdef RAVI_DEFER_STATEMENT
- case OP_RAVI_DEFER: {
- emit_DEFER(def, A, pc);
- } break;
-#endif
- default: {
- fprintf(stderr, "Unexpected bytecode %d\n", op);
- abort();
- }
- }
- }
- if (doVerify && llvm::verifyFunction(*f->function(), &llvm::errs())) {
- f->dump();
- fprintf(stderr, "LLVM Code Verification failed\n");
- exit(1);
- }
-
- ravi::RaviJITFunction *llvm_func = f.release();
- p->ravi_jit.jit_data = reinterpret_cast(llvm_func);
- p->ravi_jit.jit_function = nullptr;
- p->ravi_jit.jit_status = RAVI_JIT_COMPILED;
-
- module->owner()->set_compiling_flag(false);
-
- return llvm_func != nullptr;
-}
-
-void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
- // We need to pre-create blocks for jump targets so that we
- // can generate branch instructions in the code
- def->jmp_targets.clear();
- const Instruction *code = p->code;
- int pc, n = p->sizecode;
- def->jmp_targets.resize(n);
- for (pc = 0; pc < n; pc++) {
- Instruction i = code[pc];
- OpCode op = GET_OPCODE(i);
- switch (op) {
- case OP_LOADBOOL: {
- int C = GETARG_C(i);
- int j = pc + 2; // jump target
- if (C && !def->jmp_targets[j].jmp1)
- def->jmp_targets[j].jmp1 =
- llvm::BasicBlock::Create(def->jitState->context(), "loadbool");
- } break;
- case OP_JMP:
- case OP_RAVI_FORPREP_IP:
- case OP_RAVI_FORPREP_I1:
- case OP_RAVI_FORLOOP_IP:
- case OP_RAVI_FORLOOP_I1:
- case OP_FORLOOP:
- case OP_FORPREP:
- case OP_TFORLOOP: {
- const char *targetname = nullptr;
- char temp[80];
- if (op == OP_JMP)
- targetname = "jmp";
- else if (op == OP_FORLOOP || op == OP_RAVI_FORLOOP_IP ||
- op == OP_RAVI_FORLOOP_I1)
- targetname = "forbody";
- else if (op == OP_FORPREP || op == OP_RAVI_FORPREP_IP ||
- op == OP_RAVI_FORPREP_I1)
-#if RAVI_CODEGEN_FORPREP2
- targetname = "forloop_ilt";
-#else
- targetname = "forloop";
-#endif
- else
- targetname = "tforbody";
- int sbx = GETARG_sBx(i);
- int j = sbx + pc + 1;
- // We append the Lua bytecode location to help debug the IR
- snprintf(temp, sizeof temp, "%s%d_", targetname, j + 1);
- //
- if (!def->jmp_targets[j].jmp1) {
- def->jmp_targets[j].jmp1 =
- llvm::BasicBlock::Create(def->jitState->context(), temp);
- }
-#if RAVI_CODEGEN_FORPREP2
- if (op == OP_FORPREP) {
- lua_assert(def->jmp_targets[j].jmp2 == nullptr);
- // first target (created above) is for int < limit
- // Second target is for int > limit
- snprintf(temp, sizeof temp, "%s%d_", "forloop_igt", j + 1);
- def->jmp_targets[j].jmp2 =
- llvm::BasicBlock::Create(def->jitState->context(), temp);
- // Third target is for float < limit
- snprintf(temp, sizeof temp, "%s%d_", "forloop_flt", j + 1);
- def->jmp_targets[j].jmp3 =
- llvm::BasicBlock::Create(def->jitState->context(), temp);
- // Fourth target is for float > limit
- snprintf(temp, sizeof temp, "%s%d_", "forloop_fgt", j + 1);
- def->jmp_targets[j].jmp4 =
- llvm::BasicBlock::Create(def->jitState->context(), temp);
- }
-#endif
- } break;
- default: break;
- }
- }
-}
-} // namespace ravi
diff --git a/src/ravi_llvmcomp.cpp b/src/ravi_llvmcomp.cpp
deleted file mode 100644
index e613989..0000000
--- a/src/ravi_llvmcomp.cpp
+++ /dev/null
@@ -1,339 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-namespace ravi {
-
-// Although the name is EQ this actually
-// implements EQ, LE and LT - by using the supplied lua function to call.
-void RaviCodeGenerator::emit_EQ(RaviFunctionDef *def, int A, int B, int C,
- int j, int jA, llvm::Constant *callee,
- OpCode opCode, int pc) {
- // case OP_EQ: {
- // TValue *rb = RKB(i);
- // TValue *rc = RKC(i);
- // Protect(
- // if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
- // ci->u.l.savedpc++;
- // else
- // donextjump(ci);
- // )
- // } break;
-
- bool traced = emit_debug_trace(def, opCode, pc);
-
- // Load pointer to base
- emit_load_base(def);
-
- // Get pointer to register B
- llvm::Value *regB = emit_gep_register_or_constant(def, B);
- // Get pointer to register C
- llvm::Value *regC = emit_gep_register_or_constant(def, C);
-
- llvm::Value *result = NULL;
- switch (opCode) {
-
- case OP_RAVI_LT_II:
- case OP_RAVI_LE_II:
- case OP_RAVI_EQ_II: {
- llvm::Instruction *p1 = emit_load_reg_i(def, regB);
- llvm::Instruction *p2 = emit_load_reg_i(def, regC);
-
- switch (opCode) {
- case OP_RAVI_EQ_II:
- result = def->builder->CreateICmpEQ(p1, p2, "EQ_II_result");
- break;
- case OP_RAVI_LT_II:
- result = def->builder->CreateICmpSLT(p1, p2, "LT_II_result");
- break;
- case OP_RAVI_LE_II:
- result = def->builder->CreateICmpSLE(p1, p2, "LE_II_result");
- break;
- default:
- assert(0);
- }
- result =
- def->builder->CreateZExt(result, def->types->C_intT, "II_result_int");
-
- } break;
-
- case OP_RAVI_LT_FF:
- case OP_RAVI_LE_FF:
- case OP_RAVI_EQ_FF: {
- llvm::Instruction *p1 = emit_load_reg_n(def, regB);
- llvm::Instruction *p2 = emit_load_reg_n(def, regC);
-
- switch (opCode) {
- case OP_RAVI_EQ_FF:
- result = def->builder->CreateFCmpOEQ(p1, p2, "EQ_FF_result");
- break;
- case OP_RAVI_LT_FF:
- result = def->builder->CreateFCmpULT(p1, p2, "LT_FF_result");
- break;
- case OP_RAVI_LE_FF:
- result = def->builder->CreateFCmpULE(p1, p2, "LE_FF_result");
- break;
- default:
- assert(0);
- }
- result =
- def->builder->CreateZExt(result, def->types->C_intT, "FF_result_int");
-
- } break;
-
- default:
- // As below may invoke metamethod we need to set savedpc
- if (!traced) emit_update_savedpc(def, pc);
- // Call luaV_equalobj with register B and C
- result = CreateCall3(def->builder, callee, def->L, regB, regC);
- }
-
- // Test if result is equal to operand A
- llvm::Value *result_eq_A = def->builder->CreateICmpEQ(
- result, llvm::ConstantInt::get(def->types->C_intT, A));
-
- // If result == A then we need to execute the next statement which is a jump
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.then", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else");
- def->builder->CreateCondBr(result_eq_A, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
- if (jA > 0) {
- // jA is the A operand of the Jump instruction
-
- // Reload pointer to base as the call to luaV_equalobj() may
- // have invoked a Lua function and as a result the stack may have
- // been reallocated - so the previous base pointer could be stale
- emit_load_base(def);
-
- // base + a - 1
- llvm::Value *val = emit_gep_register(def, jA - 1);
-#ifdef RAVI_DEFER_STATEMENT
- if (!traced)
- emit_update_savedpc(def, pc);
- // Call luaF_close
- CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
-#else
- CreateCall2(def->builder, def->luaF_closeF, def->L, val);
-#endif
- }
- // Do the jump
- def->builder->CreateBr(def->jmp_targets[j].jmp1);
- // Add the else block and make it current so that the next instruction flows
- // here
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-}
-
-llvm::Value *RaviCodeGenerator::emit_boolean_testfalse(RaviFunctionDef *def,
- llvm::Value *reg,
- bool donot) {
- // (isnil() || isbool() && b == 0)
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *var = TmpB.CreateAlloca(
- llvm::Type::getInt1Ty(def->jitState->context()), nullptr, "b");
-
- llvm::Value *type = emit_load_type(def, reg);
-
- // Test if type == LUA_TNIL (0)
- llvm::Value *isnil = emit_is_value_of_type(def, type, LUA__TNIL, "is.nil");
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.nil", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "not.nil");
- llvm::BasicBlock *end_block =
- llvm::BasicBlock::Create(def->jitState->context(), "end");
- def->builder->CreateCondBr(isnil, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- emit_store_local_int(def, isnil, var);
- def->builder->CreateBr(end_block);
-
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
- // value is not nil
- // so check if bool and b == 0
-
- // Test if type == LUA_TBOOLEAN
- llvm::Value *isbool =
- emit_is_value_of_type(def, type, LUA__TBOOLEAN, "is.boolean");
- // Test if bool value == 0
- llvm::Value *bool_value = emit_load_reg_b(def, reg);
- llvm::Value *boolzero =
- def->builder->CreateICmpEQ(bool_value, def->types->kInt[0]);
- // Test type == LUA_TBOOLEAN && bool value == 0
- llvm::Value *andvalue = def->builder->CreateAnd(isbool, boolzero);
-
- emit_store_local_int(def, andvalue, var);
- def->builder->CreateBr(end_block);
-
- def->f->getBasicBlockList().push_back(end_block);
- def->builder->SetInsertPoint(end_block);
-
- llvm::Value *result = nullptr;
- if (donot) {
- auto ins = emit_load_local_int(def, var);
- result = def->builder->CreateNot(ins);
- } else {
- auto ins = emit_load_local_int(def, var);
- result = ins;
- }
-
- return result;
-}
-
-void RaviCodeGenerator::emit_TEST(RaviFunctionDef *def, int A, int B, int C,
- int j, int jA, int pc) {
-
- // case OP_TEST: {
- // if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
- // ci->u.l.savedpc++;
- // else
- // donextjump(ci);
- // } break;
-
- bool traced = emit_debug_trace(def, OP_TEST, pc);
- // Load pointer to base
- emit_load_base(def);
-
- // Get pointer to register A
- llvm::Value *ra = emit_gep_register(def, A);
- // v = C ? is_false(ra) : !is_false(ra)
- llvm::Value *v = C ? emit_boolean_testfalse(def, ra, false)
- : emit_boolean_testfalse(def, ra, true);
-
- // Test NOT v
- llvm::Value *result = def->builder->CreateNot(v);
- // If !v then we need to execute the next statement which is a jump
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.then", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else");
- def->builder->CreateCondBr(result, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
- if (jA > 0) {
- // jA is the A operand of the Jump instruction
-
- // base + a - 1
- llvm::Value *val = emit_gep_register(def, jA - 1);
-#ifdef RAVI_DEFER_STATEMENT
- if (!traced)
- emit_update_savedpc(def, pc);
- // Call luaF_close
- CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
-#else
- CreateCall2(def->builder, def->luaF_closeF, def->L, val);
-#endif
- }
- // Do the jump
- def->builder->CreateBr(def->jmp_targets[j].jmp1);
-
- // Add the else block and make it current so that the next instruction flows
- // here
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-}
-
-void RaviCodeGenerator::emit_NOT(RaviFunctionDef *def, int A, int B, int pc) {
- // case OP_NOT: {
- // TValue *rb = RB(i);
- // int res = l_isfalse(rb); /* next assignment may change this value */
- // setbvalue(ra, res);
- // } break;
- emit_debug_trace(def, OP_NOT, pc);
- emit_load_base(def);
- // Get pointer to register B
- llvm::Value *rb = emit_gep_register(def, B);
- llvm::Value *v = emit_boolean_testfalse(def, rb, false);
- llvm::Value *result = def->builder->CreateZExt(v, def->types->C_intT, "i");
- llvm::Value *ra = emit_gep_register(def, A);
- emit_store_reg_b_withtype(def, result, ra);
-}
-
-void RaviCodeGenerator::emit_TESTSET(RaviFunctionDef *def, int A, int B, int C,
- int j, int jA, int pc) {
-
- // case OP_TESTSET: {
- // TValue *rb = RB(i);
- // if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
- // ci->u.l.savedpc++;
- // else {
- // setobjs2s(L, ra, rb);
- // donextjump(ci);
- // }
- // } break;
-
- bool traced = emit_debug_trace(def, OP_TESTSET, pc);
- // Load pointer to base
- emit_load_base(def);
-
- // Get pointer to register B
- llvm::Value *rb = emit_gep_register(def, B);
- // v = C ? is_false(ra) : !is_false(ra)
- llvm::Value *v = C ? emit_boolean_testfalse(def, rb, false)
- : emit_boolean_testfalse(def, rb, true);
-
- // Test NOT v
- llvm::Value *result = def->builder->CreateNot(v);
- // If !v then we need to execute the next statement which is a jump
- llvm::BasicBlock *then_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.then", def->f);
- llvm::BasicBlock *else_block =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else");
- def->builder->CreateCondBr(result, then_block, else_block);
- def->builder->SetInsertPoint(then_block);
-
- // Get pointer to register A
- llvm::Value *ra = emit_gep_register(def, A);
- emit_assign(def, ra, rb);
-
- // if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
- if (jA > 0) {
- // jA is the A operand of the Jump instruction
-
- // base + a - 1
- llvm::Value *val = emit_gep_register(def, jA - 1);
-#ifdef RAVI_DEFER_STATEMENT
- if (!traced)
- emit_update_savedpc(def, pc);
- // Call luaF_close
- CreateCall3(def->builder, def->luaF_closeF, def->L, val, def->types->kInt[LUA_OK]);
-#else
- CreateCall2(def->builder, def->luaF_closeF, def->L, val);
-#endif
- }
- // Do the jump
- def->builder->CreateBr(def->jmp_targets[j].jmp1);
-
- // Add the else block and make it current so that the next instruction flows
- // here
- def->f->getBasicBlockList().push_back(else_block);
- def->builder->SetInsertPoint(else_block);
-}
-}
diff --git a/src/ravi_llvmforloop.cpp b/src/ravi_llvmforloop.cpp
deleted file mode 100644
index 0a69c54..0000000
--- a/src/ravi_llvmforloop.cpp
+++ /dev/null
@@ -1,454 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-namespace ravi {
-
-void RaviCodeGenerator::emit_FORLOOP2(RaviFunctionDef *def, int A, int pc,
- RaviBranchDef &b, int pc1) {
-
- // 7[1] FORLOOP 1 - 2; to 6
- // if (ttisinteger(ra)) { /* integer loop? */
- // lua_Integer step = ivalue(ra + 2);
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- // lua_Integer limit = ivalue(ra + 1);
- // if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- // setivalue(ra, idx); /* update internal index... */
- // setivalue(ra + 3, idx); /* ...and external index */
- // }
- //}
- // else { /* floating loop */
- // lua_Number step = fltvalue(ra + 2);
- // lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
- // lua_Number limit = fltvalue(ra + 1);
- // if (luai_numlt(0, step) ? luai_numle(idx, limit)
- // : luai_numle(limit, idx)) {
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- // setfltvalue(ra, idx); /* update internal index... */
- // setfltvalue(ra + 3, idx); /* ...and external index */
- // }
- //}
-
- emit_debug_trace(def, OP_FORLOOP, pc1);
-
- // We are in b.jmp1 as this is already the current block
- lua_assert(def->builder->GetInsertBlock() == b.jmp1);
-
- // Obtain pointers to the value.i field
- llvm::Value *step_int_ptr = b.istep;
- llvm::Value *idx_int_ptr = b.iidx;
- llvm::Value *limit_int_ptr = b.ilimit;
- // Obtain pointers to the value.n field
- llvm::Value *step_double_ptr = b.fstep;
- llvm::Value *idx_double_ptr = b.fidx;
- llvm::Value *limit_double_ptr = b.flimit;
-
- // Create the done block
- llvm::BasicBlock *exit_block =
- llvm::BasicBlock::Create(def->jitState->context(), "exit_iforloop");
-
- // INTEGER CASE
-
- // lua_Integer step = ivalue(ra + 2);
- llvm::Instruction *step_int_value = emit_load_local_n(def, step_int_ptr);
-
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- llvm::Instruction *idx_int_value = emit_load_local_n(def, idx_int_ptr);
- llvm::Value *new_idx = def->builder->CreateAdd(step_int_value, idx_int_value,
- "next.idx", false, true);
- emit_store_local_n(def, new_idx, idx_int_ptr);
-
- // lua_Integer limit = ivalue(ra + 1);
- llvm::Instruction *limit_int_value = emit_load_local_n(def, limit_int_ptr);
-
- // idx > limit?
- llvm::Value *new_idx_gt_limit =
- def->builder->CreateICmpSGT(new_idx, limit_int_value, "idx.gt.limit");
-
- // If idx > limit we are done
- llvm::BasicBlock *update_block =
- llvm::BasicBlock::Create(def->jitState->context(), "updatei");
- def->builder->CreateCondBr(new_idx_gt_limit, exit_block, update_block);
-
- // NOW INTEGER step < 0
-
- def->f->getBasicBlockList().push_back(b.jmp2);
- def->builder->SetInsertPoint(b.jmp2);
-
- step_int_value = emit_load_local_n(def, step_int_ptr);
-
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- idx_int_value = emit_load_local_n(def, idx_int_ptr);
- new_idx = def->builder->CreateAdd(step_int_value, idx_int_value, "next.idx",
- false, true);
- emit_store_local_n(def, new_idx, idx_int_ptr);
-
- // lua_Integer limit = ivalue(ra + 1);
- limit_int_value = emit_load_local_n(def, limit_int_ptr);
-
- // limit > idx?
- llvm::Value *limit_gt_idx =
- def->builder->CreateICmpSGT(limit_int_value, new_idx, "limit.gt.idx");
-
- // If limit > idx we are done
- def->builder->CreateCondBr(limit_gt_idx, exit_block, update_block);
-
- // Merge into update block
- def->f->getBasicBlockList().push_back(update_block);
- def->builder->SetInsertPoint(update_block);
-
- emit_load_base(def);
-
- llvm::Value *rvar = emit_gep_register(def, A + 3);
-
- // setivalue(ra + 3, idx); /* ...and external index */
- idx_int_value = emit_load_local_n(def, idx_int_ptr);
-
- emit_store_reg_i_withtype(def, idx_int_value, rvar);
-
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- // FLOATING CASE
-
- def->f->getBasicBlockList().push_back(b.jmp3);
- def->builder->SetInsertPoint(b.jmp3);
-
- // lua_Number step = fltvalue(ra + 2);
- llvm::Instruction *step_double_value =
- emit_load_local_n(def, step_double_ptr);
-
- // lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
- llvm::Instruction *idx_double_value = emit_load_local_n(def, idx_double_ptr);
- new_idx =
- def->builder->CreateFAdd(step_double_value, idx_double_value, "next.idx");
- emit_store_local_n(def, new_idx, idx_double_ptr);
-
- // lua_Number limit = fltvalue(ra + 1);
- llvm::Instruction *limit_double_value =
- emit_load_local_n(def, limit_double_ptr);
-
- // step > 0?
- // idx > limit?
- new_idx_gt_limit =
- def->builder->CreateFCmpOGT(new_idx, limit_double_value, "idx.gt.limit");
-
- // If idx > limit we are done
- update_block = llvm::BasicBlock::Create(def->jitState->context(), "updatef");
- def->builder->CreateCondBr(new_idx_gt_limit, exit_block, update_block);
-
- def->f->getBasicBlockList().push_back(b.jmp4);
- def->builder->SetInsertPoint(b.jmp4);
-
- // lua_Number step = fltvalue(ra + 2);
- step_double_value = emit_load_local_n(def, step_double_ptr);
-
- // lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
- idx_double_value = emit_load_local_n(def, idx_double_ptr);
- new_idx =
- def->builder->CreateFAdd(step_double_value, idx_double_value, "next.idx");
- emit_store_local_n(def, new_idx, idx_double_ptr);
-
- // lua_Number limit = fltvalue(ra + 1);
- limit_double_value = emit_load_local_n(def, limit_double_ptr);
-
- // limit > idx?
- limit_gt_idx =
- def->builder->CreateFCmpOGT(limit_double_value, new_idx, "limit.gt.idx");
-
- // If limit > idx we are done
- def->builder->CreateCondBr(limit_gt_idx, exit_block, update_block);
-
- // Merge into update block
- def->f->getBasicBlockList().push_back(update_block);
- def->builder->SetInsertPoint(update_block);
-
- emit_load_base(def);
- rvar = emit_gep_register(def, A + 3);
-
- // setfltvalue(ra + 3, idx); /* ...and external index */
- idx_double_value = emit_load_local_n(def, idx_double_ptr);
-
- emit_store_reg_n_withtype(def, idx_double_value, rvar);
-
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- def->f->getBasicBlockList().push_back(exit_block);
- def->builder->SetInsertPoint(exit_block);
-}
-
-void RaviCodeGenerator::emit_FORLOOP(RaviFunctionDef *def, int A, int pc,
- int pc1) {
-
- // 7[1] FORLOOP 1 - 2; to 6
- // if (ttisinteger(ra)) { /* integer loop? */
- // lua_Integer step = ivalue(ra + 2);
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- // lua_Integer limit = ivalue(ra + 1);
- // if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- // setivalue(ra, idx); /* update internal index... */
- // setivalue(ra + 3, idx); /* ...and external index */
- // }
- //}
- // else { /* floating loop */
- // lua_Number step = fltvalue(ra + 2);
- // lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
- // lua_Number limit = fltvalue(ra + 1);
- // if (luai_numlt(0, step) ? luai_numle(idx, limit)
- // : luai_numle(limit, idx)) {
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- // setfltvalue(ra, idx); /* update internal index... */
- // setfltvalue(ra + 3, idx); /* ...and external index */
- // }
- //}
-
- emit_debug_trace(def, OP_FORLOOP, pc1);
-
- // Load pointer to base
- emit_load_base(def);
-
- // TValue *rinit = ra;
- // TValue *rlimit = ra + 1;
- // TValue *rstep = ra + 2;
- // TValue *rvar = ra + 3
- llvm::Value *rinit = emit_gep_register(def, A);
- llvm::Value *rlimit = emit_gep_register(def, A + 1);
- llvm::Value *rstep = emit_gep_register(def, A + 2);
- llvm::Value *rvar = emit_gep_register(def, A + 3);
-
- // Create the done block
- llvm::BasicBlock *exit_block =
- llvm::BasicBlock::Create(def->jitState->context(), "exit_forloop");
-
- // Is index an integer?
- llvm::Instruction *rinit_tt = emit_load_type(def, rinit);
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, rinit_tt, LUA__TNUMINT, "init.is.integer");
-
- // Setup if then else branch for integer
- llvm::BasicBlock *if_integer =
- llvm::BasicBlock::Create(def->jitState->context(), "if.integer", def->f);
- llvm::BasicBlock *else_integer =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.integer");
- def->builder->CreateCondBr(cmp1, if_integer, else_integer);
- def->builder->SetInsertPoint(if_integer);
-
- // INTEGER CASE
-
- // lua_Integer step = ivalue(ra + 2);
- llvm::Instruction *step_int_value = emit_load_reg_i(def, rstep);
-
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- llvm::Instruction *idx_int_value = emit_load_reg_i(def, rinit);
- llvm::Value *new_idx = def->builder->CreateAdd(step_int_value, idx_int_value,
- "next.idx", false, true);
-
- // lua_Integer limit = ivalue(ra + 1);
- llvm::Instruction *limit_int_value = emit_load_reg_i(def, rlimit);
-
- // step > 0?
- llvm::Value *step_gt_zero = def->builder->CreateICmpSGT(
- step_int_value, def->types->kluaInteger[0], "step.gt.zero");
-
- llvm::BasicBlock *step_gt_zero_true = llvm::BasicBlock::Create(
- def->jitState->context(), "step.gt.zero.true", def->f);
- llvm::BasicBlock *step_gt_zero_false =
- llvm::BasicBlock::Create(def->jitState->context(), "step.gt.zero.false");
- def->builder->CreateCondBr(step_gt_zero, step_gt_zero_true,
- step_gt_zero_false);
- def->builder->SetInsertPoint(step_gt_zero_true);
-
- // idx > limit?
- llvm::Value *new_idx_gt_limit =
- def->builder->CreateICmpSGT(new_idx, limit_int_value, "idx.gt.limit");
-
- // If idx > limit we are done
- llvm::BasicBlock *update_block =
- llvm::BasicBlock::Create(def->jitState->context(), "update");
- def->builder->CreateCondBr(new_idx_gt_limit, exit_block, update_block);
-
- def->f->getBasicBlockList().push_back(step_gt_zero_false);
- def->builder->SetInsertPoint(step_gt_zero_false);
-
- // limit > idx?
- llvm::Value *limit_gt_idx =
- def->builder->CreateICmpSGT(limit_int_value, new_idx, "limit.gt.idx");
-
- // If limit > idx we are done
- def->builder->CreateCondBr(limit_gt_idx, exit_block, update_block);
-
- // Merge into update block
- def->f->getBasicBlockList().push_back(update_block);
- def->builder->SetInsertPoint(update_block);
-
- // setivalue(ra, idx); /* update internal index... */
- emit_store_reg_i(def, new_idx, rinit);
-
- // setivalue(ra + 3, idx); /* ...and external index */
- emit_store_reg_i_withtype(def, new_idx, rvar);
-
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- // FLOATING CASE
-
- def->f->getBasicBlockList().push_back(else_integer);
- def->builder->SetInsertPoint(else_integer);
-
- // lua_Number step = fltvalue(ra + 2);
- llvm::Instruction *step_double_value = emit_load_reg_n(def, rstep);
-
- // lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
- llvm::Instruction *idx_double_value = emit_load_reg_n(def, rinit);
-
- new_idx =
- def->builder->CreateFAdd(step_double_value, idx_double_value, "next.idx");
-
- // lua_Number limit = fltvalue(ra + 1);
- llvm::Instruction *limit_double_value = emit_load_reg_n(def, rlimit);
-
- // step > 0?
- step_gt_zero = def->builder->CreateFCmpOGT(
- step_double_value, llvm::ConstantFP::get(def->types->lua_NumberT, 0.0),
- "step.gt.zero");
-
- step_gt_zero_true = llvm::BasicBlock::Create(def->jitState->context(),
- "step.gt.zero.true", def->f);
- step_gt_zero_false =
- llvm::BasicBlock::Create(def->jitState->context(), "step.gt.zero.false");
- def->builder->CreateCondBr(step_gt_zero, step_gt_zero_true,
- step_gt_zero_false);
- def->builder->SetInsertPoint(step_gt_zero_true);
-
- // idx > limit?
- new_idx_gt_limit =
- def->builder->CreateFCmpOGT(new_idx, limit_double_value, "idx.gt.limit");
-
- // If idx > limit we are done
- update_block = llvm::BasicBlock::Create(def->jitState->context(), "update");
- def->builder->CreateCondBr(new_idx_gt_limit, exit_block, update_block);
-
- def->f->getBasicBlockList().push_back(step_gt_zero_false);
- def->builder->SetInsertPoint(step_gt_zero_false);
-
- // limit > idx?
- limit_gt_idx =
- def->builder->CreateFCmpOGT(limit_double_value, new_idx, "limit.gt.idx");
-
- // If limit > idx we are done
- def->builder->CreateCondBr(limit_gt_idx, exit_block, update_block);
-
- // Merge into update block
- def->f->getBasicBlockList().push_back(update_block);
- def->builder->SetInsertPoint(update_block);
-
- // setfltvalue(ra, idx); /* update internal index... */
- emit_store_reg_n(def, new_idx, rinit);
-
- // setfltvalue(ra + 3, idx); /* ...and external index */
- emit_store_reg_n_withtype(def, new_idx, rvar);
-
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- def->f->getBasicBlockList().push_back(exit_block);
- def->builder->SetInsertPoint(exit_block);
-}
-
-void RaviCodeGenerator::emit_iFORLOOP(RaviFunctionDef *def, int A, int pc,
- RaviBranchDef &b, int step_one, int pc1) {
-
- // lua_Integer step = ivalue(ra + 2);
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- // lua_Integer limit = ivalue(ra + 1);
- // if (idx <= limit) {
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- // setivalue(ra, idx); /* update internal index... */
- // setivalue(ra + 3, idx); /* ...and external index */
- // }
-
- emit_debug_trace(def, step_one ? OP_RAVI_FORLOOP_I1 : OP_RAVI_FORLOOP_IP,
- pc1);
- // We are in b.jmp1 as this is already the current block
- lua_assert(def->builder->GetInsertBlock() == b.jmp1);
-
- // Obtain pointers to the value.i field
- llvm::Value *idx_int_ptr = b.iidx;
- llvm::Value *limit_int_ptr = b.ilimit;
-
- // Create the done block
- llvm::BasicBlock *exit_block =
- llvm::BasicBlock::Create(def->jitState->context(), "exit_iforloop");
-
- // lua_Integer idx = ivalue(ra) + step; /* increment index */
- llvm::Instruction *idx_int_value = emit_load_local_n(def, idx_int_ptr);
- llvm::Value *new_idx;
-
- if (!step_one) {
- // lua_Integer step = ivalue(ra + 2);
- llvm::Value *step_int_ptr = b.istep;
- llvm::Instruction *step_int_value = emit_load_local_n(def, step_int_ptr);
- new_idx = def->builder->CreateAdd(step_int_value, idx_int_value, "next.idx",
- false, true);
- } else
- new_idx = def->builder->CreateAdd(def->types->kluaInteger[1], idx_int_value,
- "next.idx", false, true);
-
- // save new index
- emit_store_local_n(def, new_idx, idx_int_ptr);
-
- // lua_Integer limit = ivalue(ra + 1);
- llvm::Instruction *limit_int_value = emit_load_local_n(def, limit_int_ptr);
-
- // idx > limit?
- llvm::Value *new_idx_gt_limit =
- def->builder->CreateICmpSGT(new_idx, limit_int_value, "idx.gt.limit");
-
- // If idx > limit we are done
- llvm::BasicBlock *update_block =
- llvm::BasicBlock::Create(def->jitState->context(), "updatei");
- def->builder->CreateCondBr(new_idx_gt_limit, exit_block, update_block);
-
- // Merge into update block
- def->f->getBasicBlockList().push_back(update_block);
- def->builder->SetInsertPoint(update_block);
-
- // Load pointer to base
- emit_load_base(def);
-
- llvm::Value *rvar = emit_gep_register(def, A + 3);
-
- // setivalue(ra + 3, idx); /* ...and external index */
- idx_int_value = emit_load_local_n(def, idx_int_ptr);
- emit_store_reg_i_withtype(def, idx_int_value, rvar);
-
- // ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- def->f->getBasicBlockList().push_back(exit_block);
- def->builder->SetInsertPoint(exit_block);
-}
-}
\ No newline at end of file
diff --git a/src/ravi_llvmforprep.cpp b/src/ravi_llvmforprep.cpp
deleted file mode 100644
index f4ce603..0000000
--- a/src/ravi_llvmforprep.cpp
+++ /dev/null
@@ -1,764 +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.
-******************************************************************************/
-#include "ravi_llvmcodegen.h"
-
-namespace ravi {
-
-void RaviCodeGenerator::emit_FORPREP2(RaviFunctionDef *def, int A, int pc,
- int pc1) {
-
- // Create additional forloop targets
- // First target is for int < limit
- RaviBranchDef &forloop_target = def->jmp_targets[pc];
-
- // case OP_FORPREP: {
- // if (ttisinteger(init) && ttisinteger(pstep) &&
- // forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
- // /* all values are integer */
- // lua_Integer initv = (stopnow ? 0 : ivalue(init));
- // setivalue(plimit, ilimit);
- // setivalue(init, initv - ivalue(pstep));
- // }
- // else { /* try making all values floats */
- // if (!tonumber(plimit, &nlimit))
- // luaG_runerror(L, "'for' limit must be a number");
- // setfltvalue(plimit, nlimit);
- // if (!tonumber(pstep, &nstep))
- // luaG_runerror(L, "'for' step must be a number");
- // setfltvalue(pstep, nstep);
- // if (!tonumber(init, &ninit))
- // luaG_runerror(L, "'for' initial value must be a number");
- // setfltvalue(init, luai_numsub(L, ninit, nstep));
- // }
- // ci->u.l.savedpc += GETARG_sBx(i);
- //} break;
-
- emit_debug_trace(def, OP_FORPREP, pc1);
- // Load pointer to base
- emit_load_base(def);
-
- // lua_Integer ilimit;
- // int stopnow;
- // lua_Number ninit; lua_Number nlimit; lua_Number nstep;
-
- // Setup local vars on C stack and link them
- // to the forloop_target so that the forloop code can access these
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
- llvm::Value *stopnow =
- TmpB.CreateAlloca(def->types->C_intT, nullptr, "stopnow");
-
- forloop_target.ilimit =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "ilimit");
- forloop_target.istep =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "istep");
- forloop_target.iidx =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "iidx");
- forloop_target.flimit =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nlimit");
- forloop_target.fidx =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "ninit");
- forloop_target.fstep =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nstep");
- forloop_target.forloop_branch =
- TmpB.CreateAlloca(def->types->C_pcharT, nullptr, "brnch");
-
- llvm::Value *isinc = nullptr;
-
- // TValue *init = ra;
- // TValue *plimit = ra + 1;
- // TValue *pstep = ra + 2;
- llvm::Value *init = emit_gep_register(def, A);
- llvm::Value *plimit = emit_gep_register(def, A + 1);
- llvm::Value *pstep = emit_gep_register(def, A + 2);
-
- // if (ttisinteger(init) && ttisinteger(pstep) &&
- // forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
-
- // Get init->tt
- llvm::Instruction *pinit_tt = emit_load_type(def, init);
-
- // Compare init->tt == LUA_TNUMINT
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, pinit_tt, LUA__TNUMINT, "init.is.integer");
-
- // Get pstep->tt
- llvm::Instruction *pstep_tt = emit_load_type(def, pstep);
-
- // Compare pstep->tt == LUA_TNUMINT
- llvm::Value *icmp2 =
- emit_is_value_of_type(def, pstep_tt, LUA__TNUMINT, "step.is.integer");
-
- // Get ivalue(pstep)
- llvm::Instruction *pstep_ivalue = emit_load_reg_i(def, pstep);
-
- // Call forlimit()
- llvm::Value *forlimit_ret =
- CreateCall4(def->builder, def->luaV_forlimitF, plimit,
- forloop_target.ilimit, pstep_ivalue, stopnow);
-
- // Is init->tt == LUA_TNUMINT && pstep->tt == LUA_TNUMINT
- llvm::Value *and1 =
- def->builder->CreateAnd(cmp1, icmp2, "init.and.step.are.integers");
-
- // Convert result from forlimit() to bool
- llvm::Value *tobool =
- def->builder->CreateICmpNE(forlimit_ret, def->types->kInt[0]);
-
- // Are all vars integers?
- // init->tt == LUA_TNUMINT && pstep->tt == LUA_TNUMINT && forlimit()
- llvm::Value *and2 = def->builder->CreateAnd(and1, tobool, "all.integers");
-
- // Create if then else branch
- llvm::BasicBlock *then1 = llvm::BasicBlock::Create(def->jitState->context(),
- "if.all.integers", def->f);
- llvm::BasicBlock *else1 =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.all.integers");
- def->builder->CreateCondBr(and2, then1, else1);
- def->builder->SetInsertPoint(then1);
-
- // all values are integers
- // lua_Integer initv = (stopnow ? 0 : ivalue(init));
- // Save step
- emit_store_local_n(def, pstep_ivalue, forloop_target.istep);
-
- // Get stopnow
- llvm::Instruction *stopnow_val = emit_load_local_int(def, stopnow);
-
- // Test if stopnow is 0
- llvm::Value *stopnow_is_zero = def->builder->CreateICmpEQ(
- stopnow_val, def->types->kInt[0], "stopnow.is.zero");
-
- // Get ptr to init->i
-
- // Setup if then else branch for stopnow
- llvm::BasicBlock *then1_iffalse = llvm::BasicBlock::Create(
- def->jitState->context(), "if.stopnow.iszero", def->f);
- llvm::BasicBlock *then1_iftrue =
- llvm::BasicBlock::Create(def->jitState->context(), "if.stopnow.notzero");
- def->builder->CreateCondBr(stopnow_is_zero, then1_iffalse, then1_iftrue);
- def->builder->SetInsertPoint(then1_iffalse);
-
- // stopnow is 0
- // Get init->i
- llvm::Instruction *init_ivalue = emit_load_reg_i(def, init);
-
- // Join after the branch
- def->builder->CreateBr(then1_iftrue);
- def->f->getBasicBlockList().push_back(then1_iftrue);
- def->builder->SetInsertPoint(then1_iftrue);
-
- // Set initv to 0 if !stopnow else init->i
- auto phi1 = def->builder->CreatePHI(def->types->lua_IntegerT, 2, "initv");
- phi1->addIncoming(init_ivalue, then1_iffalse);
- phi1->addIncoming(def->types->kluaInteger[0], then1);
-
- // setivalue(init, initv - ivalue(pstep));
- // we aleady know init is LUA_TNUMINT
-
- llvm::Value *sub =
- def->builder->CreateSub(phi1, pstep_ivalue, "initv-pstep.i", false, true);
- emit_store_local_n(def, sub, forloop_target.iidx);
-
- // Ok so now we need to decide which jump target
- isinc = def->builder->CreateICmpSGT(pstep_ivalue, def->types->kluaInteger[0],
- "step.gt.zero");
-
- // Create if then else branch
- llvm::BasicBlock *b1 =
- llvm::BasicBlock::Create(def->jitState->context(), "b1", def->f);
- llvm::BasicBlock *b2 =
- llvm::BasicBlock::Create(def->jitState->context(), "b2");
- llvm::BasicBlock *b3 =
- llvm::BasicBlock::Create(def->jitState->context(), "b3");
-
- def->builder->CreateCondBr(isinc, b1, b2);
- def->builder->SetInsertPoint(b1);
-
- // TODO tbaa?
- def->builder->CreateStore(
- llvm::BlockAddress::get(def->f, forloop_target.jmp1),
- forloop_target.forloop_branch);
-
- def->builder->CreateBr(b3);
-
- def->f->getBasicBlockList().push_back(b2);
- def->builder->SetInsertPoint(b2);
-
- // TODO tbaa?
- def->builder->CreateStore(
- llvm::BlockAddress::get(def->f, forloop_target.jmp2),
- forloop_target.forloop_branch);
-
- def->builder->CreateBr(b3);
-
- def->f->getBasicBlockList().push_back(b3);
- def->builder->SetInsertPoint(b3);
-
- // Create branch
- def->builder->CreateCondBr(isinc, forloop_target.jmp1, forloop_target.jmp2);
-
- // NOW the non-integer case
-
- def->f->getBasicBlockList().push_back(else1);
- def->builder->SetInsertPoint(else1);
-
- // ************ PLIMIT - Convert plimit to float
-
- llvm::Instruction *plimit_tt = emit_load_type(def, plimit);
-
- // Test if already a float
- cmp1 = emit_is_value_of_type(def, plimit_tt, LUA__TNUMFLT, "limit.is.float");
- llvm::BasicBlock *else1_plimit_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.limit.isfloat", def->f);
- llvm::BasicBlock *else1_plimit_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.limit.notfloat");
- def->builder->CreateCondBr(cmp1, else1_plimit_ifnum, else1_plimit_elsenum);
- def->builder->SetInsertPoint(else1_plimit_ifnum);
-
- // Already a float - copy to nlimit
- llvm::Instruction *plimit_nvalue_load = emit_load_reg_n(def, plimit);
- emit_store_local_n(def, plimit_nvalue_load, forloop_target.flimit);
-
- // Go to the PSTEP section
- llvm::BasicBlock *else1_pstep =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.step");
- def->builder->CreateBr(else1_pstep);
-
- // If plimit was not already a float we need to convert
- def->f->getBasicBlockList().push_back(else1_plimit_elsenum);
- def->builder->SetInsertPoint(else1_plimit_elsenum);
- // Call luaV_tonumber_()
- llvm::Value *plimit_isnum = CreateCall2(def->builder, def->luaV_tonumberF,
- plimit, forloop_target.flimit);
- llvm::Value *plimit_isnum_bool = def->builder->CreateICmpEQ(
- plimit_isnum, def->types->kInt[0], "limit.float.ok");
-
- // Did conversion fail?
- llvm::BasicBlock *else1_plimit_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.limit.float.failed", def->f);
- def->builder->CreateCondBr(plimit_isnum_bool, else1_plimit_tonum_elsenum,
- else1_pstep);
-
- // Conversion failed, so raise error
- def->builder->SetInsertPoint(else1_plimit_tonum_elsenum);
- emit_raise_lua_error(def, "'for' limit must be a number");
- def->builder->CreateBr(else1_pstep);
-
- // Conversion OK
- // Update plimit
- def->f->getBasicBlockList().push_back(else1_pstep);
- def->builder->SetInsertPoint(else1_pstep);
-
- // *********** PSTEP - convert pstep to float
- // Test if already a float
- pstep_tt = emit_load_type(def, pstep);
- cmp1 = emit_is_value_of_type(def, pstep_tt, LUA__TNUMFLT, "step.is.float");
- llvm::BasicBlock *else1_pstep_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.step.isfloat", def->f);
- llvm::BasicBlock *else1_pstep_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.step.notfloat");
- def->builder->CreateCondBr(cmp1, else1_pstep_ifnum, else1_pstep_elsenum);
- def->builder->SetInsertPoint(else1_pstep_ifnum);
-
- // We float then copy to nstep
- llvm::Instruction *pstep_nvalue_load = emit_load_reg_n(def, pstep);
- emit_store_local_n(def, pstep_nvalue_load, forloop_target.fstep);
-
- // Now go to handle initial value
- llvm::BasicBlock *else1_pinit =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.init");
- def->builder->CreateBr(else1_pinit);
-
- // If pstep was not already a float then we need to convert
- def->f->getBasicBlockList().push_back(else1_pstep_elsenum);
- def->builder->SetInsertPoint(else1_pstep_elsenum);
-
- // call luaV_tonumber_()
- llvm::Value *pstep_isnum = CreateCall2(def->builder, def->luaV_tonumberF,
- pstep, forloop_target.fstep);
- llvm::Value *pstep_isnum_bool = def->builder->CreateICmpEQ(
- pstep_isnum, def->types->kInt[0], "step.float.ok");
- llvm::BasicBlock *else1_pstep_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.step.float.failed", def->f);
- def->builder->CreateCondBr(pstep_isnum_bool, else1_pstep_tonum_elsenum,
- else1_pinit);
-
- // If conversion failed raise error
- def->builder->SetInsertPoint(else1_pstep_tonum_elsenum);
- emit_raise_lua_error(def, "'for' step must be a number");
- def->builder->CreateBr(else1_pinit);
-
- // Conversion okay so update pstep
- def->f->getBasicBlockList().push_back(else1_pinit);
- def->builder->SetInsertPoint(else1_pinit);
-
- // *********** PINIT finally handle initial value
-
- // Check if it is already a float
- pinit_tt = emit_load_type(def, init);
- cmp1 = emit_is_value_of_type(def, pinit_tt, LUA__TNUMFLT, "init.is.float");
- llvm::BasicBlock *else1_pinit_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.init.is.float", def->f);
- llvm::BasicBlock *else1_pinit_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.init.not.float");
- def->builder->CreateCondBr(cmp1, else1_pinit_ifnum, else1_pinit_elsenum);
- def->builder->SetInsertPoint(else1_pinit_ifnum);
-
- // Already float so copy to ninit
- llvm::Instruction *pinit_nvalue_load = emit_load_reg_n(def, init);
- emit_store_local_n(def, pinit_nvalue_load, forloop_target.fidx);
-
- // Go to final section
- llvm::BasicBlock *else1_pdone =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.done");
- def->builder->CreateBr(else1_pdone);
-
- // Not a float so we need to convert
- def->f->getBasicBlockList().push_back(else1_pinit_elsenum);
- def->builder->SetInsertPoint(else1_pinit_elsenum);
-
- // Call luaV_tonumber_()
- llvm::Value *pinit_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, init, forloop_target.fidx);
- llvm::Value *pinit_isnum_bool = def->builder->CreateICmpEQ(
- pinit_isnum, def->types->kInt[0], "init.float.ok");
- llvm::BasicBlock *else1_pinit_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.init.float.failed", def->f);
- def->builder->CreateCondBr(pinit_isnum_bool, else1_pinit_tonum_elsenum,
- else1_pdone);
-
- // Conversion failed so raise error
- def->builder->SetInsertPoint(else1_pinit_tonum_elsenum);
- emit_raise_lua_error(def, "'for' initial value must be a number");
- def->builder->CreateBr(else1_pdone);
-
- // Conversion OK so we are nearly done
- def->f->getBasicBlockList().push_back(else1_pdone);
- def->builder->SetInsertPoint(else1_pdone);
- llvm::Instruction *ninit_load = emit_load_local_n(def, forloop_target.fidx);
- llvm::Instruction *nstep_load = emit_load_local_n(def, forloop_target.fstep);
-
- // setfltvalue(init, luai_numsub(L, ninit, nstep));
- llvm::Value *init_n =
- def->builder->CreateFSub(ninit_load, nstep_load, "ninit-nstep");
-
- emit_store_local_n(def, init_n, forloop_target.fidx);
-
- // Done so jump to forloop
- llvm::Value *fstep_gt_zero = def->builder->CreateFCmpOGT(
- nstep_load, llvm::ConstantFP::get(def->types->lua_NumberT, 0.0),
- "step.gt.zero");
-
- // Create if then else branch
- b1 = llvm::BasicBlock::Create(def->jitState->context(), "b1", def->f);
- b2 = llvm::BasicBlock::Create(def->jitState->context(), "b2");
- b3 = llvm::BasicBlock::Create(def->jitState->context(), "b3");
-
- def->builder->CreateCondBr(fstep_gt_zero, b1, b2);
- def->builder->SetInsertPoint(b1);
-
- def->builder->CreateStore(
- llvm::BlockAddress::get(def->f, forloop_target.jmp3),
- forloop_target.forloop_branch);
- def->builder->CreateBr(b3);
-
- def->f->getBasicBlockList().push_back(b2);
- def->builder->SetInsertPoint(b2);
- def->builder->CreateStore(
- llvm::BlockAddress::get(def->f, forloop_target.jmp4),
- forloop_target.forloop_branch);
- def->builder->CreateBr(b3);
-
- def->f->getBasicBlockList().push_back(b3);
- def->builder->SetInsertPoint(b3);
-
- def->builder->CreateCondBr(fstep_gt_zero, forloop_target.jmp3,
- forloop_target.jmp4);
-}
-
-void RaviCodeGenerator::emit_FORPREP(RaviFunctionDef *def, int A, int pc,
- int pc1) {
-
- // case OP_FORPREP: {
- // if (ttisinteger(init) && ttisinteger(pstep) &&
- // forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
- // /* all values are integer */
- // lua_Integer initv = (stopnow ? 0 : ivalue(init));
- // setivalue(plimit, ilimit);
- // setivalue(init, initv - ivalue(pstep));
- // }
- // else { /* try making all values floats */
- // if (!tonumber(plimit, &nlimit))
- // luaG_runerror(L, "'for' limit must be a number");
- // setfltvalue(plimit, nlimit);
- // if (!tonumber(pstep, &nstep))
- // luaG_runerror(L, "'for' step must be a number");
- // setfltvalue(pstep, nstep);
- // if (!tonumber(init, &ninit))
- // luaG_runerror(L, "'for' initial value must be a number");
- // setfltvalue(init, luai_numsub(L, ninit, nstep));
- // }
- // ci->u.l.savedpc += GETARG_sBx(i);
- //} break;
-
- emit_debug_trace(def, OP_FORPREP, pc1);
- // Load pointer to base
- emit_load_base(def);
-
- // lua_Integer ilimit;
- // int stopnow;
- // lua_Number ninit; lua_Number nlimit; lua_Number nstep;
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
-
- llvm::Value *ilimit =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "ilimit");
- llvm::Value *stopnow =
- TmpB.CreateAlloca(def->types->C_intT, nullptr, "stopnow");
- llvm::Value *nlimit =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nlimit");
- llvm::Value *ninit =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "ninit");
- llvm::Value *nstep =
- TmpB.CreateAlloca(def->types->lua_NumberT, nullptr, "nstep");
-
- // TValue *init = ra;
- // TValue *plimit = ra + 1;
- // TValue *pstep = ra + 2;
- llvm::Value *init = emit_gep_register(def, A);
- llvm::Value *plimit = emit_gep_register(def, A + 1);
- llvm::Value *pstep = emit_gep_register(def, A + 2);
-
- // if (ttisinteger(init) && ttisinteger(pstep) &&
- // forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
-
- // Get init->tt_
- llvm::Instruction *pinit_tt = emit_load_type(def, init);
-
- // Compare init->tt_ == LUA_TNUMINT
- llvm::Value *cmp1 =
- emit_is_value_of_type(def, pinit_tt, LUA__TNUMINT, "init.is.integer");
-
- // Get pstep->tt_
- llvm::Instruction *pstep_tt = emit_load_type(def, pstep);
-
- // Compare pstep->tt_ == LUA_TNUMINT
- llvm::Value *icmp2 =
- emit_is_value_of_type(def, pstep_tt, LUA__TNUMINT, "step.is.integer");
-
- // Get ivalue(pstep)
- llvm::Instruction *pstep_ivalue = emit_load_reg_i(def, pstep);
-
- // Call forlimit()
- llvm::Value *forlimit_ret = CreateCall4(
- def->builder, def->luaV_forlimitF, plimit, ilimit, pstep_ivalue, stopnow);
-
- // init->tt_ == LUA_TNUMINT && pstep->tt_ == LUA_TNUMINT
- llvm::Value *and1 =
- def->builder->CreateAnd(cmp1, icmp2, "init.and.step.are.integers");
-
- // Convert result from forlimit() to bool
- llvm::Value *tobool =
- def->builder->CreateICmpNE(forlimit_ret, def->types->kInt[0]);
-
- // init->tt_ == LUA_TNUMINT && pstep->tt_ == LUA_TNUMINT && forlimit()
- llvm::Value *and2 = def->builder->CreateAnd(and1, tobool, "all.integers");
-
- // Create if then else branch
- llvm::BasicBlock *then1 = llvm::BasicBlock::Create(def->jitState->context(),
- "if.all.integers", def->f);
- llvm::BasicBlock *else1 =
- llvm::BasicBlock::Create(def->jitState->context(), "if.not.all.integers");
- def->builder->CreateCondBr(and2, then1, else1);
- def->builder->SetInsertPoint(then1);
-
- // all values are integers
- // lua_Integer initv = (stopnow ? 0 : ivalue(init));
-
- // Get stopnow
- llvm::Instruction *stopnow_val = emit_load_local_int(def, stopnow);
-
- // Test if stopnow is 0
- llvm::Value *stopnow_is_zero = def->builder->CreateICmpEQ(
- stopnow_val, def->types->kInt[0], "stopnow.is.zero");
-
- // Setup if then else branch for stopnow
- llvm::BasicBlock *then1_iffalse = llvm::BasicBlock::Create(
- def->jitState->context(), "if.stopnow.iszero", def->f);
- llvm::BasicBlock *then1_iftrue =
- llvm::BasicBlock::Create(def->jitState->context(), "if.stopnow.notzero");
- def->builder->CreateCondBr(stopnow_is_zero, then1_iffalse, then1_iftrue);
- def->builder->SetInsertPoint(then1_iffalse);
-
- // stopnow is 0
- // Get init->i
- llvm::Instruction *init_ivalue = emit_load_reg_i(def, init);
-
- // Join after the branch
- def->builder->CreateBr(then1_iftrue);
- def->f->getBasicBlockList().push_back(then1_iftrue);
- def->builder->SetInsertPoint(then1_iftrue);
-
- // Set initv to 0 if !stopnow else init->i
- auto phi1 = def->builder->CreatePHI(def->types->lua_IntegerT, 2, "initv");
- phi1->addIncoming(init_ivalue, then1_iffalse);
- phi1->addIncoming(def->types->kluaInteger[0], then1);
-
- // setivalue(plimit, ilimit);
- llvm::Instruction *ilimit_val = emit_load_local_n(def, ilimit);
-
- emit_store_reg_i_withtype(def, ilimit_val, plimit);
-
- // setivalue(init, initv - ivalue(pstep));
- // we aleady know init is LUA_TNUMINT
- pstep_ivalue = emit_load_reg_i(def, pstep);
- llvm::Value *sub =
- def->builder->CreateSub(phi1, pstep_ivalue, "initv-pstep.i", false, true);
-
- emit_store_reg_i(def, sub, init);
-
- // We are done so jump to forloop
- lua_assert(def->jmp_targets[pc].jmp1);
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-
- // NOW the non-integer case
-
- def->f->getBasicBlockList().push_back(else1);
- def->builder->SetInsertPoint(else1);
-
- // ************ PLIMIT - Convert plimit to float
-
- llvm::Instruction *plimit_tt = emit_load_type(def, plimit);
- // Test if already a float
- cmp1 = emit_is_value_of_type(def, plimit_tt, LUA__TNUMFLT, "limit.is.float");
- llvm::BasicBlock *else1_plimit_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.limit.isfloat", def->f);
- llvm::BasicBlock *else1_plimit_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.limit.notfloat");
- def->builder->CreateCondBr(cmp1, else1_plimit_ifnum, else1_plimit_elsenum);
- def->builder->SetInsertPoint(else1_plimit_ifnum);
-
- // Already a float - copy to nlimit
- llvm::Instruction *plimit_nvalue_load = emit_load_reg_n(def, plimit);
- emit_store_local_n(def, plimit_nvalue_load, nlimit);
-
- // Go to the PSTEP section
- llvm::BasicBlock *else1_pstep =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.step");
- def->builder->CreateBr(else1_pstep);
-
- // If plimit was not already a float we need to convert
- def->f->getBasicBlockList().push_back(else1_plimit_elsenum);
- def->builder->SetInsertPoint(else1_plimit_elsenum);
- // Call luaV_tonumber_()
- llvm::Value *plimit_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, plimit, nlimit);
- llvm::Value *plimit_isnum_bool = def->builder->CreateICmpEQ(
- plimit_isnum, def->types->kInt[0], "limit.float.ok");
-
- // Did conversion fail?
- llvm::BasicBlock *else1_plimit_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.limit.float.failed", def->f);
- def->builder->CreateCondBr(plimit_isnum_bool, else1_plimit_tonum_elsenum,
- else1_pstep);
-
- // Conversion failed, so raise error
- def->builder->SetInsertPoint(else1_plimit_tonum_elsenum);
- emit_raise_lua_error(def, "'for' limit must be a number");
- def->builder->CreateBr(else1_pstep);
-
- // Conversion OK
- // Update plimit
- def->f->getBasicBlockList().push_back(else1_pstep);
- def->builder->SetInsertPoint(else1_pstep);
- llvm::Instruction *nlimit_load = emit_load_local_n(def, nlimit);
-
- emit_store_reg_n_withtype(def, nlimit_load, plimit);
-
- // *********** PSTEP - convert pstep to float
- // Test if already a float
- pstep_tt = emit_load_type(def, pstep);
- cmp1 = emit_is_value_of_type(def, pstep_tt, LUA__TNUMFLT, "step.is.float");
- llvm::BasicBlock *else1_pstep_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.step.isfloat", def->f);
- llvm::BasicBlock *else1_pstep_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.step.notfloat");
- def->builder->CreateCondBr(cmp1, else1_pstep_ifnum, else1_pstep_elsenum);
- def->builder->SetInsertPoint(else1_pstep_ifnum);
-
- // We float then copy to nstep
- llvm::Instruction *pstep_nvalue_load = emit_load_reg_n(def, pstep);
- emit_store_local_n(def, pstep_nvalue_load, nstep);
-
- // Now go to handle initial value
- llvm::BasicBlock *else1_pinit =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.init");
- def->builder->CreateBr(else1_pinit);
-
- // If pstep was not already a float then we need to convert
- def->f->getBasicBlockList().push_back(else1_pstep_elsenum);
- def->builder->SetInsertPoint(else1_pstep_elsenum);
-
- // call luaV_tonumber_()
- llvm::Value *pstep_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, pstep, nstep);
- llvm::Value *pstep_isnum_bool = def->builder->CreateICmpEQ(
- pstep_isnum, def->types->kInt[0], "step.float.ok");
- llvm::BasicBlock *else1_pstep_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.step.float.failed", def->f);
- def->builder->CreateCondBr(pstep_isnum_bool, else1_pstep_tonum_elsenum,
- else1_pinit);
-
- // If conversion failed raise error
- def->builder->SetInsertPoint(else1_pstep_tonum_elsenum);
- emit_raise_lua_error(def, "'for' step must be a number");
- def->builder->CreateBr(else1_pinit);
-
- // Conversion okay so update pstep
- def->f->getBasicBlockList().push_back(else1_pinit);
- def->builder->SetInsertPoint(else1_pinit);
-
- llvm::Instruction *nstep_load = emit_load_local_n(def, nstep);
-
- emit_store_reg_n_withtype(def, nstep_load, pstep);
-
- // *********** PINIT finally handle initial value
-
- // Check if it is already a float
- pinit_tt = emit_load_type(def, init);
- cmp1 = emit_is_value_of_type(def, pinit_tt, LUA__TNUMFLT, "init.is.float");
- llvm::BasicBlock *else1_pinit_ifnum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.init.is.float", def->f);
- llvm::BasicBlock *else1_pinit_elsenum =
- llvm::BasicBlock::Create(def->jitState->context(), "if.init.not.float");
- def->builder->CreateCondBr(cmp1, else1_pinit_ifnum, else1_pinit_elsenum);
- def->builder->SetInsertPoint(else1_pinit_ifnum);
-
- // Already float so copy to ninit
- llvm::Instruction *pinit_nvalue_load = emit_load_reg_n(def, init);
- emit_store_local_n(def, pinit_nvalue_load, ninit);
-
- // Go to final section
- llvm::BasicBlock *else1_pdone =
- llvm::BasicBlock::Create(def->jitState->context(), "if.else.done");
- def->builder->CreateBr(else1_pdone);
-
- // Not a float so we need to convert
- def->f->getBasicBlockList().push_back(else1_pinit_elsenum);
- def->builder->SetInsertPoint(else1_pinit_elsenum);
-
- // Call luaV_tonumber_()
- llvm::Value *pinit_isnum =
- CreateCall2(def->builder, def->luaV_tonumberF, init, ninit);
- llvm::Value *pinit_isnum_bool = def->builder->CreateICmpEQ(
- pinit_isnum, def->types->kInt[0], "init.float.ok");
- llvm::BasicBlock *else1_pinit_tonum_elsenum = llvm::BasicBlock::Create(
- def->jitState->context(), "if.init.float.failed", def->f);
- def->builder->CreateCondBr(pinit_isnum_bool, else1_pinit_tonum_elsenum,
- else1_pdone);
-
- // Conversion failed so raise error
- def->builder->SetInsertPoint(else1_pinit_tonum_elsenum);
- emit_raise_lua_error(def, "'for' initial value must be a number");
- def->builder->CreateBr(else1_pdone);
-
- // Conversion OK so we are nearly done
- def->f->getBasicBlockList().push_back(else1_pdone);
- def->builder->SetInsertPoint(else1_pdone);
- llvm::Instruction *ninit_load = emit_load_local_n(def, ninit);
- nstep_load = emit_load_local_n(def, nstep);
-
- // setfltvalue(init, luai_numsub(L, ninit, nstep));
- llvm::Value *init_n =
- def->builder->CreateFSub(ninit_load, nstep_load, "ninit-nstep");
-
- emit_store_reg_n_withtype(def, init_n, init);
-
- // Done so jump to forloop
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-}
-
-void RaviCodeGenerator::emit_iFORPREP(RaviFunctionDef *def, int A, int pc,
- int step_one, int pc1) {
-
- RaviBranchDef &forloop_target = def->jmp_targets[pc];
-
- llvm::IRBuilder<> TmpB(def->entry, def->entry->begin());
-
- forloop_target.ilimit =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "ilimit");
- if (!step_one) {
- forloop_target.istep =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "istep");
- }
- forloop_target.iidx =
- TmpB.CreateAlloca(def->types->lua_IntegerT, nullptr, "iidx");
-
- // lua_Integer initv = ivalue(init);
- // setivalue(init, initv - ivalue(pstep));
-
- emit_debug_trace(def, step_one ? OP_RAVI_FORPREP_I1 : OP_RAVI_FORPREP_IP,
- pc1);
- // Load pointer to base
- emit_load_base(def);
-
- // TValue *init = ra;
- // TValue *pstep = ra + 2;
- llvm::Value *init = emit_gep_register(def, A);
- llvm::Value *plimit = emit_gep_register(def, A + 1);
- llvm::Value *pstep = nullptr;
- if (!step_one)
- pstep = emit_gep_register(def, A + 2);
-
- // Get ivalue(pstep)
- llvm::Instruction *limit_ivalue = emit_load_reg_i(def, plimit);
- llvm::Instruction *init_ivalue = emit_load_reg_i(def, init);
-
- if (!step_one) {
- // setivalue(init, initv - ivalue(pstep));
- llvm::Instruction *step_ivalue = emit_load_reg_i(def, pstep);
- llvm::Value *idx = def->builder->CreateSub(init_ivalue, step_ivalue,
- "initv-pstep.i", false, true);
-
- // Save idx
- emit_store_local_n(def, idx, forloop_target.iidx);
-
- // Save step
- emit_store_local_n(def, step_ivalue, forloop_target.istep);
- } else {
- // setivalue(init, initv - ivalue(pstep));
- llvm::Value *idx = def->builder->CreateSub(
- init_ivalue, def->types->kluaInteger[1], "initv-pstep.i", false, true);
-
- // Save idx
- emit_store_local_n(def, idx, forloop_target.iidx);
- }
-
- // Save limit
- emit_store_local_n(def, limit_ivalue, forloop_target.ilimit);
-
- // We are done so jump to forloop
- lua_assert(def->jmp_targets[pc].jmp1);
- def->builder->CreateBr(def->jmp_targets[pc].jmp1);
-}
-}
\ No newline at end of file
diff --git a/src/ravi_llvmjit.cpp b/src/ravi_llvmjit.cpp
deleted file mode 100644
index a08d222..0000000
--- a/src/ravi_llvmjit.cpp
+++ /dev/null
@@ -1,1091 +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.
- ******************************************************************************/
-#include
-// Important to include the C++ header files (ravi_llvmcodegen.h) before following
-// (ravi_jitshared.h) as the Lua headers define macros that mess with C++ headers
-#include
-
-/*
- * Implementation Notes:
- * Each Lua function is compiled into an LLVM Module/Function
- * This strategy allows functions to be garbage collected as normal by Lua
- * See issue #78 for changes to this (wip)
- */
-
-namespace ravi {
-
-// This is just to avoid initializing LLVM repeatedly -
-// see below
-static std::atomic_int init;
-
-static const char *errortext[] = {"integer expected",
- "number expected",
- "integer[] expected",
- "number[] expected",
- "table expected",
- "upvalue of integer type, cannot be set to non integer value",
- "upvalue of number type, cannot be set to non number value",
- "upvalue of integer[] type, cannot be set to non integer[] value",
- "upvalue of number[] type, cannot be set to non number[] value",
- "upvalue of table type, cannot be set to non table value",
- "for llimit must be a number",
- "for step must be a number",
- "for initial value must be a number",
- "array index is out of bounds",
- "string expected",
- "closure expected",
- "type mismatch: wrong userdata type",
- NULL};
-
-static struct {
- const char *name;
- void *address;
-} global_syms[] = {{"lua_absindex", reinterpret_cast(lua_absindex)},
- {"lua_gettop", reinterpret_cast(lua_gettop)},
- {"lua_settop", reinterpret_cast(lua_settop)},
- {"lua_pushvalue", reinterpret_cast(lua_pushvalue)},
- {"lua_rotate", reinterpret_cast(lua_rotate)},
- {"lua_copy", reinterpret_cast(lua_copy)},
- {"lua_checkstack", reinterpret_cast(lua_checkstack)},
- {"lua_xmove", reinterpret_cast(lua_xmove)},
- {"lua_isnumber", reinterpret_cast(lua_isnumber)},
- {"lua_isstring", reinterpret_cast(lua_isstring)},
- {"lua_iscfunction", reinterpret_cast(lua_iscfunction)},
- {"lua_isinteger", reinterpret_cast(lua_isinteger)},
- {"lua_isuserdata", reinterpret_cast(lua_isuserdata)},
- {"lua_type", reinterpret_cast(lua_type)},
- {"lua_typename", reinterpret_cast(lua_typename)},
- {"lua_tonumberx", reinterpret_cast(lua_tonumberx)},
- {"lua_tointegerx", reinterpret_cast(lua_tointegerx)},
- {"lua_toboolean", reinterpret_cast(lua_toboolean)},
- {"lua_tolstring", reinterpret_cast(lua_tolstring)},
- {"lua_rawlen", reinterpret_cast(lua_rawlen)},
- {"lua_tocfunction", reinterpret_cast(lua_tocfunction)},
- {"lua_touserdata", reinterpret_cast(lua_touserdata)},
- {"lua_tothread", reinterpret_cast(lua_tothread)},
- {"lua_topointer", reinterpret_cast(lua_topointer)},
- {"lua_arith", reinterpret_cast