pull/81/head
Dibyendu Majumdar 9 years ago
parent 31d5e3e333
commit a9614f8b08

@ -75,6 +75,7 @@ struct LuaLLVMTypes {
LuaLLVMTypes(llvm::LLVMContext &context);
void dump();
llvm::Type *C_doubleT;
llvm::Type *C_intptr_t;
llvm::Type *C_size_t;
llvm::Type *C_ptrdiff_t;
@ -200,6 +201,8 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_forlimitT;
llvm::FunctionType *luaV_tonumberT;
llvm::FunctionType *luaV_tointegerT;
llvm::FunctionType *luaV_modT;
llvm::FunctionType *luaV_executeT;
llvm::FunctionType *luaV_gettableT;
llvm::FunctionType *luaV_settableT;
@ -207,7 +210,6 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_newarrayfloatT;
llvm::FunctionType *luaV_setlistT;
llvm::FunctionType *luaV_newtableT;
llvm::FunctionType *luaV_op_loadnilT;
std::array<llvm::Constant *, 256> kInt;
@ -406,6 +408,7 @@ struct RaviFunctionDef {
llvm::Constant *luaV_executeF;
llvm::Constant *luaV_gettableF;
llvm::Constant *luaV_settableF;
llvm::Constant *luaV_modF;
// Some cheats - these correspond to OPCODEs that
// are not inlined as of now
@ -417,6 +420,7 @@ struct RaviFunctionDef {
// printf
llvm::Constant *printfFunc;
llvm::Constant *fmodFunc;
// Jump targets in the function
std::vector<RaviBranchDef> jmp_targets;
@ -584,6 +588,9 @@ public:
void emit_ARITH(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C, OpCode op, TMS tms);
void emit_MOD(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C);
void emit_UNMF(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B);

@ -424,3 +424,12 @@ assert(y(x()))
assert(y(x(false)))
assert(not y(x(true)))
print("test 31 OK")
-- test 32
x=function(a,b)
return a%b
end
assert(ravi.compile(x))
assert(x(5,2) == 1)
assert(math.abs(x(5.1,2.1)-0.9) < 1e-12)
print("test 32 OK")

@ -43,7 +43,7 @@ Note that if a Lua functions contains a bytecode that cannot be be JITed then th
+-------------------------+----------+--------------------------------------------------+
| OP_MUL | YES | R(A) := RK(B) * RK(C) |
+-------------------------+----------+--------------------------------------------------+
| OP_MOD | NO | R(A) := RK(B) % RK(C) |
| OP_MOD | YES | R(A) := RK(B) % RK(C) |
+-------------------------+----------+--------------------------------------------------+
| OP_POW | NO | R(A) := RK(B) ^ RK(C) |
+-------------------------+----------+--------------------------------------------------+

@ -228,4 +228,210 @@ void RaviCodeGenerator::emit_ARITH(RaviFunctionDef *def, llvm::Value *L_ci,
def->f->getBasicBlockList().push_back(done_block);
def->builder->SetInsertPoint(done_block);
}
// OP_MOD
void RaviCodeGenerator::emit_MOD(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C) {
// 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");
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rb = emit_gep_rkb(def, base_ptr, B);
llvm::Value *rc = emit_gep_rkb(def, base_ptr, 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 = def->builder->CreateICmpEQ(
rb_type, def->types->kInt[LUA_TNUMINT], "rb.is.integer");
llvm::Value *cmp2 = def->builder->CreateICmpEQ(
rc_type, def->types->kInt[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 =
def->builder->CreateCall3(def->luaV_modF, def->L, lhs, rhs);
emit_store_reg_i(def, result, ra);
emit_store_type(def, ra, LUA_TNUMINT);
def->builder->CreateBr(done_block);
// Not integer
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
// Is RB a float?
cmp1 = def->builder->CreateICmpEQ(rb_type, def->types->kInt[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 =
def->builder->CreateCall2(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);
auto ins = def->builder->CreateStore(src, nb);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
def->builder->CreateBr(test_rc);
def->f->getBasicBlockList().push_back(test_rc);
def->builder->SetInsertPoint(test_rc);
// Is RC a float?
cmp1 = def->builder->CreateICmpEQ(rc_type, def->types->kInt[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 =
def->builder->CreateCall2(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);
ins = def->builder->CreateStore(src, nc);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
def->builder->CreateBr(float_op);
def->f->getBasicBlockList().push_back(float_op);
def->builder->SetInsertPoint(float_op);
lhs = def->builder->CreateLoad(nb);
lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
rhs = def->builder->CreateLoad(nc);
rhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
llvm::Value *fmod_result = def->builder->CreateCall2(def->fmodFunc, lhs, rhs);
// 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->C_doubleT, 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);
ins = def->builder->CreateStore(result, nb);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
def->builder->CreateBr(mb_lt0_done);
def->f->getBasicBlockList().push_back(mb_lt0_else);
def->builder->SetInsertPoint(mb_lt0_else);
ins = def->builder->CreateStore(fmod_result, nb);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
def->builder->CreateBr(mb_lt0_done);
def->f->getBasicBlockList().push_back(mb_lt0_done);
def->builder->SetInsertPoint(mb_lt0_done);
lhs = def->builder->CreateLoad(nb);
lhs->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_longlongT);
emit_store_reg_n(def, lhs, ra);
emit_store_type(def, ra, LUA_TNUMFLT);
def->builder->CreateBr(done_block);
// Neither integer nor float so try meta
def->f->getBasicBlockList().push_back(try_meta);
def->builder->SetInsertPoint(try_meta);
def->builder->CreateCall5(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);
}
}

@ -200,7 +200,9 @@ void RaviCodeGenerator::emit_refresh_L_top(RaviFunctionDef *def) {
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);
}
void RaviCodeGenerator::emit_set_L_top_toreg(RaviFunctionDef *def, llvm::Instruction *base_ptr, int B) {
void RaviCodeGenerator::emit_set_L_top_toreg(RaviFunctionDef *def,
llvm::Instruction *base_ptr,
int B) {
// L->top = R(B)
// Get pointer to register at R(B)
llvm::Value *ptr = emit_array_get(def, base_ptr, B);
@ -208,8 +210,7 @@ void RaviCodeGenerator::emit_set_L_top_toreg(RaviFunctionDef *def, llvm::Instruc
llvm::Value *top = emit_gep(def, "L.top", def->L, 0, 4);
// Assign to L->top
llvm::Instruction *ins = def->builder->CreateStore(ptr, top);
ins->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_luaState_topT);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);
}
// Check if we can compile
@ -258,6 +259,7 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_MOD:
case OP_SETTABLE:
case OP_GETTABLE:
case OP_GETUPVAL:
@ -398,6 +400,8 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
def->luaV_setlistF = def->raviF->addExternFunction(
def->types->luaV_setlistT, reinterpret_cast<void *>(&luaV_setlist),
"luaV_setlist");
def->luaV_modF = def->raviF->addExternFunction(
def->types->luaV_modT, reinterpret_cast<void *>(&luaV_mod), "luaV_mod");
// Create printf declaration
std::vector<llvm::Type *> args;
@ -407,6 +411,14 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
llvm::FunctionType::get(def->types->C_intT, args, true);
def->printfFunc =
def->raviF->module()->getOrInsertFunction("printf", printfType);
// fmod declaration
args.clear();
args.push_back(def->types->C_doubleT);
args.push_back(def->types->C_doubleT);
llvm::FunctionType *fmodType =
llvm::FunctionType::get(def->types->C_doubleT, args, false);
def->fmodFunc = def->raviF->module()->getOrInsertFunction("fmod", fmodType);
}
#define RA(i) (base + GETARG_A(i))
@ -888,6 +900,12 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
emit_DIVII(&def, L_ci, proto, A, B, C);
} break;
case OP_MOD: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_MOD(&def, L_ci, proto, A, B, C);
} break;
default:
break;
}

@ -29,7 +29,8 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
static_assert(std::is_floating_point<lua_Number>::value &&
sizeof(lua_Number) == sizeof(double),
"lua_Number is not a double");
lua_NumberT = llvm::Type::getDoubleTy(context);
C_doubleT = llvm::Type::getDoubleTy(context);
lua_NumberT = C_doubleT;
plua_NumberT = llvm::PointerType::get(lua_NumberT, 0);
static_assert(sizeof(lua_Integer) == sizeof(lua_Number) &&
@ -740,13 +741,23 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(plua_StateT);
elements.push_back(pCallInfoT);
elements.push_back(pTValueT);
luaV_newarrayintT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_newarrayfloatT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_newarrayintT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_newarrayfloatT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
elements.push_back(C_intT);
elements.push_back(C_intT);
luaV_newtableT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_setlistT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_newtableT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_setlistT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(lua_IntegerT);
elements.push_back(lua_IntegerT);
luaV_modT = llvm::FunctionType::get(lua_IntegerT, elements, false);
for (int j = 0; j < kInt.size(); j++)
kInt[j] = llvm::ConstantInt::get(C_intT, j);

Loading…
Cancel
Save