Skip to content

Claude/upgrade ape c library mm z gd - #620

Merged
staalmannen merged 4 commits into
mainfrom
claude/upgrade-ape-c-library-mmZGd
Oct 8, 2026
Merged

staalmannen merged 4 commits into
mainfrom
claude/upgrade-ape-c-library-mmZGd

Conversation

@staalmannen

Copy link
Copy Markdown
Owner

No description provided.

claude added 4 commits October 8, 2026 16:52
After the _main rename cpfe reaches its own command-line parser and
answers with its own diagnostics instead of faulting at pc=argc.  The
entry-point diagnosis is confirmed behaviourally.

Both messages in that run are cpfe working rather than refusing:
--help and -V are eccp DRIVER options, cpfe's own table in
src/cmd_line.c has no `help' entry at all and spells the other
--version, and -V reaching "missing source file name" means it was
accepted with only the operand absent.

--no_standard_includes is the driver's too, which matters for a
hand-written command: it is not in cpfe's table because the driver
implements it by not passing its default --sys_include list.  cpfe has
no standard include path of its own, so there is nothing to suppress.

The NOTE now carries the first-translation command.  The half that
matters is pcc -c on the generated C: cpfe emitting C says the front
end runs, pcc accepting it says kencc_targ.h describes this machine.
Use a toy with no `new' and no static constructors -- those are the
two places the runtime is reached and the static-init gap is open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
EDG ships no standard library and this directory contains none.
include_c++ holds eleven LANGUAGE-SUPPORT headers -- its own README
says "only those headers that require specific magic to work right
with the EDG front end" -- and a grep across all of them for
basic_string|vector|iostream|ostream is empty.  lib_src (51 files,
7191 lines) is the matching runtime: new/delete, vtables, RTTI, static
init, pure-virtual.  That is the libsupc++/libc++abi layer, not
libstdc++.

What works with no library at all is the subset EDG itself is written
in, which is why the self-translation worked.

The finding that decides the rest: EDG's exception handling here is
setjmp/longjmp with its own region bookkeeping -- __eh_curr_region
138 occurrences, an_eh_stack_entry 99, setjmp 19, longjmp 2, and zero
references to _Unwind_ anything across all 51 files.  So exceptions
need no libgcc, no libunwind, no .eh_frame and no personality routine,
which is the only model that could work on a target with none of
those; but libc++'s EH integration assumes the Itanium ABI, so the
libsupc++-shaped runtime is not the conforming ABI layer it looks
like.  Only the grep says so.

Not an obstacle, checked: the type-trait builtins a modern STL needs
are in cpfe's table.

And the axis that decides a candidate is the NAMESPACE rather than
maintenance status: APExp exists to build existing software with
minimal modification, and code written against std::vector does not
compile against etl:: or eastl:: however good those libraries are.  A
renamed STL serves new code; only a std:: one serves a port.

The NOTE carries the candidate survey (STLport, ETL, EASTL, uClibc++,
libstdc++), an honest ordering, and a provenance paragraph marking
which lines are measured in-tree and which are only recalled or came
from one web search -- the EASTL line in particular was NOT confirmed
and is flagged as unchecked.

Nothing is started and none of it blocks anything already working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
`check_target_config: must use SoftFloat library' is cpfe refusing its
own configuration, not a fault in the input.  target.c:10642 fires when
targ_ldbl_mant_dig == 64 -- an 80-bit long double it cannot constant-
fold without a SoftFloat library it was not built with.

cpfe is multi-target: target.c:6525 holds eight configurations,
fe_init.c:49180 defaults the index to 0, --target selects by name, and
entry 0 (labelled linux_x86_64) is set_legacy_target_config, built
from the unsuffixed TARG_* macros that kencc_targ.h overrides.
Measured from the generated C, that entry carries the host's values:
long 8, long double 16, mant_dig 64.

So kencc_targ.h did not reach the translation of target.c.  That is a
different macro environment from the one already measured: the
__weak__ suppression (38,245 -> 0) is a property of the cpfe build,
while the TARG_* widths are read when target.c is translated, and only
the second bakes into the committed C.  Which mechanism -- absent from
the translation command, or overridden by cmake_defines.h after it --
is not settled and is recorded as unsettled.

Both configurations are in the generated source, so their diff is a
complete list rather than a reading: 126 targ_* assignments each, 36
differ.  win64 is kencc's integer and float model exactly -- long 4,
long double 8/53, size_t/ssize_t/ptrdiff_t as long long -- and also
says targ_setjmp_func "setjmp" where legacy says "_setjmp", which is
the exact undefined symbol the first link reported.

The windows baggage is four families and one stray, all named:
wchar_t/wint_t unsigned short (APE says unsigned int); five
field-alignment variables, double_field_alignment 4 against kencc's 8
under -J, which is the most likely to bite and is unmeasured; three
bit-field rules; pointer-to-member 4 bytes with a short delta; and
packing_applies_to_base_classes.  Both targ_microsoft_* switches are 0
and the configuration sets no mode flags at all, so --microsoft is a
separate option that --target win64 does not imply.  jmp_buf differs
too (39 ints against 25 longs, APE's being neither), which matters
because EDG's exception model is setjmp-based.

With the target set, cpfe next wants lib_win64/predefined_macros.txt,
which we ship for no target.  --clear_flag=use_predefined_macro_file is
not a workaround: that file is where a win64 build's _WIN32 and
_MSC_VER come from, so suppressing it is precisely LLP64 without the
Windows macros, and it is the flag this tree's own translation recipe
already uses.

--target win64 is a bridge to a first translation with four named
divergences.  The end state is entry 0 carrying kencc's own values,
which fixes every item on that list at once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
… not it

With --clear_flag=use_predefined_macro_file cpfe accepts the target and
the option and then faults at addr=0x68.  Option parsing and target
selection are both past -- one flag earlier the same binary gave a clean
catastrophic error -- so the fault is in real work.

The host cpfe, built from the same commit with the same target
configuration and given the same flags and the same four --sys_include
directories, exits 0 and writes the expected C.  That puts the fault on
the kencc/libap side rather than on EDG's.

The static-init gap was the obvious suspect and is refuted by
measurement: the 133-file corpus holds exactly one __sti__ routine, in
fe_init.c, and its body assigns 0 to sixteen members of
diagnostic_counters -- values a BSS global already has.  The gap remains
real for programs cpfe translates and is inert for cpfe itself.

Next steps recorded in the NOTE: a sys: trap leaves the process Broken,
so acid plus lstk(), whether any C was written, and whether an empty
input faults at the same pc.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
@staalmannen
staalmannen merged commit f14d54a into main Oct 8, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants