Skip to content

Instantly share code, notes, and snippets.

@Lupus
Created November 24, 2016 16:19
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/2054268676a193688bef3f8d77c2251e to your computer and use it in GitHub Desktop.
Save Lupus/2054268676a193688bef3f8d77c2251e to your computer and use it in GitHub Desktop.
Terra return by value reproducible test case
local S = require("std")
-- some helper declarations
local size_t = uint64
local LUA_TSTRING = 4
local struct lua_State
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})
terra lua_tostring(L : &lua_State, n : int)
return lua_tolstring(L, n, nil)
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
wrapper1:compile()
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
wrapper2:compile()
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
wrapper3:compile()
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
wrapper4:compile()
bar_fn_1:disas()
wrapper1:disas()
-- wrapper 1 gives unexpected result, while wrappers 2,3,4 work as expected
local bound_fn = terralib.bindtoluaapi(wrapper1:getpointer())
bound_fn()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment