implement OP_SETTABLE and OP_GETTABLE

Dibyendu Majumdar 9 years ago
parent 684cad6f9f
commit b238cb4818

@ -70,7 +70,7 @@ set (LUA_CORE_SRCS src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c sr
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_llvmarith1.cpp src/ravi_llvmcall.cpp)
src/ravi_llvmarith1.cpp src/ravi_llvmcall.cpp src/ravi_llvmtable.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)

@ -197,6 +197,8 @@ struct LuaLLVMTypes {
llvm::FunctionType *luaV_tonumberT;
llvm::FunctionType *luaV_tointegerT;
llvm::FunctionType *luaV_executeT;
llvm::FunctionType *luaV_gettableT;
llvm::FunctionType *luaV_settableT;
llvm::FunctionType *luaV_op_loadnilT;
@ -386,6 +388,8 @@ struct RaviFunctionDef {
llvm::Constant *luaV_tonumberF;
llvm::Constant *luaV_tointegerF;
llvm::Constant *luaV_executeF;
llvm::Constant *luaV_gettableF;
llvm::Constant *luaV_settableF;
// Some cheats
llvm::Constant *luaV_op_loadnilF;
@ -622,6 +626,11 @@ public:
void emit_TOFLT(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A);
void emit_SETTABLE(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C);
void emit_GETTABLE(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C);
// Emit code for OP_EQ, OP_LT and OP_LE
// The callee parameter should be luaV_equalobj, luaV_lessthan and

@ -218,7 +218,7 @@ function tryme(x,y)
return 0
end
end
ravi.dumplua(tryme)
--ravi.dumplua(tryme)
assert(ravi.compile(tryme))
assert(tryme(1,2) == 1)
assert(tryme(2,1) == 0)
@ -228,10 +228,21 @@ print("test 16 OK")
function tryme(x,y)
return x < y
end
ravi.dumplua(tryme)
--ravi.dumplua(tryme)
assert(ravi.compile(tryme))
assert(tryme(1,2))
assert(not tryme(2,1))
print("test 17 OK")
-- test 18
function tabtest(x)
x[1] = 5
return x[1]
end
--ravi.dumplua(tabtest)
assert(ravi.compile(tabtest))
--ravi.dumpllvm(tabtest)
assert(tabtest({}) == 5)
print("test 18 OK")

@ -146,10 +146,10 @@ void RaviCodeGenerator::emit_store_reg_i(RaviFunctionDef *def,
}
void RaviCodeGenerator::emit_store_reg_b(RaviFunctionDef *def,
llvm::Value *result,
llvm::Value *dest_ptr) {
llvm::Value *result,
llvm::Value *dest_ptr) {
llvm::Value *ra_n =
def->builder->CreateBitCast(dest_ptr, def->types->C_pintT);
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);
}
@ -157,7 +157,8 @@ void RaviCodeGenerator::emit_store_reg_b(RaviFunctionDef *def,
void RaviCodeGenerator::emit_store_type(RaviFunctionDef *def,
llvm::Value *value, int type) {
llvm::Value *desttype = emit_gep(def, "dest.tt", value, 0, 1);
lua_assert(type == LUA_TNUMFLT || type == LUA_TNUMINT || type == LUA_TBOOLEAN);
lua_assert(type == LUA_TNUMFLT || type == LUA_TNUMINT ||
type == LUA_TBOOLEAN);
llvm::Instruction *store =
def->builder->CreateStore(def->types->kInt[type], desttype);
store->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT);
@ -201,7 +202,7 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
int pc, n = p->sizecode;
// TODO we cannot handle variable arguments or
// if the function has sub functions (closures)
//if (p->sizep > 0 || p->is_vararg) {
// if (p->sizep > 0 || p->is_vararg) {
if (p->is_vararg) {
p->ravi_jit.jit_status = 1;
return false;
@ -224,6 +225,8 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_FORPREP:
case OP_FORLOOP:
case OP_MOVE:
case OP_SETTABLE:
case OP_GETTABLE:
case OP_RAVI_MOVEI:
case OP_RAVI_MOVEF:
case OP_RAVI_TOINT:
@ -329,6 +332,12 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) {
def->luaV_executeF = def->raviF->addExternFunction(
def->types->luaV_executeT, reinterpret_cast<void *>(&luaV_execute),
"luaV_execute");
def->luaV_settableF = def->raviF->addExternFunction(
def->types->luaV_settableT, reinterpret_cast<void *>(&luaV_settable),
"luaV_settable");
def->luaV_gettableF = def->raviF->addExternFunction(
def->types->luaV_gettableT, reinterpret_cast<void *>(&luaV_gettable),
"luaV_gettable");
def->luaV_op_loadnilF = def->raviF->addExternFunction(
def->types->luaV_op_loadnilT, reinterpret_cast<void *>(&luaV_op_loadnil),
"luaV_op_loadnil");
@ -475,7 +484,7 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
case OP_LOADBOOL: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_LOADBOOL(&def, L_ci, proto, A, B, C, pc+2);
emit_LOADBOOL(&def, L_ci, proto, A, B, C, pc + 2);
} break;
case OP_MOVE: {
int B = GETARG_B(i);
@ -558,6 +567,17 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
emit_CALL(&def, L_ci, proto, A, B, C);
} break;
case OP_SETTABLE: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_SETTABLE(&def, L_ci, proto, A, B, C);
} break;
case OP_GETTABLE: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_GETTABLE(&def, L_ci, proto, A, B, C);
} break;
case OP_RAVI_ADDFN: {
int B = GETARG_B(i);
int C = GETARG_C(i);
@ -706,7 +726,8 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
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");
def->jmp_targets[j].jmp1 =
llvm::BasicBlock::Create(def->jitState->context(), "loadbool");
} break;
case OP_JMP:
case OP_FORLOOP:
@ -730,15 +751,15 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
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);
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
// 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 =

@ -102,41 +102,7 @@ void RaviCodeGenerator::emit_RETURN(RaviFunctionDef *def, llvm::Value *L_ci,
def->builder->SetInsertPoint(else_block);
//* b = luaD_poscall(L, ra);
llvm::Value *result =
def->builder->CreateCall2(def->luaD_poscallF, def->L, ra_ptr);
// I don't think we need below as we are not in the same
// luaV_execute() as the calling function -
// TODO check this is the case
// if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
// return; /* external invocation: return */
//* if (b) L->top = ci->top;
// Test if b is != 0
llvm::Value *result_is_notzero =
def->builder->CreateICmpNE(result, def->types->kInt[0]);
llvm::BasicBlock *ThenBB =
llvm::BasicBlock::Create(def->jitState->context(), "if.then", def->f);
llvm::BasicBlock *ElseBB =
llvm::BasicBlock::Create(def->jitState->context(), "if.else");
def->builder->CreateCondBr(result_is_notzero, ThenBB, ElseBB);
def->builder->SetInsertPoint(ThenBB);
// Get pointer to ci->top
llvm::Value *citop = emit_gep(def, "ci_top", def->ci_val, 0, 1);
// Load ci->top
llvm::Instruction *citop_val = def->builder->CreateLoad(citop);
if (!top)
// Get L->top
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);
def->builder->CreateBr(ElseBB);
def->f->getBasicBlockList().push_back(ElseBB);
def->builder->SetInsertPoint(ElseBB);
// as our prototype is lua_Cfunction we need
// to return a value
def->builder->CreateCall2(def->luaD_poscallF, def->L, ra_ptr);
def->builder->CreateRet(def->types->kInt[1]);
}
}

@ -0,0 +1,46 @@
/******************************************************************************
* Copyright (C) 2015 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 {
// 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) {
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);
def->builder->CreateCall4(def->luaV_settableF, def->L, ra, rb, rc);
}
// 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) {
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);
def->builder->CreateCall4(def->luaV_gettableF, def->L, rb, rc, ra);
}
}

@ -677,6 +677,14 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(plua_IntegerT);
luaV_tointegerT = llvm::FunctionType::get(C_intT, elements, false);
elements.clear();
elements.push_back(plua_StateT);
elements.push_back(pTValueT);
elements.push_back(pTValueT);
elements.push_back(pTValueT);
luaV_gettableT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
luaV_settableT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false);
elements.clear();
elements.push_back(pCallInfoT);
elements.push_back(C_intT);

@ -122,6 +122,7 @@ int main(int argc, const char *argv[])
{
int failures = 0;
//
failures += test_luacompexec1("function z(x); x[1] = 5; return x[1]; end; ravi.compile(z); return z({})", 5);
failures += test_luacompexec1("function z(x,y) return x<y end; ravi.compile(z); return not z(2,1)", 1);
failures += test_luacompexec1("local function x(); local d:number = 5.0; return d+5 == 5+d and d-5 == 5-d and d*5 == 5*d; end; local y = x(); return y", 1);
failures += test_luacompexec1("function x(f); local i : integer, j : integer = f(); return i + j; end; return ravi.compile(x)", 1);

Loading…
Cancel
Save