Created
November 28, 2016 10:25
-
-
Save Lupus/fc26862b8eefe641d678c88aa87f77ad to your computer and use it in GitHub Desktop.
Second repro with shared library, problem appears only in jit mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local S = require("std") | |
-- some helper declarations | |
local size_t = uint64 | |
local LUA_TSTRING = 4 | |
local struct lua_State | |
local lua_CFunction = {&lua_State} -> {int} | |
local struct luaL_Reg { | |
name: rawstring | |
func: lua_CFunction | |
} | |
local lua_pushstring = terralib.externfunction("lua_pushstring", | |
{&lua_State, rawstring} -> {}) | |
local lua_error = terralib.externfunction("lua_error", | |
{&lua_State} -> {int}) | |
local lua_type = terralib.externfunction("lua_type", | |
{&lua_State, int} -> {int}) | |
local lua_tolstring = terralib.externfunction("lua_tolstring", | |
{&lua_State, int, &size_t} -> {rawstring}) | |
local luaL_checkstack = terralib.externfunction("luaL_checkstack", | |
{&lua_State, int, rawstring} -> {}) | |
local lua_pushvalue = terralib.externfunction("lua_pushvalue", | |
{&lua_State, int} -> {}) | |
local lua_pushcclosure = terralib.externfunction("lua_pushcclosure", | |
{&lua_State, lua_CFunction, int} -> {}) | |
local lua_setfield = terralib.externfunction("lua_setfield", | |
{&lua_State, int, rawstring} -> {}) | |
local lua_createtable = terralib.externfunction("lua_createtable", | |
{&lua_State, int, int} -> {}) | |
local lua_settop = terralib.externfunction("lua_settop", | |
{&lua_State, int} -> {}) | |
terra lua_tostring(L : &lua_State, n : int) | |
return lua_tolstring(L, n, nil) | |
end | |
terra lua_pop(L : &lua_State, n : int) | |
lua_settop(L,-(n)-1) | |
end | |
terra lua_newtable(L : &lua_State) | |
lua_createtable(L, 0, 0) | |
end | |
terra luaL_setfuncs(L: &lua_State, reg: &luaL_Reg, nup: int) | |
var i: int | |
luaL_checkstack(L, nup, "too many upvalues") | |
while reg.name ~= nil do -- fill the table with given functions | |
for i = 0,nup do -- copy upvalues to the top | |
lua_pushvalue(L, -nup) | |
end | |
lua_pushcclosure(L, reg.func, nup) -- closure with those | |
-- upvalues | |
lua_setfield(L, -(nup + 2), reg.name) | |
reg = reg + 1 | |
end | |
lua_pop(L, nup) -- remove upvalues | |
end | |
-- end of helper declarations | |
function fn_setinlined(fn, v) | |
if type(fn.definition) == "function" then | |
fn:setinlined(v) | |
return | |
end | |
fn.definition.alwaysinline = not not v | |
end | |
-- test case 1 --- struct larger than pointer size | |
local struct Bar { | |
a: int64 | |
b: int64 | |
} | |
-- non inlined function | |
local terra bar_fn_1(L: &lua_State) : {rawstring, Bar} | |
return "", Bar { 0, 0 } | |
end | |
fn_setinlined(bar_fn_1, false) -- if we force inlining, it will work | |
-- same function, but force inlined | |
local terra bar_fn_2(L: &lua_State) : {rawstring, Bar} | |
return "", Bar { 0, 0 } | |
end | |
fn_setinlined(bar_fn_2, true) | |
-- test case 2 --- struct same as pointer size | |
local struct Bar2 { -- same size as rax | |
a: int64 | |
} | |
local terra bar_fn_3(L: &lua_State) : {rawstring, Bar2} | |
return "", Bar2 { 0 } | |
end | |
fn_setinlined(bar_fn_3, false) | |
local terra bar_fn_4(L: &lua_State) : {rawstring, Bar2} | |
return "", Bar2 { 0 } | |
end | |
fn_setinlined(bar_fn_4, true) | |
-- A set of wrappers, each calls bar_fn_X respectively, copy-pasted for clalrity | |
local terra wrapper1(L : &lua_State) : int | |
var result, e = bar_fn_1(L) | |
if e.a ~= 0 then S.printf("Here!\n") end | |
lua_pushstring(L, "error message") | |
return lua_error(L) | |
end | |
local terra wrapper2(L : &lua_State) : int | |
var result, e = bar_fn_2(L) | |
if e.a ~= 0 then S.printf("Here!\n") end | |
lua_pushstring(L, "error message") | |
return lua_error(L) | |
end | |
local terra wrapper3(L : &lua_State) : int | |
var result, e = bar_fn_3(L) | |
if e.a ~= 0 then S.printf("Here!\n") end | |
lua_pushstring(L, "error message") | |
return lua_error(L) | |
end | |
local terra wrapper4(L : &lua_State) : int | |
var result, e = bar_fn_4(L) | |
if e.a ~= 0 then S.printf("Here!\n") end | |
lua_pushstring(L, "error message") | |
return lua_error(L) | |
end | |
local terra luaopen_sample(L : &lua_State) | |
var reg = arrayof(luaL_Reg, | |
luaL_Reg { "wrapper1", wrapper1 }, | |
luaL_Reg { "wrapper2", wrapper2 }, | |
luaL_Reg { "wrapper3", wrapper3 }, | |
luaL_Reg { "wrapper4", wrapper4 }, | |
luaL_Reg { nil, nil } | |
) | |
lua_newtable(L) | |
luaL_setfuncs(L, reg, 0) | |
return 1 | |
end | |
os.execute("mkdir -p sample_dir") | |
terralib.saveobj("sample_dir/sample.o", "object", { | |
luaopen_sample_dir_sample = luaopen_sample | |
}, {}) | |
print("linking shared library...") | |
os.execute("ld -shared sample_dir/sample.o -o sample_dir/sample.so -llua5.1") | |
print("done!") | |
local sample = require("sample_dir.sample") | |
print("running wrapper4 via shared library...") | |
local _, msg = pcall(sample.wrapper4) | |
print(msg) | |
print() | |
print("running wrapper3 via shared library...") | |
local _, msg = pcall(sample.wrapper3) | |
print(msg) | |
print() | |
print("running wrapper2 via shared library...") | |
local _, msg = pcall(sample.wrapper2) | |
print(msg) | |
print() | |
print("running wrapper1 via shared library...") | |
local _, msg = pcall(sample.wrapper1) | |
print(msg) | |
print() | |
print("running bound_fn4 via jit...") | |
local bound_fn4 = terralib.bindtoluaapi(wrapper4:getpointer()) | |
local _, msg = pcall(bound_fn4) | |
print(msg) | |
print() | |
print("running bound_fn3 via jit...") | |
local bound_fn3 = terralib.bindtoluaapi(wrapper3:getpointer()) | |
local _, msg = pcall(bound_fn3) | |
print(msg) | |
print() | |
print("running bound_fn2 via jit...") | |
local bound_fn2 = terralib.bindtoluaapi(wrapper2:getpointer()) | |
local _, msg = pcall(bound_fn2) | |
print(msg) | |
print() | |
-- wrapper 1 gives unexpected result, while wrappers 2,3,4 work as expected | |
print("running bound_fn1 via jit...") | |
local bound_fn1 = terralib.bindtoluaapi(wrapper1:getpointer()) | |
local _, msg = pcall(bound_fn1) | |
print(msg) | |
print() | |
print("exiting normally") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment