issue #57 adding test cases

pull/81/head
Dibyendu Majumdar 9 years ago
parent 84b5b6476c
commit ed44f85a3d

@ -514,6 +514,8 @@ LUA_API void ravi_dump_stacktop(lua_State *L, const char *s);
LUA_API void ravi_debug_trace(lua_State *L, int opCode, int pc);
LUA_API void ravi_print_function(const struct Proto *f, int full);
LUA_API void ravi_dump_function(lua_State *L);
LUA_API int ravi_list_code(lua_State *L);
LUA_API int ravi_get_limits(lua_State *L);
LUAI_DDEC int ravi_parser_debug;
LUA_API void ravi_set_debuglevel(int level);

@ -1,5 +1,183 @@
ravi.auto(true)
print "testing code generation and optimizations"
T = ravi
-- this code gave an error for the code checker
do
local function f (a)
for k,v,w in a do end
end
end
-- testing opcodes
function check (f, ...)
local arg = {...}
local c = T.listcode(f)
for i=1, #arg do
-- print(arg[i], c[i])
assert(string.find(c[i], '- '..arg[i]..' *[AB][xs]?=%d'))
end
assert(c[#arg+2] == nil)
end
function checkequal (a, b)
a = T.listcode(a)
b = T.listcode(b)
for i = 1, #a do
a[i] = string.gsub(a[i], '%b()', '') -- remove line number
b[i] = string.gsub(b[i], '%b()', '') -- remove line number
assert(a[i] == b[i])
end
end
-- some basic instructions
check(function ()
(function () end){f()}
end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
-- sequence of LOADNILs
check(function ()
local a,b,c
local d; local e;
local f,g,h;
d = nil; d=nil; b=nil; a=nil; c=nil;
end, 'LOADNIL', 'RETURN')
check(function ()
local a,b,c,d = 1,1,1,1
d=nil;c=nil;b=nil;a=nil
end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN')
do
local a,b,c,d = 1,1,1,1
d=nil;c=nil;b=nil;a=nil
assert(a == nil and b == nil and c == nil and d == nil)
end
-- single return
check (function (a,b,c) return a end, 'RETURN')
-- infinite loops
check(function () while true do local a = -1 end end,
'LOADK', 'JMP', 'RETURN')
check(function () while 1 do local a = -1 end end,
'LOADK', 'JMP', 'RETURN')
check(function () repeat local x = 1 until true end,
'LOADK', 'RETURN')
-- concat optimization
check(function (a,b,c,d) return a..b..c..d end,
'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
-- not
check(function () return not not nil end, 'LOADBOOL', 'RETURN')
check(function () return not not false end, 'LOADBOOL', 'RETURN')
check(function () return not not true end, 'LOADBOOL', 'RETURN')
check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
-- direct access to locals
check(function ()
local a,b,c,d
a = b*2
c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b
end,
'LOADNIL',
'MUL',
'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
-- direct access to constants
check(function ()
local a,b
a.x = 0
a.x = b
a[b] = 'y'
a = 1 - a
b = 1/a
b = 5+4
a[true] = false
end,
'LOADNIL',
'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK',
'SETTABLE', 'RETURN')
-- no foldings
check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN')
--check(function () return 3/0 end, 'DIV', 'RETURN')
check(function () return 0%0 end, 'MOD', 'RETURN')
check(function () return -4//0 end, 'IDIV', 'RETURN')
-- bug in constant folding for 5.1
check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN')
check(function ()
local a,b,c
b[c], a = c, b
b[a], a = c, b
a, b = c, a
a = a
end,
'LOADNIL',
'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE',
-- no code for a = a
'RETURN')
-- x == nil , x ~= nil
checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
check(function () if a==nil then a=1 end end,
'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
-- de morgan
checkequal(function () local a; if not (a or b) then b=a end end,
function () local a; if (not a and not b) then b=a end end)
checkequal(function (l) local a; return 0 <= a and a <= l end,
function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
-- if-goto optimizations
check(function (a)
if a == 1 then goto l1
elseif a == 2 then goto l2
elseif a == 3 then goto l2
else if a == 4 then goto l3
else goto l3
end
end
::l1:: ::l2:: ::l3:: ::l4::
end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN')
checkequal(
function (a) while a < 10 do a = a + 1 end end,
function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1;
goto L2; ::L1:: end
)
checkequal(
function (a) while a < 10 do a = a + 1 end end,
function (a) while true do if not(a < 10) then break end; a = a + 1; end end
)
print 'OK'
local z,x,y
-- test 1
@ -728,10 +906,19 @@ t.__idiv = function(...) return 'idiv' end
local t1=setmetatable({1,2,3}, t)
local t2=setmetatable({4,5,6}, t)
local x= function() return t1//t2 end
check(x, 'GETUPVAL', 'GETUPVAL', 'IDIV', 'RETURN', 'RETURN')
local s1=x()
assert(s1 == 'idiv')
assert(ravi.compile(t.__idiv))
assert(ravi.compile(x))
local s2=x()
assert(s1 == s2)
print'test 41 OK'
local x= function(t1: number, t2: number) return t1//t2 end
check(x, 'TOFLT', 'TOFLT', 'IDIV', 'RETURN', 'RETURN')
local s1=x(4.1,2.0)
assert(s1 == 2)
assert(ravi.compile(x))
local s2=x(4.1,2.0)
assert(s1 == s2)
print'test 41 (IDIV) OK'

@ -308,6 +308,30 @@ const char* raviP_instruction_to_str(char *buf, size_t n, Instruction i) {
return buf;
}
static char *buildop(Proto *p, int pc, char *buff) {
Instruction i = p->code[pc];
OpCode o = GET_OPCODE(i);
const char *name = luaP_opnames[o];
int line = getfuncline(p, pc);
sprintf(buff, "(%4d) %4d - ", line, pc);
switch (getOpMode(o)) {
case iABC:
sprintf(buff + strlen(buff), "%-12s%4d %4d %4d", name,
GETARG_A(i), GETARG_B(i), GETARG_C(i));
break;
case iABx:
sprintf(buff + strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
break;
case iAsBx:
sprintf(buff + strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
break;
case iAx:
sprintf(buff + strlen(buff), "%-12s%4d", name, GETARG_Ax(i));
break;
}
return buff;
}
static void PrintString(const TString* ts)
{
const char* s=getstr(ts);
@ -576,4 +600,54 @@ void ravi_dump_function(lua_State *L)
Proto* f;
f = toproto(L, -1);
ravi_print_function(f, 1);
}
}
static void setnameval(lua_State *L, const char *name, int val) {
lua_pushstring(L, name);
lua_pushinteger(L, val);
lua_settable(L, -3);
}
#define obj_at(L,k) (L->ci->func + (k))
#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1)
static void pushobject(lua_State *L, const TValue *o) {
setobj2s(L, L->top, o);
api_incr_top(L);
}
static char *buildop2(Proto *p, int pc, char *buff, size_t len) {
Instruction i = p->code[pc];
int line = getfuncline(p, pc);
snprintf(buff, len, "(%4d) %4d - ", line, pc);
raviP_instruction_to_str(buff + strlen(buff), len - strlen(buff), p->code[pc]);
return buff;
}
int ravi_list_code(lua_State *L) {
int pc;
Proto *p;
p = getproto(obj_at(L, 1));
lua_newtable(L);
setnameval(L, "maxstack", p->maxstacksize);
setnameval(L, "numparams", p->numparams);
for (pc = 0; pc<p->sizecode; pc++) {
char buff[100];
lua_pushinteger(L, pc + 1);
lua_pushstring(L, buildop2(p, pc, buff, sizeof buff));
lua_settable(L, -3);
}
return 1;
}
int ravi_get_limits(lua_State *L) {
lua_createtable(L, 0, 5);
setnameval(L, "BITS_INT", LUAI_BITSINT);
setnameval(L, "MAXARG_Ax", MAXARG_Ax);
setnameval(L, "MAXARG_Bx", MAXARG_Bx);
setnameval(L, "MAXARG_sBx", MAXARG_sBx);
setnameval(L, "BITS_INT", LUAI_BITSINT);
setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
setnameval(L, "NUM_OPCODES", NUM_OPCODES);
return 1;
}

@ -32,6 +32,11 @@ extern "C" {
#include "lobject.h"
#include "lstate.h"
#include "lauxlib.h"
#include "lapi.h"
#include "lopcodes.h"
#include "lfunc.h"
#include <string.h>
// Test if the given function is compiled
static int ravi_is_compiled(lua_State *L) {
@ -202,6 +207,11 @@ static int ravi_traceenable(lua_State *L) {
return 1;
}
static int ravi_listcode(lua_State *L) {
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
return ravi_list_code(L);
}
static const luaL_Reg ravilib[] = {{"iscompiled", ravi_is_compiled},
{"compile", ravi_compile},
@ -216,6 +226,8 @@ static const luaL_Reg ravilib[] = {{"iscompiled", ravi_is_compiled},
{"sizelevel", ravi_sizelevel},
{"gcstep", ravi_gcstep},
{"tracehook", ravi_traceenable},
{"listcode", ravi_listcode},
{"limits", ravi_get_limits},
{NULL, NULL}};
LUAMOD_API int raviopen_llvmjit(lua_State *L) {

Loading…
Cancel
Save