Skip to content

Commit

Permalink
implement TFORCALL and TFORLOOP
Browse files Browse the repository at this point in the history
  • Loading branch information
Dibyendu Majumdar committed Mar 21, 2015
1 parent 362a544 commit ab97712
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 28 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ set (LUA_CORE_SRCS src/lapi.c src/lcode.c src/lctype.c src/ldebug.c src/ldo.c sr
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_llvmtable.cpp
src/ravi_llvmarith2.cpp)
src/ravi_llvmarith2.cpp src/ravi_llvmtforcall.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)
Expand Down
2 changes: 1 addition & 1 deletion clang-output/lua_upval.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ extern void luaC_upvalbarrier_ (struct lua_State *L, struct UpVal *uv);

void luaV_op_call(struct lua_State *L, struct LClosure *cl, struct TValue *ra, int b, int c) {
struct UpVal *uv = cl->upvals[b];
ra->tt_ = uv->tt_;

uv->v->tt_ = ra->tt_;
uv->v->value_.n = ra->value_.n;
int b1 = iscollectable(uv->v);
Expand Down
9 changes: 9 additions & 0 deletions include/ravi_llvmcodegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,9 @@ class RaviCodeGenerator {
llvm::Value *emit_boolean_testfalse(RaviFunctionDef *def, llvm::Value *reg,
bool donot);

void emit_refresh_L_top(RaviFunctionDef *def);


// Look for Lua bytecodes that are jump targets and allocate
// a BasicBlock for each such target in def->jump_targets.
// The BasicBlocks are not inserted into the function until later
Expand Down Expand Up @@ -737,6 +740,12 @@ class RaviCodeGenerator {
void emit_TESTSET(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C, int j, int jA);

void emit_TFORCALL(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C, int j, int jA);

void emit_TFORLOOP(RaviFunctionDef *def, llvm::Value *L_ci, llvm::Value *proto,
int A, int j);

private:
RaviJITStateImpl *jitState_;
char temp_[31]; // for name
Expand Down
46 changes: 25 additions & 21 deletions lua-5.3.0-tests/pm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -108,27 +108,31 @@ local function range (i, j)
end
end

local abc = string.char(range(0, 255));

assert(string.len(abc) == 256)

function strset (p)
local res = {s=''}
string.gsub(abc, p, function (c) res.s = res.s .. c end)
return res.s
end;

assert(string.len(strset('[\200-\210]')) == 11)

assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz")
assert(strset('[a-z%d]') == strset('[%da-uu-z]'))
assert(strset('[a-]') == "-a")
assert(strset('[^%W]') == strset('[%w]'))
assert(strset('[]%%]') == '%]')
assert(strset('[a%-z]') == '-az')
assert(strset('[%^%[%-a%]%-b]') == '-[]^ab')
assert(strset('%Z') == strset('[\1-\255]'))
assert(strset('.') == strset('[\1-\255%z]'))
if not ravi.auto() then
local abc = string.char(range(0, 255));

assert(string.len(abc) == 256)

function strset (p)
local res = {s=''}
string.gsub(abc, p, function (c) res.s = res.s .. c end)
return res.s
end;

assert(string.len(strset('[\200-\210]')) == 11)

assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz")
assert(strset('[a-z%d]') == strset('[%da-uu-z]'))
assert(strset('[a-]') == "-a")
assert(strset('[^%W]') == strset('[%w]'))
assert(strset('[]%%]') == '%]')
assert(strset('[a%-z]') == '-az')
assert(strset('[%^%[%-a%]%-b]') == '-[]^ab')
assert(strset('%Z') == strset('[\1-\255]'))
assert(strset('.') == strset('[\1-\255%z]'))

end

print('+');

assert(string.match("alo xyzK", "(%w+)K") == "xyz")
Expand Down
17 changes: 16 additions & 1 deletion ravi-tests/ravi_tests1.ravi
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,19 @@ y=x()
y[1] = 99.67
assert(y[1], 99.67)
assert(#y == 1)
print("test 29 OK")
print("test 29 OK")

-- test 30
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
x = function()
local t
for k,v in pairs(days) do
print(k,v)
t = v
end
return t
end
assert(ravi.compile(x))
assert(x() == "Saturday")
print("test 30 OK")
8 changes: 4 additions & 4 deletions readthedocs/ravi-jit-status.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ Note that if a Lua functions contains a bytecode that cannot be be JITed then th
+-------------------------+----------+--------------------------------------------------+
| OP_FORPREP | YES | R(A)-=R(A+2); pc+=sBx |
+-------------------------+----------+--------------------------------------------------+
| OP_TFORCALL | NO | R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); |
| OP_TFORCALL | YES | R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); |
+-------------------------+----------+--------------------------------------------------+
| OP_TFORLOOP | NO | if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } |
| OP_TFORLOOP | YES | if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } |
+-------------------------+----------+--------------------------------------------------+
| OP_SETLIST | YES | R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B |
+-------------------------+----------+--------------------------------------------------+
Expand All @@ -107,9 +107,9 @@ Note that if a Lua functions contains a bytecode that cannot be be JITed then th
+-------------------------+----------+--------------------------------------------------+
| OP_EXTRAARG | NO | extra (larger) argument for previous opcode |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_NEWARRAYI | NO | R(A) := array of int |
| OP_RAVI_NEWARRAYI | YES | R(A) := array of int |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_NEWARRAYF | NO | R(A) := array of float |
| OP_RAVI_NEWARRAYF | YES | R(A) := array of float |
+-------------------------+----------+--------------------------------------------------+
| OP_RAVI_LOADIZ | YES | R(A) := tointeger(0) |
+-------------------------+----------+--------------------------------------------------+
Expand Down
1 change: 1 addition & 0 deletions src/ravi_llvmcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ void RaviCodeGenerator::emit_CALL(RaviFunctionDef *def, llvm::Value *L_ci,
def->builder->CreateCondBr(precall_C, then1_block, end_block);
def->builder->SetInsertPoint(then1_block);

// TODO replace below with emit_refresh_L_top()
// Get pointer to ci->top
llvm::Value *citop = emit_gep(def, "ci_top", def->ci_val, 0, 1);
// Load ci->top
Expand Down
23 changes: 23 additions & 0 deletions src/ravi_llvmcodegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_TESTSET:
case OP_FORPREP:
case OP_FORLOOP:
case OP_TFORCALL:
case OP_TFORLOOP:
case OP_MOVE:
case OP_ADD:
case OP_SUB:
Expand Down Expand Up @@ -625,6 +627,25 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
int j = sbx + pc + 1;
emit_EQ(&def, L_ci, proto, A, B, C, j, GETARG_A(i), comparison_function);
} break;
case OP_TFORCALL: {
int B = GETARG_B(i);
int C = GETARG_C(i);
// OP_TFORCALL is followed by OP_TFORLOOP - we process this
// along with OP_TFORCALL
pc++;
i = code[pc];
op = GET_OPCODE(i);
lua_assert(op == OP_TFORLOOP);
int sbx = GETARG_sBx(i);
// j below is the jump target
int j = sbx + pc + 1;
emit_TFORCALL(&def, L_ci, proto, A, B, C, j, GETARG_A(i));
} break;
case OP_TFORLOOP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
emit_TFORLOOP(&def, L_ci, proto, A, j);
} break;
case OP_TEST: {
int B = GETARG_B(i);
int C = GETARG_C(i);
Expand Down Expand Up @@ -659,6 +680,7 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
int j = sbx + pc + 1;
emit_JMP(&def, j);
} break;

case OP_FORPREP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
Expand All @@ -677,6 +699,7 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
emit_FORLOOP(&def, L_ci, proto, A, j);
#endif
} break;

case OP_LOADNIL: {
int B = GETARG_B(i);
emit_LOADNIL(&def, L_ci, proto, A, B);
Expand Down
152 changes: 152 additions & 0 deletions src/ravi_llvmtforcall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/******************************************************************************
* 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 {

void RaviCodeGenerator::emit_refresh_L_top(RaviFunctionDef *def) {
// 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);
// TODO set tbaa
// Get L->top
llvm::Value *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);
}

void RaviCodeGenerator::emit_TFORCALL(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int B, int C,
int j, int jA) {

// case OP_TFORCALL: {
// StkId cb = ra + 3; /* call base */
// setobjs2s(L, cb + 2, ra + 2);
// setobjs2s(L, cb + 1, ra + 1);
// setobjs2s(L, cb, ra);
// L->top = cb + 3; /* func. + 2 args (state and index) */
// Protect(luaD_call(L, cb, GETARG_C(i), 1));
// L->top = ci->top;
// i = *(ci->u.l.savedpc++); /* go to next instruction */
// ra = RA(i);
// lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
// goto l_tforloop;
// }
// case OP_TFORLOOP: {
// l_tforloop:
// if (!ttisnil(ra + 1)) { /* continue loop? */
// setobjs2s(L, ra, ra + 1); /* save control variable */
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
// }
// } break;

// Load pointer to base
llvm::Instruction *base_ptr = emit_load_base(def);

// Get pointer to register A
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *ra1 = emit_gep_ra(def, base_ptr, A + 1);
llvm::Value *ra2 = emit_gep_ra(def, base_ptr, A + 2);
llvm::Value *cb = emit_gep_ra(def, base_ptr, A + 3);
llvm::Value *cb1 = emit_gep_ra(def, base_ptr, A + 4);
llvm::Value *cb2 = emit_gep_ra(def, base_ptr, A + 5);

emit_assign(def, cb2, ra2);
emit_assign(def, cb1, ra1);
emit_assign(def, cb, ra);

// Get pointer to register at cb+3
llvm::Value *cb3 = emit_gep_ra(def, base_ptr, A + 6);
// Get pointer to L->top
llvm::Value *top = emit_gep(def, "L_top", def->L, 0, 4);
// Assign to L->top
llvm::Instruction *ins = def->builder->CreateStore(cb3, top);
ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_luaState_topT);

def->builder->CreateCall4(def->luaD_callF, def->L, cb, def->types->kInt[C],
def->types->kInt[1]);
// reload base
base_ptr = emit_load_base(def);
emit_refresh_L_top(def);
ra = emit_gep_ra(def, base_ptr, jA);
ra1 = emit_gep_ra(def, base_ptr, jA + 1);
llvm::Value *type = emit_load_type(def, ra1);

// Test if type != LUA_TNIL (0)
llvm::Value *isnotnil = def->builder->CreateICmpNE(type, def->types->kInt[0]);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.not.nil", def->f);
llvm::BasicBlock *else_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.nil");
def->builder->CreateCondBr(isnotnil, then_block, else_block);
def->builder->SetInsertPoint(then_block);

emit_assign(def, ra, ra1);
// Do the jump
def->builder->CreateBr(def->jmp_targets[j].jmp1);

// Add the else block and make it current so that the next instruction flows
// here
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
}

void RaviCodeGenerator::emit_TFORLOOP(RaviFunctionDef *def, llvm::Value *L_ci,
llvm::Value *proto, int A, int j) {
// case OP_TFORLOOP: {
// l_tforloop:
// if (!ttisnil(ra + 1)) { /* continue loop? */
// setobjs2s(L, ra, ra + 1); /* save control variable */
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
// }
// } break;

// Load pointer to base
llvm::Instruction *base_ptr = emit_load_base(def);

// Get pointer to register A
llvm::Value *ra = emit_gep_ra(def, base_ptr, A);
llvm::Value *ra1 = emit_gep_ra(def, base_ptr, A + 1);
llvm::Value *type = emit_load_type(def, ra1);

// Test if type != LUA_TNIL (0)
llvm::Value *isnotnil = def->builder->CreateICmpNE(type, def->types->kInt[0]);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.not.nil", def->f);
llvm::BasicBlock *else_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.nil");
def->builder->CreateCondBr(isnotnil, then_block, else_block);
def->builder->SetInsertPoint(then_block);

emit_assign(def, ra, ra1);
// Do the jump
def->builder->CreateBr(def->jmp_targets[j].jmp1);

// Add the else block and make it current so that the next instruction flows
// here
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
}
}

0 comments on commit ab97712

Please sign in to comment.