pull/168/head
dibyendumajumdar 5 years ago
commit 2672b86904

@ -30,6 +30,7 @@ if (ASM_VM)
# For now we switch to static build
# TODO A fix is needed to ensure that in shared library the asm functions are resolved
set(STATIC_BUILD ON)
# LTESTS messes with global state and breaks the ASMVM dispatch table
set(LTESTS OFF)
set(LLVM_JIT OFF)
set(OMR_JIT OFF)
@ -423,58 +424,55 @@ set(NOJIT_RAVI_SRCS
${DMR_C_JIT_SRCS}
src/ravi_nojit.c)
# We always build a static library without JIT so that
# we can create some default executables
add_library(libravinojit_static
${NOJIT_RAVI_SRCS})
set_target_properties(libravinojit_static PROPERTIES PREFIX "") # As we already prefix with lib
target_link_libraries(libravinojit_static ${EXTRA_LIBRARIES})
# Create a simple NoJIT version of statically linked ravi
# This is sometimes useful in other projects that just need a Lua commandline
# but do not care about the shared library
add_executable(ravi_s
src/lua.c)
target_link_libraries(ravi_s libravinojit_static)
# Ravi VSCode Debug adapter
set(RAVI_DEBUGGER_TARGET ravidebug)
add_executable(${RAVI_DEBUGGER_TARGET}
vscode-debugger/src/ravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(${RAVI_DEBUGGER_TARGET} libravinojit_static)
# Tests for VSCode Debug Adapter
add_executable(testravidebug
vscode-debugger/src/testravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(testravidebug libravinojit_static)
# Simple VM tests
add_executable(test_vm tests/test_vm.c)
target_link_libraries(test_vm ${LIBRAVI_NAME})
if (LLVM_JIT)
# LLVM playground
add_executable(test_llvm tests/test_llvm.cpp)
set_target_properties(test_llvm PROPERTIES COMPILE_DEFINITIONS "USE_LLVM=1")
target_link_libraries(test_llvm ${LIBRAVI_NAME})
endif ()
add_executable(test_misc tests/test_misc.c)
if (NOT ASM_VM)
set(RAVI_STATICEXEC_TARGET ravi_s)
# We always build a static library without JIT so that
# we can create some default executables
add_library(libravinojit_static
${NOJIT_RAVI_SRCS})
set_target_properties(libravinojit_static PROPERTIES PREFIX "") # As we already prefix with lib
target_link_libraries(libravinojit_static ${EXTRA_LIBRARIES})
# Create a simple NoJIT version of statically linked ravi
# This is sometimes useful in other projects that just need a Lua commandline
# but do not care about the shared library
add_executable(ravi_s
src/lua.c)
target_link_libraries(ravi_s libravinojit_static)
# Ravi VSCode Debug adapter
set(RAVI_DEBUGGER_TARGET ravidebug)
add_executable(${RAVI_DEBUGGER_TARGET}
vscode-debugger/src/ravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(${RAVI_DEBUGGER_TARGET} libravinojit_static)
# Tests for VSCode Debug Adapter
add_executable(testravidebug
vscode-debugger/src/testravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(testravidebug libravinojit_static)
add_test(TestRaviDebug testravidebug)
add_executable(test_vm tests/test_vm.c)
target_link_libraries(test_vm ${LIBRAVI_NAME})
add_test(TestVM test_vm)
else()
# Simple VM tests
add_executable(test_asmvm tests/test_asmvm.c)
target_link_libraries(test_asmvm ${LIBRAVI_NAME})
add_test(TestRaviDebug testravidebug)
if (LLVM_JIT)
add_test(TestLLVM test_llvm)
endif ()
add_test(TestVM test_vm)
add_test(TestMisc test_misc)
add_test(TestVM test_asmvm)
endif()
install(FILES ${LUA_HEADERS}
DESTINATION include/ravi)
install(TARGETS ${LIBRAVI_NAME} ravi ${RAVI_DEBUGGER_TARGET} ravi_s
install(TARGETS ${LIBRAVI_NAME} ravi ${RAVI_DEBUGGER_TARGET} ${RAVI_STATICEXEC_TARGET}
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)

@ -1,4 +1,4 @@
mkdir nojit64
cd nojit64
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Debug -DSTATIC_BUILD=OFF -G "Visual Studio 15 2017 Win64" ..
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Release -DSTATIC_BUILD=OFF -G "Visual Studio 15 2017 Win64" ..
cd ..

@ -579,7 +579,9 @@ static void stackerror (lua_State *L) {
}
#ifdef RAVI_USE_ASMVM
/* following is a temporary solution to decide whether we can use ASM VM */
/* following is a temporary solution to decide whether we can use ASM VM.
The symbol ravi_luaV_interp() is generated by the VMBuilder component.
*/
extern int ravi_luaV_interp(lua_State * L);
int asvm_compatible(Proto *p) {
static unsigned char opcodes_supported[NUM_OPCODES] = {

@ -0,0 +1,173 @@
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <inttypes.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lobject.h"
#ifndef RAVI_USE_ASMVM
#error This file can only be compiled with ASMVM
#endif
struct MyValue {
int type;
union {
lua_Integer i;
lua_Number n;
const char *s;
} u;
};
/**
* Compiles the given code and invokes it, passing params to it.
* Checks that the code returns given number of values that match expected
* results. Returns 0 if no error.
*/
static int do_asmvm_test(
const char *code, /* code to compiled and invoked */
int nparams, struct MyValue *params, /* parameters */
int nresults, struct MyValue *expected) /* expected return values */
{
int rc = 0;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L); /* open standard libraries */
if (luaL_loadbuffer(L, code, strlen(code), "chunk") != 0) {
rc = 1;
fprintf(stderr, "Failed to load chunk: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
goto Lerror;
}
if (lua_pcall(L, 0, 1, 0) != 0) {
rc = 1;
fprintf(stderr, "Failed to run chunk: %s\n", lua_tostring(L, -1));
goto Lerror;
}
if (!lua_isfunction(L, -1)) {
rc = 1;
fprintf(stderr, "Script did not return a function\n");
goto Lerror;
}
for (int i = 0; i < nparams; i++) {
switch (params[i].type) {
case RAVI_TNUMINT:
lua_pushinteger(L, params[i].u.i);
break;
case RAVI_TNUMFLT:
lua_pushnumber(L, params[i].u.n);
break;
case RAVI_TSTRING:
lua_pushstring(L, params[i].u.s);
break;
default:
fprintf(stderr, "Unsupported argument type %d\n", params[i].type);
rc = 1;
goto Lerror;
}
}
if (lua_pcall(L, nparams, nresults, 0) != 0) {
rc = 1;
fprintf(stderr, "Test function failed: %s\n", lua_tostring(L, -1));
goto Lerror;
}
for (int i = nresults - 1, j = -1; i >= 0; i--, j--) {
switch (expected[i].type) {
case RAVI_TNUMINT: {
if (!lua_isinteger(L, j)) {
fprintf(stderr, "Result %d was expected to be integer\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Integer num = lua_tointeger(L, j);
if (num != expected[i].u.i) {
fprintf(stderr, "Result %d was expected to be %d, but got %d\n", i + 1, (int)expected[i].u.i, (int)num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TNUMFLT: {
if (!lua_isnumber(L, j)) {
fprintf(stderr, "Result %d was expected to be number\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Number num = lua_tonumber(L, j);
if (num != expected[i].u.n) {
fprintf(stderr, "Result %d was expected to be %g, but got %g\n", i + 1, expected[i].u.n, num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TSTRING: {
if (!lua_isstring(L, j)) {
fprintf(stderr, "Result %d was expected to be string\n", i + 1);
rc = 1;
goto Lerror;
}
const char *s = lua_tostring(L, j);
if (strcmp(s, expected[i].u.s) != 0) {
fprintf(stderr, "Result %d was expected to be %s, but got %s\n", i + 1, expected[i].u.s, s);
rc = 1;
goto Lerror;
}
break;
}
default: {
fprintf(stderr, "Result %d has unexpected type\n", i + 1);
rc = 1;
goto Lerror;
}
}
}
Lerror:
lua_close(L);
return rc;
}
static int test_vm()
{
int failures = 0;
struct MyValue args[3];
struct MyValue results[3];
args[0].type = RAVI_TNUMINT; args[0].u.i = 42;
args[1].type = RAVI_TNUMFLT; args[1].u.n = -4.2;
args[2].type = RAVI_TSTRING; args[2].u.s = "hello";
results[0].type = RAVI_TNUMINT; results[0].u.i = 42;
results[1].type = RAVI_TNUMFLT; results[1].u.n = -4.2;
results[2].type = RAVI_TSTRING; results[2].u.s = "hello";
failures = do_asmvm_test("return function() end", 0, NULL, 0, NULL); // OP_RETURN
failures += do_asmvm_test("return function() return 42 end", 0, NULL, 1, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2 end", 0, NULL, 2, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2, 'hello' end", 0, NULL, 3, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function(a) local b = a; return b end", 1, args, 1, results); // OP_MOVE, OP_RETURN
failures += do_asmvm_test("return function(a,c) local b,d = a,c; return b,d end", 2, args, 2, results); // OP_MOVE, OP_RETURN
results[0].u.i = 5;
failures += do_asmvm_test("return function (a) for i=1,5 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_I1, OP_RAVI_FORLOOP_I1
results[0].u.i = 3;
failures += do_asmvm_test("return function (a) for i=1,4,2 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_IP, OP_RAVI_FORLOOP_IP
return failures;
}
int main()
{
int failures = 0;
failures += test_vm();
if (failures)
printf("FAILED\n");
else
printf("OK\n");
return failures ? 1 : 0;
}

@ -12,8 +12,6 @@
#include "lualib.h"
#include "lobject.h"
#ifndef RAVI_USE_ASMVM
/* test supplied lua code compiles */
static int test_luacomp1(const char *code)
{
@ -31,62 +29,6 @@ static int test_luacomp1(const char *code)
return rc;
}
#if 0
static int test_luacompfile(const char *code)
{
int rc = 0;
lua_State *L;
L = luaL_newstate();
if (luaL_loadfile(L, code) != 0) {
rc = 1;
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
}
else
ravi_dump_function(L);
lua_close(L);
return rc;
}
/* test supplied lua code compiles */
static int test_luafileexec1(const char *code, int expected)
{
int rc = 0;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L); /* open standard libraries */
if (luaL_loadfile(L, code) != 0) {
rc = 1;
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
}
else {
ravi_dump_function(L);
time_t start = time(NULL);
if (lua_pcall(L, 0, 1, 0) != 0) {
rc = 1;
fprintf(stderr, "%s\n", lua_tostring(L, -1));
}
else {
time_t end = time(NULL);
ravi_dump_stack(L, "after executing function");
printf("time taken = %f\n", difftime(end, start));
lua_Integer got = 0;
if (lua_isboolean(L, -1))
got = lua_toboolean(L, -1) ? 1 : 0;
else
got = lua_tointeger(L, -1);
if (got != expected) {
rc = 1;
}
}
}
lua_close(L);
return rc;
}
#endif
/* test supplied lua code compiles */
static int test_luacompexec1(const char *code, int expected)
{
@ -124,152 +66,10 @@ static int test_luacompexec1(const char *code, int expected)
return rc;
}
#else
struct MyValue {
int type;
union {
lua_Integer i;
lua_Number n;
const char *s;
} u;
};
static int do_asmvm_test(const char *code, int nparams, struct MyValue *params, int nresults, struct MyValue *expected)
{
int rc = 0;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L); /* open standard libraries */
if (luaL_loadbuffer(L, code, strlen(code), "chunk") != 0) {
rc = 1;
fprintf(stderr, "Failed to load chunk: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
goto Lerror;
}
if (lua_pcall(L, 0, 1, 0) != 0) {
rc = 1;
fprintf(stderr, "Failed to run chunk: %s\n", lua_tostring(L, -1));
goto Lerror;
}
if (!lua_isfunction(L, -1)) {
rc = 1;
fprintf(stderr, "Script did not return a function\n");
goto Lerror;
}
for (int i = 0; i < nparams; i++) {
switch (params[i].type) {
case RAVI_TNUMINT:
lua_pushinteger(L, params[i].u.i);
break;
case RAVI_TNUMFLT:
lua_pushnumber(L, params[i].u.n);
break;
case RAVI_TSTRING:
lua_pushstring(L, params[i].u.s);
break;
default:
fprintf(stderr, "Unsupported argument type %d\n", params[i].type);
rc = 1;
goto Lerror;
}
}
if (lua_pcall(L, nparams, nresults, 0) != 0) {
rc = 1;
fprintf(stderr, "Test function failed: %s\n", lua_tostring(L, -1));
goto Lerror;
}
for (int i = nresults - 1, j = -1; i >= 0; i--, j--) {
switch (expected[i].type) {
case RAVI_TNUMINT: {
if (!lua_isinteger(L, j)) {
fprintf(stderr, "Result %d was expected to be integer\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Integer num = lua_tointeger(L, j);
if (num != expected[i].u.i) {
fprintf(stderr, "Result %d was expected to be %d, but got %d\n", i + 1, (int)expected[i].u.i, (int)num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TNUMFLT: {
if (!lua_isnumber(L, j)) {
fprintf(stderr, "Result %d was expected to be number\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Number num = lua_tonumber(L, j);
if (num != expected[i].u.n) {
fprintf(stderr, "Result %d was expected to be %g, but got %g\n", i + 1, expected[i].u.n, num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TSTRING: {
if (!lua_isstring(L, j)) {
fprintf(stderr, "Result %d was expected to be string\n", i + 1);
rc = 1;
goto Lerror;
}
const char *s = lua_tostring(L, j);
if (strcmp(s, expected[i].u.s) != 0) {
fprintf(stderr, "Result %d was expected to be %s, but got %s\n", i + 1, expected[i].u.s, s);
rc = 1;
goto Lerror;
}
break;
}
default: {
fprintf(stderr, "Result %d has unexpected type\n", i + 1);
rc = 1;
goto Lerror;
}
}
}
Lerror:
lua_close(L);
return rc;
}
static int test_vm()
{
int failures = 0;
struct MyValue args[3];
struct MyValue results[3];
args[0].type = RAVI_TNUMINT; args[0].u.i = 42;
args[1].type = RAVI_TNUMFLT; args[1].u.n = -4.2;
args[2].type = RAVI_TSTRING; args[2].u.s = "hello";
results[0].type = RAVI_TNUMINT; results[0].u.i = 42;
results[1].type = RAVI_TNUMFLT; results[1].u.n = -4.2;
results[2].type = RAVI_TSTRING; results[2].u.s = "hello";
failures = do_asmvm_test("return function() end", 0, NULL, 0, NULL); // OP_RETURN
failures += do_asmvm_test("return function() return 42 end", 0, NULL, 1, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2 end", 0, NULL, 2, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2, 'hello' end", 0, NULL, 3, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function(a) local b = a; return b end", 1, args, 1, results); // OP_MOVE, OP_RETURN
failures += do_asmvm_test("return function(a,c) local b,d = a,c; return b,d end", 2, args, 2, results); // OP_MOVE, OP_RETURN
results[0].u.i = 5;
failures += do_asmvm_test("return function (a) for i=1,5 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_I1, OP_RAVI_FORLOOP_I1
results[0].u.i = 3;
failures += do_asmvm_test("return function (a) for i=1,4,2 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_IP, OP_RAVI_FORLOOP_IP
return failures;
}
#endif
#ifndef RAVI_USE_ASMVM
static int test_vm()
{
int failures = 0;
//
failures += test_luacomp1("function x() local t : table = {}; t.name = 'd'; end");
failures += test_luacompexec1("function test(); local x: integer = 1; return function (j) x = j; return x; end; end; fn = test(); return fn('55')", 55);
failures += test_luacompexec1("ravi.auto(true); function arrayaccess (); local x: integer[] = {5}; return x[1]; end; assert(ravi.compile(arrayaccess)); return arrayaccess()", 5);
@ -339,8 +139,6 @@ static int test_vm()
return failures;
}
#endif
int main()
{
int failures = 0;

@ -287,12 +287,11 @@ And the epilogue::
As you can see the unwind information basically tells Windows what the epilogue is supposed to be, and where to find the saved
values of the registers.
Building Ravi With New VM
-------------------------
Building Ravi With New ASM VM
-----------------------------
This is only for the brave who want to hack with the code.
To enable the new VM first build and install VMBuilder as described above.
Then build Ravi using the cmake flags ``-DSTATIC_BUILD=ON`` and ``-DASM_VM=ON`` enabled. Don't enable JIT.
Right now the ASM VM is exercised via the ``test_vm`` sub project. The ASM VM is only invoked in special cases, i.e. a function has small number of instructions and only contains supported instructions, and additionally as OP_CALL is not yet implemented, you can only call the new VM via the Lua C api (see test_asmvm() in test_vm.c).
Right now the ASM VM is exercised via the ``test_vm`` sub project. The ASM VM is only invoked in special cases, i.e. a function has small number of instructions and only contains supported instructions, and additionally as OP_CALL is not yet implemented, you can only call the new VM via the Lua C api (see `test_asmvm() in test_vm.c <https://github.com/dibyendumajumdar/ravi/blob/master/tests/test_vm.c>`_).

Loading…
Cancel
Save