Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adaptation of pallene-tracer directly in Pallene #614

Merged
merged 11 commits into from
Aug 8, 2024
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ jobs:
make
sudo make install

- name: Install Pallene Tracer
run: |
git clone https://github.com/pallene-lang/pallene-tracer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should create version tags in that repo, and import a particular version. Otherwise, Pallene builds might break if there new commits over there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do that when Pallene Tracer is stabilized.

cd pallene-tracer
sudo make install
luarocks --local make

- name: Build
run: luarocks --local make

Expand All @@ -87,3 +94,4 @@ jobs:
run: |
eval "$(luarocks path)"
busted -o gtest -v ./spec

6 changes: 6 additions & 0 deletions pallene-dev-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ dependencies = {
"lua == 5.4",
"lpeg >= 1.0",
"argparse >= 0.7.0",
"pallene-tracer >= 0.5.0a"
}
external_dependencies = {
PTRACER = {
header = "ptracer.h",
}
}
build = {
type = "builtin",
Expand Down
2 changes: 1 addition & 1 deletion run-tests
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ FLAGS=(--verbose --no-keep-going)

# To speed things up, we tell the C compiler to skip optimizations. (It's OK, the CI still uses -O2)
# Also, add some compiler flags to verify standard compliance.
export CFLAGS='-O0 -std=c99 -Wall -Werror -Wundef -Wpedantic -Wno-unused'
export CFLAGS='-O0 -std=c99 -Wall -Werror -Wundef -Wno-unused'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure we want to get rid of -Wpedantic? If I remember correctly, it's not just for C89. In this case it would know about c99 and warn about things that are not c99.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a long and complicated history behind it that I have been researching thyself for a while.

Generally, for some time being ISO was in charge of publishing C standards (Like C89, C90, C95 and C99). People easily mistakes ISO standards as pure C standards (they are not wrong tho). But there is a catch. When it is said ISO C, it literally means C89 standard initially developed by ISO. It's because C89 is said to be the most complete C standard ever developed and other C standards are just inherited C89 with some extra features minus some strictness. The C89 standard is also said to be ANSI C by historical mistake (don't quote me on that).

According to GCC manual, -Wpedantic will generate warnings as if you are using C89. So, using it beside C99 actually doesn't make all that sense instead of using -std=c89 or -pedantic or -ansi flags to fully adopt C89. But with that being said as all the standards are sorta inheritance of C89, there are some flags we can use to take advantage of some features of C89 aka ISO C. One of the flags that I came across recently while patching DWL (DWM for Wayland) is -Wdeclaration-after-statement which uses the ISO C suggestion for keeping all the local variable declaration at the top.

For the record, using gcc:

  • Without any -std defaults to latest GNU C standard equivalent of -std=gnu**.
  • With -std=c** to use any pure C standard.
  • With -pedantic or -ansi to use ISO C89, which is less robust way to define -std=c89.
  • With -Wpedantic to generate warnings as if we are using ISO C89 even tho we may have some standard defined. Using -Wpedantic with -Werror is lesser of a robust way of using -std=c89.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the GCC manual:

-std=

Determine the language standard. This option is currently only supported when compiling C or C++.
The compiler can accept several base standards, such as c90 or c++98, and GNU dialects of those
standards, such as gnu90 or gnu++98. When a base standard is specified, the compiler accepts all
programs following that standard plus those using GNU extensions that do not contradict it. For
example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the
"asm" and "typeof" keywords, but not other GNU extensions that do not have a meaning in ISO C90, such
as omitting the middle term of a "?:" expression. On the other hand, when a GNU dialect of a standard
is specified, all features supported by the compiler are enabled, even when those features change the
meaning of the base standard. As a result, some strict-conforming programs may be rejected. The
particular standard is used by -Wpedantic to identify which features are GNU extensions given that
version of the standard. For example -std=gnu90 -Wpedantic warns about C++ style // comments, while
-std=gnu99 -Wpedantic does not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From Wikipedia:

ANSI C, ISO C, and Standard C are successive standards for the C programming language published by the American National Standards Institute (ANSI) and ISO/IEC JTC 1/SC 22/WG 14 of the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC). Historically, the names referred specifically to the original and best-supported version of the standard (known as C89 or C90). Software developers writing in C are encouraged to conform to the standards, as doing so helps portability between compilers.

This is from GCC flags manual:

-Wpedantic
-pedantic
Issue all the warnings demanded by strict ISO C and ISO C++; diagnose all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. This follows the version of the ISO C or C++ standard specified by any -std option used.

Actually to be honest I am confused right now. From my experience, while using -Wpedantic with -std=c11 I was getting warnings which was of C89 standard as far as I can remember.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am bringing back -Wpedantic flag.

Here is where I was wrong: ISO C used to be historically and strictly referred to C89. But now it is not. ISO C standard in this case is the standard you specify using -std=.


if [ "$#" -eq 0 ]; then
if command -v parallel >/dev/null; then
Expand Down
3 changes: 3 additions & 0 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 @@ -61,6 +62,8 @@ function c_compiler.compile_o_to_so(in_filename, out_filename)
CFLAGS_SHARED,
"-o", util.shell_quote(out_filename),
util.shell_quote(in_filename),
"-lptracer",
"-Wl,-rpath="..PTLIBDIR,
})
end

Expand Down
79 changes: 28 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("$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($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 @@ -1490,11 +1469,8 @@ gen_cmd["CallStatic"] = function(self, args)
end

table.insert(parts, self:update_stack_top(args.position))

if self.flags.use_traceback then
table.insert(parts, string.format("PALLENE_SETLINE(%d);\n",
args.func.loc and args.func.loc.line or 0))
end
table.insert(parts, string.format("PALLENE_SETLINE(%d);\n",
args.func.loc and args.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 @@ -1531,12 +1507,9 @@ gen_cmd["CallDyn"] = function(self, args)
}))
end

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

return util.render([[
${update_stack_top}
Expand Down Expand Up @@ -1808,6 +1781,10 @@ function Coder:generate_module_header()
table.insert(out, "/* This file was generated by the Pallene compiler. Do not edit by hand */")
table.insert(out, "")
table.insert(out, string.format("#define PALLENE_SOURCE_FILE %s", C.string(self.filename)))
if self.flags.use_traceback then
table.insert(out, "/* Enable Pallene Tracer debugging. */")
table.insert(out, "#define PT_DEBUG")
end
table.insert(out, "")

table.insert(out, "/* ------------------------ */")
Expand Down
2 changes: 1 addition & 1 deletion src/pallene/pallenec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ do
)

-- No Pallene tracebacks
p:flag("--use-traceback", "Use function traceback for debugging")
p:flag("--use-traceback", "Enable call-stack tracing")

p:option("-O", "Optimization level")
:args(1):convert(tonumber)
Expand Down
Loading
Loading