Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Lupus
Created November 28, 2016 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lupus/fc26862b8eefe641d678c88aa87f77ad to your computer and use it in GitHub Desktop.
Save Lupus/fc26862b8eefe641d678c88aa87f77ad to your computer and use it in GitHub Desktop.
Second repro with shared library, problem appears only in jit mode
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