implement loadfz, loadnil, addfn

Dibyendu Majumdar 9 years ago
parent 2091942c4c
commit 6edfc4bfa0

@ -69,7 +69,8 @@ set (LUA_CORE_SRCS src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c sr
src/lparser.c src/lstate.c src/lstring.c src/ltable.c src/ltm.c src/lundump.c
src/lvm.c src/lzio.c src/ravijit.cpp src/ravi_llvmtypes.cpp
src/ravi_llvmcodegen.cpp src/ravi_llvmforprep.cpp src/ravi_llvmcomp.cpp
src/ravi_llvmreturn.cpp src/ravi_llvmload.cpp src/ravi_llvmforloop.cpp)
src/ravi_llvmreturn.cpp src/ravi_llvmload.cpp src/ravi_llvmforloop.cpp
src/ravi_llvmarith1.cpp)
# define the lua lib source files
set (LUA_LIB_SRCS src/lauxlib.c src/lbaselib.c src/lbitlib.c src/lcorolib.c src/ldblib.c src/liolib.c
src/lmathlib.c src/loslib.c src/ltablib.c src/lstrlib.c src/loadlib.c src/linit.c src/lutf8lib.c)

@ -55,7 +55,11 @@ LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
// RAVI changes
LUAI_FUNC int luaV_forlimit(const TValue *obj, lua_Integer *p, lua_Integer step,
int *stopnow);
LUAI_FUNC void luaV_op_loadnil(CallInfo *ci, int a, int b);
#endif

@ -172,6 +172,8 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_forlimitT;
llvm::FunctionType *luaV_tonumberT;
llvm::FunctionType *luaV_op_loadnilT;
std::array<llvm::Constant *, 21> kInt;
std::array<llvm::Constant *, 21> kluaInteger;
@ -297,6 +299,12 @@ public:
const std::string &triple() const { return triple_; }
};
// To optimise fornum loops
// i.e. OP_FORPREP and OP_FORLOOP instructions
// we use computed gotos to specialised
// jmp labels. Hence the 4 jmp targets.
// For other instructions only the first jump
// targetis used
struct RaviBranchDef {
// main or int step > 0
llvm::BasicBlock *jmp1;
@ -307,6 +315,8 @@ struct RaviBranchDef {
// forlook float step < 0
llvm::BasicBlock *jmp4;
// These are local variables for a fornum
// loop
llvm::Value *ilimit;
llvm::Value *istep;
llvm::Value *iidx;
@ -314,6 +324,9 @@ struct RaviBranchDef {
llvm::Value *fstep;
llvm::Value *fidx;
// This holds the branch to which the
// loop body will jump to using a
// IndirectBr instruction
llvm::Value *forloop_branch;
RaviBranchDef();
@ -340,6 +353,11 @@ struct RaviFunctionDef {
llvm::Constant *luaG_runerrorF;
llvm::Constant *luaV_forlimitF;
llvm::Constant *luaV_tonumberF;
// Some cheats
llvm::Constant *luaV_op_loadnilF;
// printf
llvm::Constant *printfFunc;
llvm::Value *str;
@ -416,6 +434,15 @@ public:
void link_block(RaviFunctionDef *def, int pc);
void emit_LOADNIL(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B);
void emit_LOADFZ(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A);
void emit_ADDFN(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C);
void emit_LOADK(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int Bx);

@ -0,0 +1,18 @@
local function x()
local j=0.0
for i=1,1000000000 do
j = j+1.0
end
return j
end
x()
local t1 = os.clock()
local y = x();
local t2 = os.clock()
print(y)
assert(y == 1000000000.0)
print("time taken ", t2-t1);

@ -0,0 +1,18 @@
local function x()
local j:double
for i=1,1000000000 do
j = j+1
end
return j
end
x()
local t1 = os.clock()
local y = x();
local t2 = os.clock()
print(y)
assert(y == 1000000000.0)
print("time taken ", t2-t1);

@ -43,6 +43,15 @@
/* limit for table tag-method chains (to avoid loops) */
#define MAXTAGLOOP 2000
// This is a cheat for a boring opcode
void luaV_op_loadnil(CallInfo *ci, int a, int b) {
StkId base;
base = ci->u.l.base;
TValue *ra = base + a;
do {
setnilvalue(ra++);
} while (b--);
}
/*
** Similar to 'tonumber', but does not attempt to convert strings and

@ -0,0 +1,50 @@
#include "ravi_llvmcodegen.h"
namespace ravi {
void RaviCodeGenerator::emit_ADDFN(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C) {
// 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);
// Load pointer to k
llvm::Value *k_ptr = def->k_ptr;
llvm::Value *ra;
if (A == 0) {
// If A is 0 we can use the base pointer which is &base[0]
ra = base_ptr;
} else {
// emit &base[A]
ra = emit_array_get(def, base_ptr, A);
}
llvm::Value *rb;
// Get pointer to register B
llvm::Value *base_or_k = ISK(B) ? k_ptr : 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);
}
llvm::Value *rb_n = def->builder->CreateBitCast(rb, def->types->plua_NumberT);
llvm::Instruction *lhs = def->builder->CreateLoad(rb_n);
lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
// Call luaV_equalobj with register B and C
llvm::Value *result = def->builder->CreateFAdd(
lhs,
def->builder->CreateSIToFP(llvm::ConstantInt::get(def->types->C_intT, C),
def->types->lua_NumberT));
llvm::Value *ra_n = def->builder->CreateBitCast(ra, def->types->plua_NumberT);
llvm::Instruction *store = def->builder->CreateStore(result, ra_n);
store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
}
}

@ -2,10 +2,10 @@
namespace ravi {
RaviBranchDef::RaviBranchDef() : jmp1(nullptr), jmp2(nullptr),
jmp3(nullptr), jmp4(nullptr), ilimit(nullptr), istep(nullptr),
iidx(nullptr), flimit(nullptr), fstep(nullptr), fidx(nullptr) {
}
RaviBranchDef::RaviBranchDef()
: jmp1(nullptr), jmp2(nullptr), jmp3(nullptr), jmp4(nullptr),
ilimit(nullptr), istep(nullptr), iidx(nullptr), flimit(nullptr),
fstep(nullptr), fidx(nullptr) {}
RaviCodeGenerator::RaviCodeGenerator(RaviJITStateImpl *jitState)
: jitState_(jitState), id_(1) {
@ -98,6 +98,9 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_FORPREP:
case OP_FORLOOP:
case OP_MOVE:
case OP_LOADNIL:
case OP_RAVI_LOADFZ:
case OP_RAVI_ADDFN:
break;
default:
return false;
@ -141,6 +144,7 @@ RaviCodeGenerator::create_function(llvm::IRBuilder<> &builder,
}
void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
// Add extern declarations for Lua functions that we need to call
def->luaD_poscallF = def->raviF->addExternFunction(
def->types->luaD_poscallT, reinterpret_cast<void *>(&luaD_poscall),
@ -166,14 +170,17 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
def->luaV_tonumberF = def->raviF->addExternFunction(
def->types->luaV_tonumberT, reinterpret_cast<void *>(&luaV_tonumber_),
"luaV_tonumber_");
def->luaV_op_loadnilF = def->raviF->addExternFunction(
def->types->luaV_op_loadnilT, reinterpret_cast<void *>(&luaV_op_loadnil),
"luaV_op_loadnil");
// Create printf declaration
std::vector<llvm::Type *> 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);
llvm::FunctionType::get(def->types->C_intT, args, true);
def->printfFunc =
def->raviF->module()->getOrInsertFunction("printf", printfType);
def->raviF->module()->getOrInsertFunction("printf", printfType);
}
#define RA(i) (base + GETARG_A(i))
@ -195,13 +202,8 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
check_exp(getCMode(GET_OPCODE(i)) == OpArgK, k + INDEXK(GETARG_C(i)))
void RaviCodeGenerator::link_block(RaviFunctionDef *def, int pc) {
// 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].jmp2) {
// 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);
@ -209,7 +211,12 @@ void RaviCodeGenerator::link_block(RaviFunctionDef *def, int pc) {
idb->addDestination(def->jmp_targets[pc].jmp3);
idb->addDestination(def->jmp_targets[pc].jmp4);
}
// 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
@ -338,6 +345,18 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
int j = sbx + pc + 1;
emit_FORLOOP2(&def, L_ci, proto, A, j, def.jmp_targets[pc]);
} break;
case OP_LOADNIL: {
int B = GETARG_B(i);
emit_LOADNIL(&def, L_ci, proto, A, B);
} break;
case OP_RAVI_LOADFZ: {
emit_LOADFZ(&def, L_ci, proto, A);
} break;
case OP_RAVI_ADDFN: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_ADDFN(&def, L_ci, proto, A, B, C);
} break;
default:
break;
}
@ -390,15 +409,18 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
snprintf(temp, sizeof temp, "%s%d_", targetname, j + 1);
def->jmp_targets[j].jmp1 =
def->jmp_targets[j].jmp1 =
llvm::BasicBlock::Create(def->jitState->context(), temp);
if (op == OP_FORPREP) {
// Second target is for int > limit
def->jmp_targets[j].jmp2 = llvm::BasicBlock::Create(def->jitState->context(), "forloop_igt");
def->jmp_targets[j].jmp2 =
llvm::BasicBlock::Create(def->jitState->context(), "forloop_igt");
// Third target is for float < limit
def->jmp_targets[j].jmp3 = llvm::BasicBlock::Create(def->jitState->context(), "forloop_flt");
def->jmp_targets[j].jmp3 =
llvm::BasicBlock::Create(def->jitState->context(), "forloop_flt");
// Fourth target is for flot > limit
def->jmp_targets[j].jmp4 = llvm::BasicBlock::Create(def->jitState->context(), "forloop_fgt");
def->jmp_targets[j].jmp4 =
llvm::BasicBlock::Create(def->jitState->context(), "forloop_fgt");
}
} break;
default:

@ -2,6 +2,42 @@
namespace ravi {
void RaviCodeGenerator::emit_LOADNIL(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B) {
def->builder->CreateCall3(def->luaV_op_loadnilF, def->ci_val,
llvm::ConstantInt::get(def->types->C_intT, A),
llvm::ConstantInt::get(def->types->C_intT, B));
}
void RaviCodeGenerator::emit_LOADFZ(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A) {
// 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);
llvm::Value *dest;
if (A == 0) {
// If A is 0 we can use the base pointer which is &base[0]
dest = base_ptr;
}
else {
// emit &base[A]
dest = emit_array_get(def, base_ptr, A);
}
// destvalue->n = 0.0
llvm::Value *destvalue = emit_gep(def, "dest.value", dest, 0, 0, 0);
llvm::Instruction *store = def->builder->CreateStore(llvm::ConstantFP::get(def->types->lua_NumberT, 0.0), destvalue);
store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_nT);
// destvalue->type = LUA_TNUMFLT
llvm::Value *desttype = emit_gep(def, "dest.tt", dest, 0, 1);
store = def->builder->CreateStore(def->types->kInt[LUA_TNUMFLT], desttype);
store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT);
}
void RaviCodeGenerator::emit_MOVE(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B) {

@ -638,6 +638,12 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(plua_NumberT);
luaV_tonumberT = llvm::FunctionType::get(C_intT, elements, false);
elements.clear();
elements.push_back(pCallInfoT);
elements.push_back(C_intT);
elements.push_back(C_intT);
luaV_op_loadnilT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
for (int j = 0; j < kInt.size(); j++)
kInt[j] = llvm::ConstantInt::get(C_intT, j);
for (int j = 0; j < kluaInteger.size(); j++)

@ -85,6 +85,8 @@ int main(int argc, const char *argv[])
{
int failures = 0;
//failures += test_luacompfile("ravi-tests/mandel1.ravi");
failures += test_luacompexec1("local function x(); local j:double; for i=1,1000000000 do; j = j+1; end; return j; end; local y = x(); print(y); return y", 1000000000);
failures += test_luacompexec1("local function x(); local j = 0; for i=2,6,3 do; j = i; end; return j; end; local y = x(); print(y); return y", 5);
failures += test_luacompexec1("local function x(); local j = 0; for i=2.0,6.0,3.0 do; j = i; end; return j; end; local y = x(); print(y); return y", 5);
failures += test_luacompexec1("local function x(); local a=5; return 1004,2; end; local y; y = x(); print(y); return y", 1004);
@ -136,7 +138,6 @@ int main(int argc, const char *argv[])
failures += test_luacompexec1("return (1 and 2)+(-1.25 or -4) == 0.75", 1);
failures += test_luacomp1("local a=1; if a==0 then; a = 2; else a=3; end;");
failures += test_luacomp1("local f = function(); return; end; local d:double = 5.0; d = f(); return d");
failures += test_luacompexec1("local j:double; for i=1,1000000000 do; j = j+1; end; return j", 1000000000);
failures += test_luacompexec1("local i, j:int; j=0; for i=1,1000000000 do; j = j+1; end; return j", 1000000000);
failures += test_luacomp1("local f = function(); return; end; local d = 5.0; d = f(); return d");
return failures ? 1 : 0;

Loading…
Cancel
Save