implement OP_RAVI_GETTABLE_AI and OP_RAVI_GETTABLE_AF

pull/81/head
Dibyendu Majumdar 9 years ago
parent 41e3426314
commit 57c735e63f

@ -535,10 +535,12 @@ public:
llvm::Instruction *emit_load_reg_h(RaviFunctionDef *def, llvm::Value *ra);
// emit code to load pointer to int array
llvm::Instruction *emit_load_reg_h_intarray(RaviFunctionDef *def, llvm::Instruction *ra);
llvm::Instruction *emit_load_reg_h_intarray(RaviFunctionDef *def,
llvm::Instruction *ra);
// emit code to load pointer to double array
llvm::Instruction *emit_load_reg_h_floatarray(RaviFunctionDef *def, llvm::Instruction *ra);
llvm::Instruction *emit_load_reg_h_floatarray(RaviFunctionDef *def,
llvm::Instruction *ra);
// emit code to store lua_Number value into register
void emit_store_reg_n(RaviFunctionDef *def, llvm::Value *value,
@ -558,8 +560,13 @@ public:
// emit code to load the type from a register
llvm::Instruction *emit_load_type(RaviFunctionDef *def, llvm::Value *value);
// emit code to load the type from a register
llvm::Instruction *emit_load_ravi_arraytype(RaviFunctionDef *def, llvm::Value *value);
// emit code to load the array type
llvm::Instruction *emit_load_ravi_arraytype(RaviFunctionDef *def,
llvm::Value *value);
// emit code to load the array length
llvm::Instruction *emit_load_ravi_arraylength(RaviFunctionDef *def,
llvm::Value *value);
// TValue assign
void emit_assign(RaviFunctionDef *def, llvm::Value *ra, llvm::Value *rb);
@ -825,6 +832,12 @@ public:
void emit_TFORLOOP(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int j);
void emit_GETTABLE_AF(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C);
void emit_GETTABLE_AI(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C);
private:
RaviJITStateImpl *jitState_;
char temp_[31]; // for name

@ -179,10 +179,10 @@ Note that if a Lua functions contains a bytecode that cannot be be JITed then th
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_MOVEAF | NO | R(A) := R(B), check R(B) is array of numbers |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_GETTABLE_AI | NO | R(A) := R(B)[RK(C)] where R(B) is array of |
| OP_RAVI_GETTABLE_AI | YES | R(A) := R(B)[RK(C)] where R(B) is array of |
| | | integers and RK(C) is integer |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_GETTABLE_AF | NO | R(A) := R(B)[RK(C)] where R(B) is array of |
| OP_RAVI_GETTABLE_AF | YES | R(A) := R(B)[RK(C)] where R(B) is array of |
| | | numbers and RK(C) is integer |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_SETTABLE_AI | NO | R(A)[RK(B)] := RK(C) where RK(B) is an integer |

@ -204,6 +204,14 @@ llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraytype(RaviFunctionDef *
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, 11, 2);
llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.len");
tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_lenT);
return tt;
}
llvm::Value *RaviCodeGenerator::emit_gep_rkb(RaviFunctionDef *def,
llvm::Instruction *base_ptr,
int B) {
@ -341,6 +349,8 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_RAVI_DIVFI:
case OP_RAVI_DIVIF:
case OP_RAVI_DIVII:
case OP_RAVI_GETTABLE_AI:
case OP_RAVI_GETTABLE_AF:
break;
default:
return false;
@ -860,6 +870,17 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
int C = GETARG_C(i);
emit_GETTABLE(&def, L_ci, proto, A, B, C);
} break;
case OP_RAVI_GETTABLE_AI: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_GETTABLE_AI(&def, L_ci, proto, A, B, C);
} break;
case OP_RAVI_GETTABLE_AF: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_GETTABLE_AF(&def, L_ci, proto, A, B, C);
} break;
case OP_GETTABUP: {
int B = GETARG_B(i);
int C = GETARG_C(i);

@ -40,7 +40,7 @@ void RaviCodeGenerator::emit_SELF(RaviFunctionDef *def, llvm::Value *L_ci,
void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B) {
//Protect(luaV_objlen(L, ra, RB(i)));
// Protect(luaV_objlen(L, ra, RB(i)));
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rb = emit_gep_ra(def, base_ptr, B);
@ -50,7 +50,7 @@ void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, llvm::Value *L_ci,
// R(A)[RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C) {
//Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
// Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
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);
@ -61,7 +61,7 @@ void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, llvm::Value *L_ci,
// R(A) := R(B)[RK(C)]
void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C) {
//Protect(luaV_gettable(L, RB(i), RKC(i), ra));
// Protect(luaV_gettable(L, RB(i), RKC(i), ra));
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rb = emit_gep_ra(def, base_ptr, B);
@ -69,11 +69,136 @@ void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, llvm::Value *L_ci,
def->builder->CreateCall4(def->luaV_gettableF, def->L, rb, rc, ra);
}
void RaviCodeGenerator::emit_GETTABLE_AF(RaviFunctionDef *def,
llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C) {
//#define raviH_get_float_inline(L, t, key, v) \
//{ unsigned ukey = (unsigned)((key)-1); \
// lua_Number *data = (lua_Number *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) {\
// setfltvalue(v, data[ukey]); \
// }else \
// luaG_runerror(L, "array out of bounds"); \
//}
//TValue *rb = RB(i);
//TValue *rc = RKC(i);
//lua_Integer idx = ivalue(rc);
//Table *t = hvalue(rb);
//raviH_get_float_inline(L, t, idx, ra);
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rb = emit_gep_ra(def, base_ptr, B);
llvm::Value *rc = emit_gep_rkb(def, base_ptr, C);
llvm::Instruction *key = emit_load_reg_i(def, rc);
llvm::Instruction *t = emit_load_reg_h(def, rb);
llvm::Instruction *data = emit_load_reg_h_floatarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.in.range", def->f);
llvm::BasicBlock *else_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.not.in.range");
llvm::BasicBlock *end_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.end");
def->builder->CreateCondBr(cmp, then_block, else_block);
def->builder->SetInsertPoint(then_block);
llvm::Value *ptr = def->builder->CreateGEP(data, ukey);
llvm::Instruction *value = def->builder->CreateLoad(ptr);
// TODO tbaa
emit_store_reg_n(def, value, ra);
emit_store_type(def, ra, LUA_TNUMFLT);
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
llvm::Value *errmsg1 =
def->builder->CreateGlobalString("array out of bounds");
def->builder->CreateCall2(def->luaG_runerrorF, def->L,
emit_gep(def, "out_of_bounds_msg", errmsg1, 0, 0));
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(end_block);
def->builder->SetInsertPoint(end_block);
}
void RaviCodeGenerator::emit_GETTABLE_AI(RaviFunctionDef *def,
llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C) {
//#define raviH_get_int_inline(L, t, key, v) \
//{ unsigned ukey = (unsigned)((key)-1); \
// lua_Integer *data = (lua_Integer *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) {\
// setivalue(v, data[ukey]); \
// } else \
// luaG_runerror(L, "array out of bounds"); \
//}
// TValue *rb = RB(i);
// TValue *rc = RKC(i);
// lua_Integer idx = ivalue(rc);
// Table *t = hvalue(rb);
// raviH_get_int_inline(L, t, idx, ra);
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rb = emit_gep_ra(def, base_ptr, B);
llvm::Value *rc = emit_gep_rkb(def, base_ptr, C);
llvm::Instruction *key = emit_load_reg_i(def, rc);
llvm::Instruction *t = emit_load_reg_h(def, rb);
llvm::Instruction *data = emit_load_reg_h_intarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.in.range", def->f);
llvm::BasicBlock *else_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.not.in.range");
llvm::BasicBlock *end_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.end");
def->builder->CreateCondBr(cmp, then_block, else_block);
def->builder->SetInsertPoint(then_block);
llvm::Value *ptr = def->builder->CreateGEP(data, ukey);
llvm::Instruction *value = def->builder->CreateLoad(ptr);
// TODO tbaa
emit_store_reg_i(def, value, ra);
emit_store_type(def, ra, LUA_TNUMINT);
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
llvm::Value *errmsg1 =
def->builder->CreateGlobalString("array out of bounds");
def->builder->CreateCall2(def->luaG_runerrorF, def->L,
emit_gep(def, "out_of_bounds_msg", errmsg1, 0, 0));
def->builder->CreateBr(end_block);
def->f->getBasicBlockList().push_back(end_block);
def->builder->SetInsertPoint(end_block);
}
// R(A) := UpValue[B]
void RaviCodeGenerator::emit_GETUPVAL(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B) {
//int b = GETARG_B(i);
//setobj2s(L, ra, cl->upvals[b]->v);
// int b = GETARG_B(i);
// setobj2s(L, ra, cl->upvals[b]->v);
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *upval_ptr = emit_gep_upvals(def, def->p_LClosure, B);
@ -126,8 +251,8 @@ void RaviCodeGenerator::emit_SETUPVAL(RaviFunctionDef *def, llvm::Value *L_ci,
// R(A) := UpValue[B][RK(C)]
void RaviCodeGenerator::emit_GETTABUP(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C) {
//int b = GETARG_B(i);
//Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
// int b = GETARG_B(i);
// Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
llvm::Instruction *base_ptr = emit_load_base(def);
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *rc = emit_gep_rkb(def, base_ptr, C);

@ -122,6 +122,7 @@ int main(int argc, const char *argv[])
{
int failures = 0;
//
failures += test_luacompexec1("function arrayaccess (); local x: integer[] = {5}; return x[1]; end; assert(ravi.compile(arrayaccess)); return arrayaccess()", 5);
failures += test_luacompexec1("function cannotload (msg, a,b); assert(not a and string.find(b, msg)); end; ravi.compile(cannotload); return 1", 1);
failures += test_luacompexec1("function z(); local a = 5; a = a + 1; return a; end; ravi.compile(z); return z()", 6);
failures += test_luacompexec1("function z(x); x[1] = 5; return x[1]; end; ravi.compile(z); return z({})", 5);

Loading…
Cancel
Save