Created
November 24, 2016 16:19
-
-
Save Lupus/2054268676a193688bef3f8d77c2251e to your computer and use it in GitHub Desktop.
Terra return by value reproducible test case
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_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