From 17bf5e352bc1541b8084ba578c15d621f151b80b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 7 Oct 2026 18:02:48 +0000 Subject: [PATCH 1/2] tcl: the per-name baseline, and withdraw the -J socket confirmation Total 68118 Passed 62159 Skipped 5916 Failed 43, marker, exit 0, 167 files, tcl::test 9.0.3 present. Total and Skipped are identical to the digit against the recorded 62156/46, so Passed +3 / Failed -3 is one statement about the same 68118 executions. All 43 names are now recorded in docs/notes/tcl-suite.md with the extraction command beside them. Their absence is what kept the per-name question open for rounds while every comparison was made by total -- this file's own rule says compare per name, never by total, and no list existed to compare against. Three fixed, nothing broken, all three named: chan-io-41.8, expr-old-37.21 and unixFCmd-2.2.2, three of the eleven recorded unread singletons. Three gone and the net is three, so nothing arrived. None was predicted or being worked on, so the vehicle is unidentified and naming one would be a guess. Both questions the -J round left open are answered. socket_inet-5.1 and 5.3 are still failing, so they were not among the eighteen and the leftover-listener false pass did not return. event.test and main.test are event-1.1 and Tcl_Main-5.10, unchanged rather than new. AND THERE IS NO socket_inet.test. The -J round recorded that it had "left the failing-file list entirely" and offered that as the behavioural confirmation that -J had not broken the socket half of its own blast radius. The suite has one socket.test, whose body is `foreach {af localhost}` with `test socket_$af-1.1`, so every socket_inet-* name is generated with $af = inet; a grep for socket_inet-5.1 matches no file in the tree. Its absence from the list could not have been anything else under any outcome, and socket_inet still has four failures (2.11, 5.1, 5.3, 7.3) -- the same four already listed as unread. The eighteen stand on the totals; the attribution to sockets does not, and with the pthread half skipped the behavioural confirmation of -J covers neither family it moved. New method rule: a name absent from a list is not a measurement until you have checked the name could ever have appeared there. Also corrected: zipfs is five zipfs-password-* cipher tests where the notes recorded three -- one family sized from a prediction rather than counted from the names. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs --- CLAUDE.md | 80 +++++++++++++++++------ docs/notes/tcl-suite.md | 140 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+), 21 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f47e97b35..0033f90ba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1232,31 +1232,56 @@ with errors` section is gone**, so this really is the test interpreter. *The void run and this one differ in nothing but which binary ran them, and that is the cleanest control this suite can give.* -**`socket_inet.test` HAS LEFT THE FAILING-FILE LIST ENTIRELY**, and -sockets are half of the measured blast radius -- `sockaddr_in` -24 -> 16, `in_addr` 8 -> 4, `sockaddr_storage` 112 -> 110. *The -refutation condition was written down before the switch -- "a NEW -socket failure means something is computing a length it should not" --- and the opposite happened in the one file named.* `socket.test` -still fails, which is the `_resettimer`/timer-process story and -predates this. +**AND THE SOCKET CONFIRMATION IS WITHDRAWN: THERE IS NO +`socket_inet.test`.** This round recorded *"`socket_inet.test` has +left the failing-file list entirely"* as the behavioural evidence that +`-J` had not broken the socket half of its own blast radius +(`sockaddr_in` 24 -> 16, `in_addr` 8 -> 4). **That file does not exist +and never did**: the suite has one `socket.test`, whose body is +`foreach {af localhost}` with `test socket_$af-1.1 ...`, so every +`socket_inet-*` name is GENERATED with `$af` = `inet`, and a grep for +`socket_inet-5.1` matches no file in the tree. *Its absence from the +list could not have been anything else under any outcome* -- and the +substance fails too: **`socket_inet` has four failures, 2.11, 5.1, +5.3, 7.3**, which is exactly the "`socket_inet` 4" already listed as +unread below. **A name absent from a list is not a measurement until +you have checked the name could ever have appeared there** -- an +absence has two explanations, the thing passed or it was never called +that, and only one is a result. +*The eighteen stand on `Total` and `Skipped` being identical with +`Passed` +18, which is sound. The ATTRIBUTION to sockets does not* -- +so with the pthread half already recorded as skipped (`197 thread`, +`12 testmutex`), the behavioural confirmation of `-J` covers neither +family it actually moved. **THE PTHREAD HALF IS NOT MEASURED HERE, and the skip table says so rather than leaving it to be assumed**: `197 thread` and `12 testmutex` are SKIPPED, so `pthread_mutex_t` 56 -> 40 and `pthread_cond_t` 56 -> 48 were barely exercised. *Half the blast radius is confirmed and half is untouched*, which is a different statement from "the suite is clean". -**TWO THINGS TO CHECK PER NAME BEFORE THIS IS CLOSED.** The totals -cannot tell 18 fixed from 20 fixed and 2 broken -- this tree's own -rule -- and `event.test` and `main.test` appear in the failing list -where the baseline notes had `event-1.1` and `Tcl_Main-5.10` as -unread singletons, so they are probably unchanged rather than new. -**And `socket_inet-5.1`/`5.3` were recorded as tests that SHOULD -fail** (`notRoot`, and glenda is the host owner): if they are among -the eighteen, that is the leftover-listener false pass returning, not -a fix. *A test that newly passes may be passing for the wrong -reason* -- and this is exactly the file where that has happened -before. +**BOTH PER-NAME QUESTIONS ARE NOW ANSWERED, AND A PER-NAME BASELINE +EXISTS AT LAST** -- `docs/notes/tcl-suite.md` carries all 43 names and +the extraction command, because *its absence is what kept this open +for rounds* while every comparison was made by total. +**`Total 68118 Passed 62159 Skipped 5916 Failed 43`**, marker, +exit 0, 167 files, four minutes, `tcl::test 9.0.3 present`. +- **`socket_inet-5.1`/`5.3` were NOT among the eighteen**: both are + still failing, so the leftover-listener false pass did NOT return. + That was the stated hazard and this is the good answer. +- **`event.test`/`main.test` were unchanged, not new**: by name they + are `event-1.1` and `Tcl_Main-5.10`, the two singletons already on + the list. +**AND 46 -> 43 IS THREE FIXED, NOTHING BROKEN, ALL THREE NAMED**: +`chan-io-41.8`, `expr-old-37.21` and `unixFCmd-2.2.2`, three entries +of the eleven unread singletons. *Three gone and the net is three, so +nothing arrived* -- the only form that confirmation can take, and the +first time this suite's movement has been attributed by name. **None +was predicted or being worked on**, so the vehicle is unidentified and +naming one would be a guess; the baseline makes the next run settle +it. (`io-6.46` and `chan-io-6.46` now both fail, which is the twins +rule working as written; zipfs is **five** `zipfs-password-*` cipher +tests where this file recorded three, one family undercounted from a +prediction rather than a regression.) **AND THE FIRST REBUILD STOPPED IN bash -- NOT ON `-J`, ON A SHADOWED HEADER.** `/sys/include/ape/qlock.h:44 syntax error, last name: Lock`, @@ -1983,6 +2008,15 @@ in the topic file. `tcl-runall.tcl`; check for it before reading any total. - **A marker says the run reached the end, not that it was the run you asked for.** Read the `Total` line beside it. +- **A NAME absent from a list is not a measurement until you have + checked that the name could ever have been present.** An absence has + at least two explanations -- the thing passed, or it was never called + that -- and only one of them is a result. `socket_inet.test` was + recorded as having "left the failing-file list" and offered as the + behavioural confirmation of `-J`; **there is no such file**, the + names are generated inside `socket.test` by a `foreach {af ...}` + loop, and `socket_inet`'s four failures never moved. One `ls` would + have cleared it. - **And check the log's own `Tests ended at` line before reading anything from it.** A copied file that was never committed leaves the previous run in place, and a stale log reads exactly like a real one. @@ -2331,8 +2365,12 @@ or a constraint that fails on Linux too). The port's own share is `focus-6.1`, `geometry-4.7`, `event-9.13`/`9.14` and `visual-3.1`. **Tcl's suite**: **it finishes and nothing aborts.** -**`Total 68118 Passed 62156 Skipped 5916 Failed 46`** under `-J`, -167 files, marker, exit 0, no `Test files exiting with errors`. +**`Total 68118 Passed 62159 Skipped 5916 Failed 43`**, 167 files, +marker, exit 0, no `Test files exiting with errors`, four minutes. +**All 43 are listed BY NAME in `docs/notes/tcl-suite.md`** with the +one-command extraction beside them -- the first per-name baseline this +suite has had, and the thing whose absence made every earlier +comparison a total. The log is committed at `tmp/tcl-all.out`. *(The baseline this is measured against is `Passed 62138 Failed 64`, same Total and Skipped; the eighteen are discussed in the `-J` section. A run in between reporting `Failed 37` diff --git a/docs/notes/tcl-suite.md b/docs/notes/tcl-suite.md index 75f8d85a2..c62d5d2d8 100644 --- a/docs/notes/tcl-suite.md +++ b/docs/notes/tcl-suite.md @@ -7185,3 +7185,143 @@ multiplication's range, so `scalbn`'s broken arm was never involved. Run it with `pcc -o binfloat-test binfloat-test.c && ./binfloat-test` and read which section fails; that names the cause in one run instead of by elimination. + +--- + +## The per-name baseline: 43 failing tests, 2026-10-07 + +**This list exists because its ABSENCE kept one question open for +rounds.** This file's own rule is *compare runs per file, never by +total* -- and every Tcl round so far has been compared by total, +because no per-name list was ever written down. `Failed 46 -> 43` +cannot tell three fixed from five fixed and two broken; the names can. + +Provenance, which has to be read before anything else here (the stale +log and the void `tclsh` run are both recorded above): + +``` +tcl-runall: tcl::test 9.0.3 present -- this is the test interpreter. +Tests began at 2026-10-07 17:50:49 +0200 +Tests ended at 2026-10-07 17:54:57 +0200 +all.tcl: Total 68118 Passed 62159 Skipped 5916 Failed 43 +Sourced 167 Test Files. +tcl-runall: exit called (code 0) +``` + +The log is committed at `tmp/tcl-all.out`. **It does NOT contain the +four C++-usability header fixes** (`_Noreturn`, `template`, `new`, +`restrict`), which landed after this rebuild; it does contain the +`features.h`, `getopt` and `libnet.h` changes. + +The 43, sorted, every one of which already appears somewhere in this +file or in CLAUDE.md: + +``` +Tcl_Main-5.10 chan-io-28.7 chan-io-40.3 chan-io-6.31 chan-io-6.43 +chan-io-6.44 chan-io-6.45 chan-io-6.46 cmdAH-20.5 cmdAH-25.3 +env-2.1 env-2.2 env-2.3 env-2.4 env-3.1 env-4.1 env-4.3 +env-4.4 env-4.5 event-1.1 exec-19.1 io-29.33b io-40.3 +io-52.22.1 io-6.31 io-6.43 io-6.44 io-6.45 io-6.46 lseq-4.21.4 +scan-15.1 socket-14.19 socket_inet-2.11 socket_inet-5.1 +socket_inet-5.3 socket_inet-7.3 unixFCmd-1.1 unixInit-1.2 +zipfs-password-read-cipher-2 zipfs-password-write-cipher-w-2 +zipfs-password-write-cipher-deflate-w +zipfs-password-write-cipher-deflate-w+ +zipfs-password-write-cipher-deflate-a+ +``` + +To compare the next run, extract the same way rather than by eye -- +`grep -oE '^==== [^ ]+ FAILED' | awk '{print $2}' | sort -u` -- +and diff against the block above. + +### THREE FIXED, NOTHING BROKEN, ALL THREE NAMED + +`Failed 46 -> 43` with **`Total` and `Skipped` identical to the +digit**, which is what makes the arithmetic a statement about the same +68118 executions rather than about a different suite. And the three +are exactly three entries of the recorded eleven unread singletons: + +``` + chan-io-41.8 GONE + expr-old-37.21 GONE + unixFCmd-2.2.2 GONE +``` + +*Three gone and the net is three, so nothing arrived* -- which is the +only form that confirmation can take, and it is the first time this +suite's movement has been attributed by name instead of by total. +**None of the three was predicted and none was being worked on**, so +which change carried them is unidentified; guessing a vehicle would be +the third such story in this file. The cheap discriminator is the next +run, now that a baseline exists. + +### THE TWO QUESTIONS THE `-J` ROUND LEFT OPEN ARE BOTH ANSWERED + +- **`socket_inet-5.1`/`5.3` were NOT among the eighteen.** Both are + still failing, so *the leftover-listener false pass did not return* + -- which was the stated hazard, since those two want a port bind + refused and a stale listener had been refusing it. The prediction + was written down before the run and the answer is the good one. +- **`event.test` and `main.test` were unchanged, not new.** Read by + name they are `event-1.1` and `Tcl_Main-5.10`, exactly the two + singletons the baseline already carried. + +### AND A CORRECTION THAT MATTERS MORE THAN THE THREE: THERE IS NO `socket_inet.test` + +The `-J` round recorded *"`socket_inet.test` HAS LEFT THE FAILING-FILE +LIST ENTIRELY"* and offered it as the behavioural confirmation that +`-J` had not broken the socket half of its measured blast radius +(`sockaddr_in` 24 -> 16, `in_addr` 8 -> 4). + +**That file does not exist and never did.** `ls` over the suite shows +one `socket.test`, and its body is a loop -- +`foreach {af localhost} {...}` with `test socket_$af-1.1 ...` -- so +every `socket_inet-*` name is GENERATED inside `socket.test`, with +`$af` taking the value `inet`. A grep for `socket_inet-5.1` matches no +file in the tree at all. + +So the absence of `socket_inet.test` from `Files with failing tests` +was never evidence of anything: it could not have appeared there under +any outcome. And the substance does not hold either -- **`socket_inet` +has four failures in this run, 2.11, 5.1, 5.3 and 7.3**, which is +exactly the "`socket_inet` 4" this file already listed as unread. They +did not go away and they have not moved. + +*The eighteen-test improvement under `-J` stands: it rests on `Total` +and `Skipped` being identical with `Passed` +18, which is sound. What +does not stand is the attribution of it to sockets.* The socket half +of the blast radius is **unmeasured**, not confirmed -- and the +pthread half was already recorded as unmeasured, because `197 thread` +and `12 testmutex` are skipped. So the behavioural confirmation of +`-J` covers neither family it actually moved. + +**The rule this breaks is one already in this file**: *a marker says +the run reached the end, not that it was the run you asked for* -- and +its sharper form, which is new. **A file name absent from a list is +not a measurement until you have checked that the name could ever have +been present.** An absence has at least two explanations -- the thing +passed, or the thing was never named that way -- and only one of them +is a result. Same family as *a check whose negative result has two +explanations*, arriving for a FILE NAME rather than a test. + +### Still true, and worth keeping beside the list + +- **`io-6.46` and `chan-io-6.46` now BOTH fail**, which is the twins + rule working: `io-6.46` was recorded as *flaky not fixed* precisely + because its twin still failed, with "count that group by whether the + twins agree" written down. They agree. +- **`socket_inet-2.11` FAILS rather than hanging**, so the + `_resettimer` repair is still holding -- the suite completed in four + minutes with no file aborting. +- **`chan-io-40.3`/`io-40.3` still fail with `umask()` now working**, + which is correct rather than surprising: the initial mask is + deliberately 0, the file server hands out `perm & (dirperm | ~0666)` + regardless, and the test computes 0666. *A conformance fix that was + deliberately not a default change does not move a test that measures + the default.* +- **zipfs is FIVE, where this file records three.** All five are + `zipfs-password-*` cipher tests with `errorCode TCL ZIPFS PASSWORD` + -- one family, zipfs's own, so the "13 -> 3 CONFIRMED" undercounted + a single cluster by two rather than anything regressing. *A cluster + sized from a prediction rather than counted from the names, which is + the same error as sizing `run-redir` from one section head.* From ddbe2c0d4cd9c7c11df9e0a14956c58917541cb7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 7 Oct 2026 18:29:16 +0000 Subject: [PATCH 2/2] edg: mkfiles for the runtime library and cpfe It is three products rather than one, and `main' settles that rather than taste: src's 75 files hold exactly one (cfe.c), so they are one binary; util's seven hold six, plus decode.c with none, which is edg_decode's second object; lib_src's 51 hold none, so they are a library. So sys/src/ape/lib/edg builds libedg.a with mksyslib and sys/src/ape/cmd/edg builds cpfe with mkone. util is six small binaries and blocks nothing, so it is not written yet. Neither is added to cmd/mkfile's lists: one failing entry aborts the whole tree's mk, which is why basic and c++lib are commented out there. Build by hand first. Order is a dependency, not a preference. lib/edg first, because an archive sidesteps the link model entirely -- ar takes duplicate members and the clash only arrives at a link -- so it answers "does pcc compile EDG's generated C" with nothing else in frame. Then cmd/edg, where the compile of a 315,616-line translation unit (src/sys_predef.c) and the 3,094 duplicate COMDAT symbols both land. Run it as `mk -k': Plan 9 mk stops at the first failing recipe, so a plain run costs one round per bad file across 75 files. cpfe has no LIB=, and that is a question rather than a claim. It is itself a translated C++ program so it may want EDG's own runtime, and reading cannot settle it: src holds 145,752 distinct _Z-prefixed tokens, nearly all names it defines itself, with ordinary identifiers like _ZERO among them. Only the link says which are undefined. It is not obviously needed -- EDG is built -fno-exceptions -fno-rtti and src references none of _Znwm/_Znam/_ZdlPv/_ZdaPv, __memzero or __abort_execution -- so the first link is the measurement and the fix, if any, is one line naming libedg.a. That is the second reason to build the library first. Checked rather than assumed, because this tree has paid for it: the runtime adds nothing libap already provides. lib_src holds exit.c, main.c, error.c and memzero.c, which is the gnulib strerror shape -- but every definition there is _Z-mangled or __-prefixed (exit.c defines _Z4exiti, memzero.c defines __memzero) and the plain C names appear only as declarations, so they resolve to libap rather than replacing it. The filenames read alarmingly and the definitions do not. Also measured: EDG bakes in no struct sizes at all -- zero `sizeof X == N' markers against cfront's 132 -- because it emits real sizeof expressions, so kencc computes every layout and cfrontsz-probe's class of problem does not recur. CFLAGS is -c alone so nothing is quieted on the first run; no -I or -D is needed because each file is a whole lowered translation unit that declares everything it uses, down to its own memcpy with kencc's size_t. Both OFILES lists are sound and complete: 51 and 75, no name missing a file and no file missing from a list. mkcont-sweep 0. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs --- CLAUDE.md | 59 +++++++++++- sys/src/ape/cmd/edg/mkfile | 182 +++++++++++++++++++++++++++++++++++++ sys/src/ape/lib/edg/mkfile | 104 +++++++++++++++++++++ 3 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 sys/src/ape/cmd/edg/mkfile create mode 100644 sys/src/ape/lib/edg/mkfile diff --git a/CLAUDE.md b/CLAUDE.md index 0033f90ba..01e2b54e6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1835,8 +1835,63 @@ live either way. is reachable by regenerating the macro configuration rather than by setting switches, and it changes mangling, the ctor/dtor model and vtable layout. Its own round. - - **NO MKFILE, AND NOTHING HERE HAS BEEN THROUGH pcc.** That is the - next step and the link model is what it will run into. + - **THE MKFILES ARE WRITTEN AND NOTHING HAS BEEN THROUGH pcc YET.** + **It is THREE products, not one**, which `main` settles rather than + taste: `src`'s 75 files hold exactly one (`cfe.c`) so they are one + binary, `cpfe`; `util`'s seven hold six, plus `decode.c` with none + (it is `edg_decode`'s second object); `lib_src`'s 51 hold none, so + they are a LIBRARY. Hence `sys/src/ape/lib/edg` -> `libedg.a` + (`mksyslib`) and `sys/src/ape/cmd/edg` -> `cpfe` (`mkone`); `util` + is six small binaries and blocks nothing. + **DELIBERATELY NOT IN `cmd/mkfile`'s lists** -- one failing entry + aborts the whole tree's `mk`, as `basic` and `c++lib` already + record. By hand first. + **ORDER IS A DEPENDENCY RATHER THAN A PREFERENCE.** lib/edg first, + because an archive sidesteps the link model entirely -- `ar` takes + duplicate members and the clash only arrives at a LINK -- so it + answers "does pcc compile EDG's generated C" with nothing else in + frame. Then cmd/edg, where both remaining questions land. + **AND `mk -k`, NOT `mk`**: Plan 9 mk stops at the first failing + recipe, so a plain run costs one round per bad file across 75; + -k names them all at once. *That is the rule bacon's missing + headers and bacon's missing link symbols both paid for.* + **`src/sys_predef.c` IS 315,616 LINES IN ONE TRANSLATION UNIT** + (`ifc_modules_read.c` 130,330, `expr.c` 120,824; 2.9M lines over + the 133). A `6c` table limit is the likeliest first answer, and it + would be kencc's rather than the port's -- worth knowing before + anything is blamed on EDG. + **`cpfe` HAS NO `LIB=`, AND THAT IS A QUESTION, NOT A CLAIM.** + cpfe is itself a translated C++ program so it may want EDG's own + runtime, and *reading cannot settle it*: `src` holds 145,752 + distinct `_Z`-prefixed tokens, nearly all names it defines itself, + with ordinary identifiers like `_ZERO` among them. Only the link + says which are undefined. It is not obviously needed -- EDG is + built `-fno-exceptions -fno-rtti` and `src` references none of + `_Znwm`/`_Znam`/`_ZdlPv`/`_ZdaPv`, `__memzero` or + `__abort_execution` -- so the first link is the measurement and + the fix, if any, is one line naming `libedg.a`. + - **AND THE RUNTIME ADDS NOTHING libap ALREADY PROVIDES, checked + rather than assumed.** `lib_src` holds `exit.c`, `main.c`, + `error.c` and `memzero.c`, which is the shape that cost this tree + the gnulib `strerror` round -- but **every DEFINITION there is + `_Z`-mangled or `__`-prefixed**: `exit.c` defines `_Z4exiti`, + `memzero.c` defines `__memzero`. The plain C names (`memset`, + `memcpy`, `malloc`, `free`, `abort`, `exit`) appear only as + DECLARATIONS and resolve to libap rather than replacing it. + *The filenames read alarmingly and the definitions do not* -- + the declaration/definition distinction the `reject` round cost a + build over, asked the right way round this time. + **And EDG bakes in NO struct sizes**, which is the other thing + cfront's C did and the reason its oracle existed: zero + `sizeof X == N` markers against cfront's 132, because EDG emits + real `sizeof` expressions. *kencc computes every layout here*, so + conforming `-J` is exactly what the generated code wants and + `cfrontsz-probe`'s whole class of problem does not recur. + **Both OFILES lists are sound AND complete** -- 51 and 75, no + name missing a file and no file missing from a list, which are + different properties and only one of them was checked the time + the 47-of-97 probe passed its control and measured the wrong + types. `mkcont-sweep` 0. - **Its staging list doubled as a to-do list for our own headers.** Eight APE headers could not be included from C++; **four were fixed on their own evidence** later in the same session diff --git a/sys/src/ape/cmd/edg/mkfile b/sys/src/ape/cmd/edg/mkfile new file mode 100644 index 000000000..5a21fe247 --- /dev/null +++ b/sys/src/ape/cmd/edg/mkfile @@ -0,0 +1,182 @@ +APEXPROOT=../../../../.. +APE=$APEXPROOT/sys/src/ape +<$APE/config +EDGSRC=../../../external/edg/src + +# cpfe -- EDG's C++ front end, built from EDG's own C. One binary from +# 75 translation units; `src/cfe.c' is the only one with a `main'. +# See sys/src/external/edg/NOTE for how the C was produced and for the +# target configuration, `kencc_targ.h', which is committed beside it. +# +# DELIBERATELY NOT IN `sys/src/cmd/mkfile''s app lists, and the reason +# is this tree's own: ONE FAILING ENTRY ABORTS THE WHOLE TREE'S `mk', +# which is why `basic' and `c++lib' are commented out there too. Build +# this directory BY HAND until it comes back clean. +# +# TWO THINGS ARE EXPECTED TO BE MEASURED HERE, in this order, and they +# are different questions with different answers. +# +# 1. DOES pcc COMPILE IT. Nothing in this directory has ever been +# through pcc. `src/sys_predef.c' is **315,616 lines in one +# translation unit** (`ifc_modules_read.c' is 130,330 and +# `expr.c' 120,824), so a compiler table limit is the first thing +# likely to answer, and it would be kencc's answer rather than the +# port's -- worth knowing before anything is blamed on EDG. +# **RUN IT AS `mk -k'.** Plan 9 mk stops at the first failing +# recipe, so a plain `mk' costs one round per bad file across 75 +# files; -k compiles the rest and the run names every one at once. +# That is the rule this tree has paid for twice -- bacon's missing +# header names and bacon's missing link symbols were both asked all +# at once rather than one per round, and both came back complete. +# +# 2. THEN THE LINK, WHICH IS THE KNOWN WALL. `mkone' compiles every +# OFILE before it links, so a compile pass followed by a link +# failure is the expected shape and is TWO results rather than one. +# EDG emulates COMDAT for vague linkage -- inline functions, +# template instantiations, vtables, typeinfo -- and with the kencc +# target that emulation emits no `__weak__' at all (38,245 applied +# attributes went to 0), so the duplicates are now plain. Measured +# on two trivial translation units sharing one header: they collide +# on **10 symbols**; across these 75 files **3,094 COMDAT symbols +# are named in more than one**. `6l' will say which, and its list +# is worth more than that grep -- the grep counts annotations, some +# of which are declarations rather than definitions, so 3,094 is an +# UPPER bound on colliding definitions. +# Neither answer to that is reached by editing this mkfile: +# `--one_instantiation_per_object' covers only the template share +# (3 of the 10) and makes the output depend on an `edg_prelink' +# phase, and upstream's answer for a target without COMDAT is the +# Cfront-like ABI, which was attempted and backed out. The NOTE +# carries both and where each stops. +# +# NO -I AND NO -D: each file declares everything it uses, including its +# own `void *memcpy(void *, const void *, unsigned long long)', where +# the `unsigned long long' is kencc's size_t from `kencc_targ.h'. +# CFLAGS is `-c' alone so that nothing is quieted on the first run. +# +# AND NO `LIB=' -- which is a QUESTION rather than a claim, and it is +# why `sys/src/ape/lib/edg' should be built first. cpfe is itself a +# C++ program translated to C, so it may want EDG's own runtime +# (`lib_src': new, delete, vtable support, static init, pure-virtual, +# RTTI -- NOT libstdc++). Reading cannot settle it: `src' holds +# 145,752 distinct `_Z'-prefixed tokens and nearly all are names it +# defines itself, with ordinary identifiers like `_ZERO' among them, so +# a grep over them measures nothing. *Only the link says which are +# undefined.* It is not obviously needed -- EDG is compiled +# `-fno-exceptions -fno-rtti' and `src' references none of +# `_Znwm'/`_Znam'/`_ZdlPv'/`_ZdaPv', nor `__memzero' or +# `__abort_execution' -- so the first link is the measurement, and if +# it names undefined `_Z' symbols the fix is one line: +# LIB=$APEXPROOT/$objtype/lib/ape/libedg.a +# **Build lib/edg before this directory so that line is available +# rather than blocking a round.** +# +# One thing the runtime does NOT do, checked rather than assumed, +# because this tree has paid for it once: it adds nothing libap +# already provides. Every DEFINITION under `lib_src' is `_Z'-mangled +# or `__'-prefixed -- `exit.c' defines `_Z4exiti', `memzero.c' defines +# `__memzero' -- and the plain C names (`memset', `memcpy', `malloc', +# `free', `abort', `exit') appear only as DECLARATIONS, so they resolve +# to libap rather than replacing it. *The filenames read alarmingly +# and the definitions do not*, which is the declaration/definition +# distinction the `reject' round cost a build over. + +TARG=cpfe + +BIN=$APEXPROOT/$objtype/bin/ape + +OFILES=\ + attribute.$O\ + c_gen_be.$O\ + cfe.$O\ + cfe_daemon.$O\ + class_decl.$O\ + cmd_line.$O\ + const_ints.$O\ + cp_gen_be.$O\ + debug.$O\ + decl_inits.$O\ + decl_spec.$O\ + declarator.$O\ + decls.$O\ + def_arg.$O\ + disambig.$O\ + error.$O\ + expr.$O\ + exprutil.$O\ + extasm.$O\ + fe_init.$O\ + fe_wrapup.$O\ + fixed_pt.$O\ + float_pt.$O\ + floating.$O\ + folding.$O\ + func_def.$O\ + host_envir.$O\ + ifc_map_functions.$O\ + ifc_map_functions_acc.$O\ + ifc_map_functions_dbg.$O\ + ifc_map_functions_mut.$O\ + ifc_map_functions_val.$O\ + ifc_modules.$O\ + ifc_modules_read.$O\ + ifc_modules_templ.$O\ + ifc_modules_write.$O\ + il.$O\ + il_alloc.$O\ + il_display.$O\ + il_read.$O\ + il_to_str.$O\ + il_walk.$O\ + il_write.$O\ + inline.$O\ + interpret.$O\ + layout.$O\ + lexical.$O\ + literals.$O\ + lookup.$O\ + lower_c99.$O\ + lower_eh.$O\ + lower_il.$O\ + lower_init.$O\ + lower_name.$O\ + macro.$O\ + mem_manage.$O\ + modules.$O\ + ms_attrib.$O\ + overload.$O\ + pch.$O\ + pragma.$O\ + preproc.$O\ + scope_stk.$O\ + src_seq.$O\ + statements.$O\ + symbol_ref.$O\ + symbol_tbl.$O\ + sys_predef.$O\ + target.$O\ + templates.$O\ + trans_copy.$O\ + trans_corresp.$O\ + trans_unit.$O\ + types.$O\ + unicode_name_fsm.$O\ + +UPDATE=\ + mkfile\ + ${OFILES:%.$O=%.c}\ + +<$APEXPROOT/sys/src/cmd/mkone + +CC=pcc +LD=pcc +CFLAGS= -c + +%.$O: $EDGSRC/%.c + $CC $CFLAGS $EDGSRC/$stem.c + +install:V: + cp $O.out $BIN/cpfe + +nuke:V: + rm -f $BIN/cpfe diff --git a/sys/src/ape/lib/edg/mkfile b/sys/src/ape/lib/edg/mkfile new file mode 100644 index 000000000..88ebc9d8d --- /dev/null +++ b/sys/src/ape/lib/edg/mkfile @@ -0,0 +1,104 @@ +