implement OP_IDIV

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

@ -202,6 +202,8 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_tonumberT;
llvm::FunctionType *luaV_tointegerT;
llvm::FunctionType *luaV_modT;
llvm::FunctionType *luaV_objlenT;
llvm::FunctionType *luaV_divT;
llvm::FunctionType *luaV_executeT;
llvm::FunctionType *luaV_gettableT;
@ -409,6 +411,8 @@ struct RaviFunctionDef {
llvm::Constant *luaV_gettableF;
llvm::Constant *luaV_settableF;
llvm::Constant *luaV_modF;
llvm::Constant *luaV_divF;
llvm::Constant *luaV_objlenF;
// Some cheats - these correspond to OPCODEs that
// are not inlined as of now
@ -418,9 +422,10 @@ struct RaviFunctionDef {
llvm::Constant *luaV_newtableF;
llvm::Constant *luaV_op_loadnilF;
// printf
// standard C functions
llvm::Constant *printfFunc;
llvm::Constant *fmodFunc;
llvm::Constant *floorFunc;
// Jump targets in the function
std::vector<RaviBranchDef> jmp_targets;
@ -591,6 +596,9 @@ public:
void emit_MOD(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C);
void emit_IDIV(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);

@ -432,4 +432,13 @@ 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")
print("test 32 OK")
-- test 33
x=function(a,b)
return a//b
end
assert(ravi.compile(x))
assert(x(5,2) == 2)
assert(math.abs(x(5.5,2.1)-2.0) < 1e-12)
print("test 33 OK")

@ -49,7 +49,7 @@ Note that if a Lua functions contains a bytecode that cannot be be JITed then th
+-------------------------+----------+--------------------------------------------------+
| OP_DIV | YES | R(A) := RK(B) / RK(C) |
+-------------------------+----------+--------------------------------------------------+
| OP_IDIV | NO | R(A) := RK(B) // RK(C) |
| OP_IDIV | YES | R(A) := RK(B) // RK(C) |
+-------------------------+----------+--------------------------------------------------+
| OP_BAND | NO | R(A) := RK(B) & RK(C) |
+-------------------------+----------+--------------------------------------------------+

@ -434,4 +434,175 @@ void RaviCodeGenerator::emit_MOD(RaviFunctionDef *def, llvm::Value *L_ci,
def->f->getBasicBlockList().push_back(done_block);
def->builder->SetInsertPoint(done_block);
}
// OP_IDIV
void RaviCodeGenerator::emit_IDIV(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_div(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");
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_divF, 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);
result = def->builder->CreateFDiv(lhs, rhs);
llvm::Value *floor_result = def->builder->CreateCall(def->floorFunc, result);
emit_store_reg_n(def, floor_result, 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);
}
}

@ -260,6 +260,7 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_MUL:
case OP_DIV:
case OP_MOD:
case OP_IDIV:
case OP_SETTABLE:
case OP_GETTABLE:
case OP_GETUPVAL:
@ -402,6 +403,11 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
"luaV_setlist");
def->luaV_modF = def->raviF->addExternFunction(
def->types->luaV_modT, reinterpret_cast<void *>(&luaV_mod), "luaV_mod");
def->luaV_divF = def->raviF->addExternFunction(
def->types->luaV_divT, reinterpret_cast<void *>(&luaV_div), "luaV_div");
def->luaV_objlenF = def->raviF->addExternFunction(
def->types->luaV_objlenT, reinterpret_cast<void *>(&luaV_objlen),
"luaV_objlen");
// Create printf declaration
std::vector<llvm::Type *> args;
@ -412,13 +418,21 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
def->printfFunc =
def->raviF->module()->getOrInsertFunction("printf", printfType);
// fmod declaration
// stdc 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);
// stdc floor declaration
args.clear();
args.push_back(def->types->C_doubleT);
llvm::FunctionType *floorType =
llvm::FunctionType::get(def->types->C_doubleT, args, false);
def->floorFunc =
def->raviF->module()->getOrInsertFunction("floor", floorType);
}
#define RA(i) (base + GETARG_A(i))
@ -905,6 +919,11 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
int C = GETARG_C(i);
emit_MOD(&def, L_ci, proto, A, B, C);
} break;
case OP_IDIV: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_IDIV(&def, L_ci, proto, A, B, C);
} break;
default:
break;

@ -715,6 +715,9 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(plua_StateT);
elements.push_back(pTValueT);
elements.push_back(pTValueT);
luaV_objlenT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
elements.push_back(pTValueT);
luaV_gettableT =
llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
@ -758,6 +761,7 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(lua_IntegerT);
elements.push_back(lua_IntegerT);
luaV_modT = llvm::FunctionType::get(lua_IntegerT, elements, false);
luaV_divT = 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