Skip to content

Commit

Permalink
Pallene Tracer API usage improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
singul4ri7y committed Aug 4, 2024
1 parent 906f8b3 commit ec66bf2
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 84 deletions.
16 changes: 11 additions & 5 deletions src/pallene/c_compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ local c_compiler = {}

local CC = os.getenv("CC") or "cc"
local CFLAGS = os.getenv("CFLAGS") or "-O2"
local PTLIBDIR = os.getenv("PTLIBDIR") or "/usr/local/lib"

local function get_uname()
local ok, err, uname = util.outputs_of_execute("uname -s")
Expand Down Expand Up @@ -54,16 +55,21 @@ function c_compiler.compile_c_to_o(in_filename, out_filename)
})
end

function c_compiler.compile_o_to_so(in_filename, out_filename)
function c_compiler.compile_o_to_so(in_filename, out_filename, _, _, flags)
-- There is no need to add the '-x' flag when compiling an object file without a '.o' extension.
-- According to GCC, any file name with no recognized suffix is treated as an object file.
return run_cc({
local command = {
CFLAGS_SHARED,
"-o", util.shell_quote(out_filename),
util.shell_quote(in_filename),
"-lptracer",
"-Wl,-rpath=/usr/local/lib",
})
}

if flags.pt_dynamic or not flags.use_traceback then
table.insert(command, "-lptracer")
table.insert(command, "-Wl,-rpath="..PTLIBDIR)
end

return run_cc(command)
end

return c_compiler
81 changes: 30 additions & 51 deletions src/pallene/coder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,7 @@ end
-- these cases instead of invoking the metatable operations, which may impair program optimization
-- even if they are never called.
local function check_no_metatable(self, src, loc)
local setline = ""
if self.flags.use_traceback then
setline = string.format("PALLENE_SETLINE(%d);", loc.line)
end
local setline = string.format("PALLENE_SETLINE(%d);", loc.line)

return (util.render([[
if ($src->metatable) {
Expand Down Expand Up @@ -254,10 +251,7 @@ function Coder:get_stack_slot(typ, dst, slot, loc, description_fmt, ...)
assert(not typ.is_upvalue_box)
local extra_args = table.pack(...)

local setline = ""
if self.flags.use_traceback then
setline = string.format("PALLENE_SETLINE(%d);", loc.line)
end
local setline = string.format("PALLENE_SETLINE(%d);", loc.line)

check_tag = util.render([[
if (l_unlikely(!$test)) {
Expand Down Expand Up @@ -461,18 +455,12 @@ function Coder:pallene_entry_point_definition(f_id)
local max_frame_size = self.gc[func].max_frame_size
local slots_needed = max_frame_size + self.max_lua_call_stack_usage[func]

local setline = ""
local frameexit = ""
if self.flags.use_traceback then
table.insert(prologue, util.render([[
PALLENE_C_FRAMEENTER(L, "$name");
]], {
name = func.name
}));

setline = string.format("PALLENE_SETLINE(%d);", func.loc and func.loc.line or 0)
frameexit = "PALLENE_FRAMEEXIT();"
end
table.insert(prologue, util.render([[
PALLENE_C_FRAMEENTER(L, "$name");
]], {
name = func.name
}));
local setline = string.format("PALLENE_SETLINE(%d);", func.loc and func.loc.line or 0)

if slots_needed > 0 then
table.insert(prologue, util.render([[
Expand Down Expand Up @@ -527,7 +515,7 @@ function Coder:pallene_entry_point_definition(f_id)
${prologue}
/**/
${body}
${frameexit}
PALLENE_FRAMEEXIT();
${ret_mult}
${ret_stat}
}
Expand All @@ -537,7 +525,6 @@ function Coder:pallene_entry_point_definition(f_id)
prologue = table.concat(prologue, "\n"),
body = body,
ret_mult = ret_mult,
frameexit = frameexit,
ret_stat = ret_stat,
}))
end
Expand Down Expand Up @@ -615,22 +602,18 @@ function Coder:lua_entry_point_definition(f_id)
Udata *K = uvalue(&func->upvalue[0]);
]]

local frameenter = ""
local frameexit = ""
local nargs = #arg_types
-- We will be having our call-stack finalizer object on top of our stack when debugging mode is
-- enabled
local cargs = nargs
if self.flags.use_traceback then
frameenter = util.render([[
PALLENE_LUA_FRAMEENTER(L, $fun_name);
]], {
fun_name = self:lua_entry_point_name(f_id),
})
-- It's as simple as popping the finalizer.
frameexit = "lua_pop(L, 1);"

-- We will be having our finalizer on top of our stack.
cargs = cargs + 1
end
local frameenter = util.render([[
PALLENE_LUA_FRAMEENTER(L, $fun_name);
]], {
fun_name = self:lua_entry_point_name(f_id),
})

local arity_check = util.render([[
int nargs = lua_gettop(L);
Expand Down Expand Up @@ -694,7 +677,6 @@ function Coder:lua_entry_point_definition(f_id)
/**/
${ret_decls}
${call_pallene}
${lua_fexit}
${push_results}
return $nresults;
}
Expand All @@ -708,7 +690,6 @@ function Coder:lua_entry_point_definition(f_id)
ret_decls = table.concat(ret_decls, "\n"),
call_pallene = call_pallene,
push_results = table.concat(push_results, "\n"),
lua_fexit = frameexit,
nresults = C.integer(#ret_types)
}))
end
Expand All @@ -728,11 +709,9 @@ define_union("Constant", {

function Coder:init_upvalues()

-- If we are using tracebacks
if self.flags.use_traceback then
table.insert(self.constants, coder.Constant.DebugUserdata())
table.insert(self.constants, coder.Constant.DebugMetatable())
end
-- Debug traceback constants
table.insert(self.constants, coder.Constant.DebugUserdata())
table.insert(self.constants, coder.Constant.DebugMetatable())

-- Metatables
for _, typ in ipairs(self.module.record_types) do
Expand Down Expand Up @@ -1488,11 +1467,8 @@ gen_cmd["CallStatic"] = function(self, cmd, func)
end

table.insert(parts, self:update_stack_top(func, cmd))

if self.flags.use_traceback then
table.insert(parts, string.format("PALLENE_SETLINE(%d);\n",
func.loc and func.loc.line or 0))
end
table.insert(parts, string.format("PALLENE_SETLINE(%d);\n",
func.loc and func.loc.line or 0))

table.insert(parts, self:call_pallene_function(dsts, f_id, cclosure, xs, nil))
table.insert(parts, self:restorestack())
Expand Down Expand Up @@ -1528,12 +1504,9 @@ gen_cmd["CallDyn"] = function(self, cmd, func)
}))
end

local setline = ""
if self.flags.use_traceback then
setline = util.render([[ PALLENE_SETLINE($line); ]], {
line = C.integer(func.loc and func.loc.line or 0)
})
end
local setline = util.render([[ PALLENE_SETLINE($line); ]], {
line = C.integer(func.loc and func.loc.line or 0)
})

return util.render([[
${update_stack_top}
Expand Down Expand Up @@ -1805,6 +1778,12 @@ function Coder:generate_module_header()
if self.flags.use_traceback then
table.insert(out, "/* Enable Pallene Tracer debugging. */")
table.insert(out, "#define PT_DEBUG")

if not self.flags.pt_dynamic then
table.insert(out, "/* Inlining for maximum performance during debugging. */")
table.insert(out, "#define PT_INLINE")
table.insert(out, "#define PT_IMPLEMENTATION")
end
end
table.insert(out, "")

Expand Down
6 changes: 4 additions & 2 deletions src/pallene/pallenec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ do
)

-- No Pallene tracebacks
p:flag("--use-traceback", "Use function traceback for debugging")
p:flag("--use-traceback", "Use function traceback for debugging using Pallene Tracer")
p:flag("--pt-dynamic", "Use dynamic linking to Pallene Tracer. Reduced code redundancy, compromised performance")

p:option("-O", "Optimization level")
:args(1):convert(tonumber)
Expand Down Expand Up @@ -73,7 +74,8 @@ end

function pallenec.main()
local flags = {
use_traceback = opts.use_traceback and true or false
use_traceback = opts.use_traceback and true or false,
pt_dynamic = opts.pt_dynamic and true or false
}

if opts.emit_c then compile("pln", "c", flags)
Expand Down
62 changes: 36 additions & 26 deletions src/pallene/pallenelib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,33 +46,49 @@ return [==[
#include <stdbool.h>
#include <stdlib.h>
/* Pallene Tracer for tracebacks (dynamically linked). */
/* Pallene Tracer for function call tracebacks. */
/* Look at `https://github.com/pallene-lang/pallene-tracer` for more info. */
#include <ptracer.h>
#define PALLENE_UNREACHABLE __builtin_unreachable()
/* PALLENE TRACER MACROS */
/* PALLENE TRACER HELPER MACROS */
#ifdef PT_DEBUG
/* Prepares finalizer function for Lua interface calls. */
#define PALLENE_PREPARE_FINALIZER() \
setobj(L, s2v(L->top.p++), &K->uv[1].uv); \
lua_toclose(L, -1)
#define PALLENE_C_FRAMEENTER(L, name) \
pt_fnstack_t *fnstack = pvalue(&K->uv[0].uv); \
static pt_fn_details_t _details = \
PALLENE_TRACER_FN_DETAILS(name, PALLENE_SOURCE_FILE); \
pt_frame_t _frame = \
PALLENE_TRACER_C_FRAME(_details); \
PALLENE_TRACER_FRAMEENTER(L, fnstack, &_frame);
#define PALLENE_LUA_FRAMEENTER(L, fnptr) \
pt_fnstack_t *fnstack = pvalue(&K->uv[0].uv); \
pt_frame_t _frame = \
PALLENE_TRACER_LUA_FRAME(fnptr); \
PALLENE_TRACER_FRAMEENTER(L, fnstack, &_frame); \
PALLENE_PREPARE_FINALIZER()
#define PALLENE_PREPARE_FINALIZER() \
setobj(L, s2v(L->top.p++), &K->uv[1].uv); \
lua_toclose(L, -1)
#define PALLENE_GET_FNSTACK() \
pt_fnstack_t *fnstack = pvalue(&K->uv[0].uv)
#define PALLENE_PREPARE_C_FRAME(name) \
PALLENE_GET_FNSTACK(); \
static pt_fn_details_t _details = \
PALLENE_TRACER_FN_DETAILS(name, PALLENE_SOURCE_FILE); \
pt_frame_t _frame = \
PALLENE_TRACER_C_FRAME(_details)
#define PALLENE_PREPARE_LUA_FRAME(fnptr) \
PALLENE_GET_FNSTACK(); \
pt_frame_t _frame = \
PALLENE_TRACER_LUA_FRAME(fnptr)
#else
#define PALLENE_PREPARE_FINALIZER()
#define PALLENE_PREPARE_C_FRAME(name)
#define PALLENE_PREPARE_LUA_FRAME(fnptr)
#endif // PT_DEBUG
#define PALLENE_C_FRAMEENTER(L, name) \
PALLENE_PREPARE_C_FRAME(name); \
PALLENE_TRACER_FRAMEENTER(L, fnstack, &_frame);
#define PALLENE_LUA_FRAMEENTER(L, fnptr) \
PALLENE_PREPARE_LUA_FRAME(fnptr); \
PALLENE_TRACER_FRAMEENTER(L, fnstack, &_frame); \
PALLENE_PREPARE_FINALIZER()
#define PALLENE_SETLINE(line) PALLENE_TRACER_SETLINE(fnstack, line)
#define PALLENE_FRAMEEXIT() PALLENE_TRACER_FRAMEEXIT(fnstack)
Expand All @@ -96,7 +112,6 @@ static l_noret pallene_runtime_mod_by_zero_error(lua_State *L, const char* file,
static l_noret pallene_runtime_number_to_integer_error(lua_State *L, const char* file, int line);
static l_noret pallene_runtime_array_metatable_error(lua_State *L, const char* file, int line);
static l_noret pallene_runtime_cant_grow_stack_error(lua_State *L);
static l_noret pallene_runtime_callstack_overflow_error(lua_State *L);
/* Arithmetic operators */
static lua_Integer pallene_int_divi(lua_State *L, lua_Integer m, lua_Integer n, const char* file, int line);
Expand Down Expand Up @@ -246,11 +261,6 @@ static l_noret pallene_runtime_cant_grow_stack_error(lua_State *L)
PALLENE_UNREACHABLE;
}
static l_noret pallene_runtime_callstack_overflow_error(lua_State *L) {
luaL_error(L, "pallene callstack overflow");
PALLENE_UNREACHABLE;
}
/* Lua and Pallene round integer division towards negative infinity, while C rounds towards zero.
* Here we inline luaV_div, to allow the C compiler to constant-propagate. For an explanation of the
* algorithm, see the comments for luaV_div. */
Expand Down

0 comments on commit ec66bf2

Please sign in to comment.