You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Raised by gale on #929 while verifying the v0.56.0 fix, and reproduced here on
v0.56.0. Filing separately as they offered, because it is a different defect from #929 and outlives it.
$ synth compile ctrl.wat -b arm -t cortex-m3 --all-exports --relocatable -o ctrl.o
warning: skipping function 'f': ... #929: call arg 1 is 64-bit ... Declining rather
than emitting a silent miscompile
warning: 1 of 2 functions were skipped (not in output): f
$ echo $?
0
$ llvm-objdump -t ctrl.o | grep 'F .text'
00000000 l F .text 00000004 func_0 # $g only — the EXPORT 'f' is absent
Exit 0. Object written. The requested export is not in it.
Why this matters more than it used to
The decline itself is right and its wording is good — it names the mechanism, not
a generic "unsupported". The problem is where the honesty stops.
A build that gates on $? — which is every build — accepts this object and ships
it. The absence surfaces only in the symbol table, or downstream as a link
failure, or at run time as a missing entry point. So a LOUD decline at the
compiler becomes a SILENT one at the build-system boundary, which is the exact
class v0.56.0 spent its whole scope closing (#911, #924, #928, #945: gates that
report something other than what they check).
It also got sharper in v0.56.0 rather than milder. Declining is now the DESIGNED
outcome for a whole class of ordinary signatures — every call passing a 64-bit
value in a register, including fn(ptr, u64) — and #931 added another
(br whose carried-value count cannot be trusted across frames). As the decline
frontier grows deliberately, the cost of it being invisible to $? grows with it.
Suggested shape (gale's, and I agree)
A nonzero exit when a REQUESTED export is skipped, with an opt-in --allow-skipped-exports for callers who genuinely want partial objects (the --all-exports sweep over a corpus, where skipping is expected and counted).
Note the asymmetry worth preserving: skipping a non-exported helper is routine;
dropping a function the user explicitly asked to export is not. The exit code
should distinguish those, which the current warning already does textually
(1 of 2 functions were skipped (not in output): f) — the information exists,
it just does not reach the caller.
gale also corrected their own [CRITICAL] thumb-2 silently miscompiles any call with an i64 parameter that is not last — args land in the wrong registers, exit 0, no warning #929 report there: the (i32, i64) row they
listed as correct was an artifact of a callee that returned local.get 0,
the one operand the bug cannot disturb. (i32, i64) was broken too, and
v0.56.0 declining every 64-bit register argument — not only non-final ones — is
right. Narrowing the decline on the strength of that row would silently
reintroduce the bug for fn(ptr, u64). I re-ran it: (i32, i64) does decline
on 0.56.0.
Raised by gale on #929 while verifying the v0.56.0 fix, and reproduced here on
v0.56.0. Filing separately as they offered, because it is a different defect from
#929 and outlives it.
Measured (synth 0.56.0)
Exit 0. Object written. The requested export is not in it.
Why this matters more than it used to
The decline itself is right and its wording is good — it names the mechanism, not
a generic "unsupported". The problem is where the honesty stops.
A build that gates on
$?— which is every build — accepts this object and shipsit. The absence surfaces only in the symbol table, or downstream as a link
failure, or at run time as a missing entry point. So a LOUD decline at the
compiler becomes a SILENT one at the build-system boundary, which is the exact
class v0.56.0 spent its whole scope closing (#911, #924, #928, #945: gates that
report something other than what they check).
It also got sharper in v0.56.0 rather than milder. Declining is now the DESIGNED
outcome for a whole class of ordinary signatures — every call passing a 64-bit
value in a register, including
fn(ptr, u64)— and #931 added another(
brwhose carried-value count cannot be trusted across frames). As the declinefrontier grows deliberately, the cost of it being invisible to
$?grows with it.Suggested shape (gale's, and I agree)
A nonzero exit when a REQUESTED export is skipped, with an opt-in
--allow-skipped-exportsfor callers who genuinely want partial objects (the--all-exportssweep over a corpus, where skipping is expected and counted).Note the asymmetry worth preserving: skipping a non-exported helper is routine;
dropping a function the user explicitly asked to export is not. The exit code
should distinguish those, which the current warning already does textually
(
1 of 2 functions were skipped (not in output): f) — the information exists,it just does not reach the caller.
Related
(i32, i64)row theylisted as correct was an artifact of a callee that returned
local.get 0,the one operand the bug cannot disturb.
(i32, i64)was broken too, andv0.56.0 declining every 64-bit register argument — not only non-final ones — is
right. Narrowing the decline on the strength of that row would silently
reintroduce the bug for
fn(ptr, u64). I re-ran it:(i32, i64)does declineon 0.56.0.