diff --git a/CLAUDE.md b/CLAUDE.md index ba9d0b2b0..f47e97b35 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1559,6 +1559,12 @@ sweep rather than argued, and each named its own error. blast radius is every package in the tree, and no instrument here measures that* -- the cheap guard is to grep `external/` for the bare word before adding any name to `sys/include/ape`. + **CONFIRMED ON THE VM: the revert builds.** `mk distclean` plus + `mk install` completes, so the tree gets past `lex` and the whole + order after it was reached for the first time since the header + changed. *That is the weakest useful result and is worth saying so* + -- it confirms the collision is gone, and the `net_*` removal + beside it costs no link, which is all a completed build can say. - **`getopt`: TWO INSTALLED HEADERS DECLARED IT INCOMPATIBLY, and my note said there was only one.** `bsd.h:47` had `(int, char**, char*)` while **`getopt.h:8` has had POSIX's @@ -1754,13 +1760,102 @@ live either way. ## What is open, as a list **Ports not started**, in the order their risk was last measured: -- **EDG** -- investigated and measured on the host (it builds, the - default build IS the C-generating one, `eccp -S` translates a toy - with templates and virtual bases into C that gcc compiles). Two - named risks remain and both are one host afternoon: `targ_def.h` - describing kencc (`int` 4, `long` **4**, pointer 8 -- LLP64, which - EDG supports for MSVC), and whether its C back end handles the C++ - subset EDG itself is written in. No mkfile written. +- **EDG** -- **BOTH NAMED RISKS ARE CLOSED AND THE SELF-TRANSLATION IS + IN THE TREE.** `sys/src/external/edg` holds **133 generated C files, + ~2.90M lines**: all 75 `src/`, 7 `util/` and 51 `lib_src/`, produced + by a `cpfe` built from the same commit with a kencc target, plus + EDG's own 17 C++ headers verbatim. `gcc -fsyntax-only` over all 133 + is **0 errors, 0 warnings** -- which is the host's answer and says + nothing about kencc. Full detail in `sys/src/external/edg/NOTE`; + only the consequences are here. + - **Risk 1, the target description: answered by EDG's own `win64`.** + kencc on amd64 is LLP64 and win64 is EDG's LLP64 configuration, so + the values were taken from the build's generated + `cmake_defines.h` rather than invented. Every scalar width + matches, **including `long double` 8** -- win64 says 8 because + MSVC has no extended precision and kencc says 8 because + `cc/sub.c`'s `simplet()` maps `BDOUBLE|BLONG` to `types[TDOUBLE]`, + which was not predicted. `size_t`/`ssize_t`/`ptrdiff_t` are + win64's kinds too, read out of `stddef_arch.h`; **`wchar_t` is the + one place the two differ** (`unsigned int` here, `unsigned short` + there). `kencc_targ.h`, committed beside the NOTE, is the whole + configuration -- a **pre-included header**, so nothing in the EDG + tree is modified. + - **Risk 2, self-translation: it translates.** One file does not and + it is the right one -- `util/cfe_daemon_client.c`, the only file + in the tree needing a real C++ standard library, and a + unix-domain-socket client is out of scope here twice over. + - **The target was inferred from the compiler that BUILT cpfe, which + is the finding of the round.** `targ_def.h:3505` derives + `GCC_IS_GENERATED_CODE_TARGET` from `defined(__GNUC__)`, and that + one variable is the sole gate on both `__weak__` emission sites -- + so cpfe built by g++ decided its OUTPUT was for gcc and emitted + **26,712 `__attribute__((__weak__))`**, which kencc has not. A + first round also baked in LP64 and glibc's headers. Setting it to + 0 and staging APExp's own headers takes the applied-attribute + count **38,245 -> 0**; the 11 textual occurrences left are all + inside string literals, EDG's own emitter text. + - **THE LINK MODEL IS THE OPEN PROBLEM, and removing `__weak__` + exposed it rather than solving it.** Those attributes were COMDAT + emulation for vague linkage. Measured: two trivial TUs sharing one + header collide on **10 symbols**, and across `src/` there are + **3,094 COMDAT symbols named in more than one of the 75 files**. + `--one_instantiation_per_object` is deliberately NOT used -- it + covers only the template instantiations (3 of the 10) and makes + the output depend on an `edg_prelink` phase mk cannot naturally + express. Upstream's answer for a target without COMDAT is the + **Cfront-like ABI**, and that was attempted and **backed out**: + `IA64_ABI=0` makes cpfe fail to *compile* on three + `TARGET_CONFIGURATION`-suffixed macros the Cfront ABI needs, so it + 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. + - **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 + (`signal()`'s prototype, the `SIG_*` casts, `features.h`'s + `hidden`, `bsd.h`'s `getopt`) and a re-translation need not repeat + them. **The other four are fixed now too, so the staging list is + closed**: `stdlib.h`'s unguarded `_Noreturn`, its parameter named + `template`, `unistd.h`'s parameter named `new`, and `signal.h`'s + `restrict` read as a duplicate parameter name -- every one a + parameter name or a keyword, so invisible to a C caller. + *EDG is a stricter compiler than gcc, and that is what it bought.* + - **AND THE OBVIOUS FIX FOR TWO OF THEM WAS THE ONE THAT HAD JUST + BROKEN THE BUILD.** `#define _Noreturn` or `#define restrict` + under `__cplusplus` would put an UNRESERVED name in a public APE + header that external packages define themselves -- gnulib ships a + whole `_Noreturn.h`, and a dozen `config.h` here define + `restrict` -- which is `reject` again, one round later. **The + bare-word sweep was run FIRST this time**, and it is what chose + the spellings: everything used is in the reserved + double-underscore space, which nothing outside an implementation + may define. + **Three of the four need no macro at all.** `restrict` becomes + `__restrict`, which costs nothing because *kencc lexes all three + spellings to the same `LRESTRICT`* (`cc/lex.c:1652,1678-1679`) -- + and where a package's own `cdefs.h` defines `__restrict` (twelve + do) it expands to the qualifier or to nothing, correct either way. + The two parameters are renamed, which no caller can see. + `__ape_template` was not invented here: **EDG's generated C + already carries it**, so the staged edit had used this convention + and the tree now matches its own output. + - **The control is a before-and-after pair on IDENTICAL staging, and + it found a FIFTH item.** A C++ translation unit including + ``, `` and `` gives **12 errors + before and 1 after** -- and the survivor is `stddef.h:50` + typedef'ing **`wchar_t`, which is a built-in type in C++**, + present in BOTH runs and named nowhere in the NOTE's list of + eight. *Recorded, not fixed.* The half that could have cost the + tree is the other one: the same unit compiled as **C is 0 + errors**. `apehdr-sweep` 148 headers / 0 findings with the + together-case holding at its recorded 8; `apdecl-sweep` 0. + *The first staging recipe differed slightly between the two runs + and the after-count was re-taken with the before's exact + commands* -- two compiles differing in anything but the change + are not a control, which this file records from the `-J` round. - **muon** -- in `_OPTIONAL_APPS` commented out. Never built here. - **go** -- `go1.4` is in the tree, commented out of `_CORE_APPS`, and is the only thing that mentions `Ureg` outside libap. diff --git a/sys/include/ape/signal.h b/sys/include/ape/signal.h index 8f7fd0d97..7d32471e0 100644 --- a/sys/include/ape/signal.h +++ b/sys/include/ape/signal.h @@ -158,10 +158,25 @@ extern int sigaction(int, const struct sigaction *, struct sigaction *); extern int sigprocmask(int, sigset_t *, sigset_t *); extern int sigpending(sigset_t *); extern int sigsuspend(const sigset_t *); -extern int sigwait(const sigset_t *restrict, int *restrict); -extern int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict); +/* + * `__restrict' RATHER THAN `restrict', AND IT COSTS NOTHING: kencc + * lexes all three spellings to the same LRESTRICT (`cc/lex.c:1652, + * 1678-1679'). `restrict' is a C keyword and NOT a C++ one, so in C++ + * these read as PARAMETER NAMES -- and two per prototype is then a + * duplicate parameter name, which is why a C++ compiler could not + * read these three lines at all. + * + * `#define restrict' away for C++ would be the wrong fix twice over: + * it is an unreserved name, and gnulib's `config.h' already defines + * it in a dozen packages here. `__restrict' is reserved, so nothing + * outside an implementation may define it -- and where a package's + * own `cdefs.h' does (twelve do), it expands to the qualifier or to + * nothing, which is correct either way. + */ +extern int sigwait(const sigset_t *__restrict, int *__restrict); +extern int sigwaitinfo(const sigset_t *__restrict, siginfo_t *__restrict); struct timespec; /* avoid pulling in time.h */ -extern int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict); +extern int sigtimedwait(const sigset_t *__restrict, siginfo_t *__restrict, const struct timespec *__restrict); extern int sigqueue(pid_t, int, const union sigval); /* diff --git a/sys/include/ape/stdlib.h b/sys/include/ape/stdlib.h index 5b93f2d92..589b25f66 100644 --- a/sys/include/ape/stdlib.h +++ b/sys/include/ape/stdlib.h @@ -12,6 +12,28 @@ typedef struct { int quot, rem; } div_t; typedef struct { long quot, rem; } ldiv_t; +/* + * `_Noreturn' IS A C11 KEYWORD AND C++ HAS NO SUCH SPELLING, so the + * three declarations using it below could not be read by a C++ + * compiler at all. Found by EDG, which is stricter than gcc: its own + * sources had to be translated against a STAGED copy of this header, + * and the staging list is in `sys/src/external/edg/NOTE'. + * + * **The obvious fix is the one this tree has just been burned by.** + * `#define _Noreturn' under __cplusplus would be a public APE header + * defining a name ten external packages define themselves -- gnulib + * ships a whole `_Noreturn.h' -- which is the `reject' collision + * waiting for the next build. The spelling used instead is in the + * RESERVED double-underscore space, which nothing outside an + * implementation may define, and `__ape_template' below is the same + * convention; EDG's generated C already carries that one. + */ +#if defined(__cplusplus) +#define __ape_Noreturn +#else +#define __ape_Noreturn _Noreturn +#endif + #ifdef __cplusplus extern "C" { #endif @@ -44,9 +66,9 @@ extern void *calloc(size_t, size_t); extern void free(void *); extern void *malloc(size_t); extern void *realloc(void *, size_t); -extern _Noreturn void abort(void); +extern __ape_Noreturn void abort(void); extern int atexit(void (*func)(void)); -extern _Noreturn void exit(int); +extern __ape_Noreturn void exit(int); extern char *getenv(const char *); extern int putenv(char *); extern int system(const char *); @@ -66,8 +88,8 @@ extern size_t wcstombs(char *, const wchar_t *, size_t); #include extern char *mktemp(char *); -extern int mkstemp(char *template); -extern int mkostemp(char *template, int); +extern int mkstemp(char *__ape_template); +extern int mkostemp(char *__ape_template, int); /* from musl */ typedef struct { long long quot, rem; } lldiv_t; @@ -84,7 +106,7 @@ extern long long llabs(long long); extern lldiv_t lldiv(long long, long long); extern int at_quick_exit(void (*)(void)); -extern _Noreturn void quick_exit(int); +extern __ape_Noreturn void quick_exit(int); /* musl and other ports */ diff --git a/sys/include/ape/unistd.h b/sys/include/ape/unistd.h index 073e196ff..a0d53c101 100644 --- a/sys/include/ape/unistd.h +++ b/sys/include/ape/unistd.h @@ -183,13 +183,20 @@ int openat(int dirfd, const char *path, int flags, ...); /* unistd/at_functions. int fstatat(int dirfd, const char *path, struct stat *buf, int flags); int unlinkat(int dirfd, const char *path, int flags); int mkdirat(int dirfd, const char *path, mode_t mode); -int renameat(int olddirfd, const char *old, int newdirfd, const char *new); +/* + * `__ape_new' because `new' is a C++ KEYWORD, so these two lines + * could not be read from C++ at all. A parameter name in a prototype + * is documentation -- no caller can see it -- so this changes nothing + * for C. Same convention as `'s `__ape_template'; the + * reason both are in the reserved space is recorded there. + */ +int renameat(int olddirfd, const char *old, int newdirfd, const char *__ape_new); ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t n); int symlinkat(const char *target, int dirfd, const char *linkpath); int faccessat(int dirfd, const char *path, int mode, int flags); int fchownat(int dirfd, const char *path, uid_t uid, gid_t gid, int flags); int fchmodat(int dirfd, const char *path, mode_t mode, int flags); -int linkat(int old_dfd, const char *old, int new_dfd, const char *new, int flags); +int linkat(int old_dfd, const char *old, int new_dfd, const char *__ape_new, int flags); /* GNU extensions */ extern int pipe2(int [2], int); diff --git a/sys/src/external/edg/NOTE b/sys/src/external/edg/NOTE index 94e817150..efa8f0771 100644 --- a/sys/src/external/edg/NOTE +++ b/sys/src/external/edg/NOTE @@ -26,7 +26,11 @@ Converted cmake --preset linux-gcc-release -B build/kencc \ -DCMAKE_CXX_FLAGS="-include /kencc_targ.h" ninja cpfe - kencc_targ.h is the target configuration; see below. It is a + kencc_targ.h IS COMMITTED BESIDE THIS FILE -- it is the one + input to this directory that is neither upstream's nor + generated, so a scratch copy of it would have made the whole + translation unreproducible once the container went. + It is the target configuration; see below. It is a pre-included header rather than a patch: NOTHING IN THE EDG TREE IS MODIFIED. Driver: dev_tools/bin/eccp, with build/kencc/environment.sh sourced. @@ -270,31 +274,74 @@ it makes the output DEPEND on a prelink step. APExp HEADER CHANGES THIS TRANSLATION DEPENDS ON ------------------------------------------------ -The headers were STAGED (copied) and edited in the staging copy only. -NOTHING IN APExp's HEADER TREE WAS MODIFIED. To reproduce this -directory those edits have to be repeated, and they are all cases of -an APE header not being usable from C++: +At translation time the headers were STAGED (copied) and edited in the +staging copy only, and NOTHING IN APExp's HEADER TREE WAS MODIFIED. +Eight edits were needed, every one a case of an APE header not being +usable from C++. + +**ALL EIGHT ARE FIXED IN THE TREE NOW, so a re-translation needs NONE +of them** -- stage the headers as they stand. The list is kept +because it is the record of what a stricter compiler found, and +because each was fixed on its own evidence rather than to suit EDG. + +The last four, each a parameter name or a keyword, so none of them +changes what a C caller sees: sys/include/ape/stdlib.h:47,49,87 `_Noreturn` (a C11 keyword that does not exist in C++) used unguarded sys/include/ape/stdlib.h:69,70 parameter named `template` sys/include/ape/unistd.h:186,192 parameter named `new` - sys/include/ape/signal.h:132-135 `restrict` as a parameter name; + sys/include/ape/signal.h:161-164 `restrict` as a parameter name; two per prototype reads as a duplicate parameter name in C++ - sys/include/ape/signal.h:57 `signal()`'s handler parameter - declared `void (*)()` -- unprototyped -- where POSIX says - `void (*)(int)` - sys/include/ape/signal.h:16-18 SIG_DFL/SIG_ERR/SIG_IGN cast to - `void (*)()`, same defect as the declaration beside them - sys/include/ape/features.h:55 `#define hidden` -- musl's - internal visibility macro, in a PUBLIC header - sys/include/ape/bsd.h:47 `getopt(int, char**, char*)`, - non-const, where POSIX says `(int, char *const *, const char *)` + +And the first four, fixed earlier in the same session for their own +reasons. Verified against the tree rather than assumed: + + signal.h `signal()` is prototyped now -- + `extern void (*signal(int, void (*)(int)))(int)` at :86 + signal.h SIG_DFL/SIG_ERR/SIG_IGN are `(void (*)(int))` at :45-47; + they had to move with the declaration, since callers + compare the return value against them + features.h `#define hidden` is GONE from the public header -- it had + a measured victim in `sqlite3.h:10957`'s + `unsigned char hidden[48]` + bsd.h:53 `getopt(int, char * const [], const char *)`, POSIX's + spelling, agreeing with `` at last + +*That is the translation's own staging list working as a to-do list +for the HEADER TREE*: it was written as eight things EDG could not +use, and every one turned out to be a defect worth fixing on its own +evidence, found by a compiler stricter than gcc. + +The control is a before-and-after pair on IDENTICAL staging: a C++ +translation unit including , and +gives 12 errors before and 1 after. The same unit as C is 0 errors, +which is the half that could have cost the tree. + +THE SURVIVOR IS A NINTH ITEM THIS LIST NEVER NAMED: stddef.h:50 +typedefs `wchar_t', which is a BUILT-IN TYPE in C++. It is present +in both runs, so it is pre-existing rather than anything done here, +and it is recorded and not fixed. cpfe does not trip on it -- +`--no_standard_includes' plus EDG's own include_c99 is why -- so it +blocks nothing in this directory. + +Two of the four could not be fixed the obvious way. `#define +_Noreturn' or `#define restrict' under __cplusplus would put an +UNRESERVED name in a public APE header that external packages define +themselves: gnulib ships a whole `_Noreturn.h' and a dozen `config.h' +here define `restrict'. That is exactly the collision that broke +flex over `reject' one round earlier, so the spellings used are all +in the reserved double-underscore space. Three of the four need no +macro at all -- `restrict' becomes `__restrict', which kencc lexes to +the same LRESTRICT (cc/lex.c:1652,1678-1679), and the two parameters +are simply renamed. `__ape_template' is this directory's own +convention arriving back in the tree: the generated C already carries +it. One absolute include also had to be rewritten for a host compile: amd64/include/ape/stddef_arch.h's `#include "/sys/include/ape/..."`. Four others of the form `#include "/sys/include/..."` name native Plan 9 headers and are unreachable from EDG, so they were left. -These are reported as findings in their own right; see the round-2 -report. They are not EDG's problem and they are not fixed here. +The four that remain are reported as findings in their own right and +are not fixed here; they are not EDG's problem either. diff --git a/sys/src/external/edg/kencc_targ.h b/sys/src/external/edg/kencc_targ.h new file mode 100644 index 000000000..210067d82 --- /dev/null +++ b/sys/src/external/edg/kencc_targ.h @@ -0,0 +1,181 @@ +/* + * kencc_targ.h -- APExp target configuration for EDG's cpfe. + * + * NOT part of EDG. Supplied with -include so that it is seen before + * src/defines.h pulls in the generated cmake_defines.h, every entry of + * which is #ifndef-guarded. Nothing in the EDG tree is modified. + * + * Target: APExp/kencc on amd64 (6c/pcc). This is LLP64 -- the same + * integer model EDG already ships as its "win64" configuration, whose + * values in cmake_defines.h are quoted beside each line below. + */ + +#ifndef APEXP_KENCC_TARG_H +#define APEXP_KENCC_TARG_H + +/* + * Only for translation units that take defines.h's USE_CMAKE_DEFINES + * branch -- that is cpfe, and cpfe is the only thing whose target + * matters. The helper programs in util/ are compiled WITHOUT that + * define, so they take the legacy "#include defines_linux.h" path at + * defines.h:518, where the TARG_* macros are UNCONDITIONAL and a + * command-line definition only produces a redefinition warning that + * the header then wins. They are host programs here; leave them on + * the host's own configuration. + */ +#if defined(USE_CMAKE_DEFINES) + +/* ---- generated-code target -------------------------------------- * + * The round-1 build inferred GCC_IS_GENERATED_CODE_TARGET from + * __GNUC__ (targ_def.h:3505), i.e. from the compiler that built cpfe, + * and that is the sole gate on both __attribute__((__weak__)) sites in + * c_gen_be.c (8806, 11103). kencc is "a compiler for which we have no + * special handling", which is targ_def.h's own EDG_WIN32 #else arm. + */ +#define GCC_IS_GENERATED_CODE_TARGET 0 +#define CLANG_IS_GENERATED_CODE_TARGET 0 +#define SUN_IS_GENERATED_CODE_TARGET 0 +#define MSVC_IS_GENERATED_CODE_TARGET 0 +#define MICROSOFT_DIALECT_IS_GENERATED_CODE_TARGET 0 +#define C_GEN_BE_GENERATES_ANSI_C 1 + +/* ---- no COMDAT ---------------------------------------------------- * + * Clearing GCC_IS_GENERATED_CODE_TARGET above stops __weak__ being + * EMITTED, but by itself that only turns a kencc-unsupported attribute + * into a duplicate-definition link error: measured, two trivial TUs + * sharing one header collide on 10 symbols. + * + * host_envir.h:862 names the real axis -- + * LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS, whose own comment is + * "a simplified interpretation of this flag is: do we have COMDAT + * sections?". Plan 9's loaders do not. It is forced TRUE by + * IA64_ABI (host_envir.h:868), which the Linux configuration sets, so + * IA64_ABI is what has to go: that selects EDG's Cfront-like ABI, + * which is the no-COMDAT world this whole mechanism was built for. + * With IA64_ABI off, extern inline entities are routed through the + * template instantiation machinery instead of a COMDAT section + * (targ_def.h:4641-4686) and vtables/typeinfo follow the same path. + * + * ATTEMPTED AND BACKED OUT -- see the note at the end of this block. + * It is left here, disabled, because the wall it hits is the finding + * and re-deriving it would cost another round. + */ +#if defined(APEXP_TRY_CFRONT_ABI) +#define IA64_ABI 0 +#define LINKER_CAN_DISCARD_DUPLICATE_DEFINITIONS 0 +#define INSTANTIATE_EXTERN_INLINE 1 +#define INSTANTIATE_INLINE_VARIABLES 1 + +/* + * targ_def.h:648 defaults this to GNU_EXTENSIONS_ALLOWED, and + * targ_def.h:657 only permitted it to be off when IA64_ABI was off -- + * which it now is. kencc has no weak references, so lazy + * initialization must not be built on them. + */ +#define LAZY_INITIALIZATION_USES_WEAK_REFERENCES 0 + +/* + * Two consistency checks fire on IA64_ABI going off, and each names + * its own remedy; both are Cfront-ABI settings rather than choices: + * targ_def.h:357 TIE_DEFAULT_GNU_ABI_VERSION_TO_GNU_VERSION + * requires that IA64_ABI be TRUE + * targ_def.h:4603 HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS must + * be FALSE when IA64_ABI is FALSE + */ +#define TIE_DEFAULT_GNU_ABI_VERSION_TO_GNU_VERSION 0 +#define HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS 0 + +/* + * ...and then it stops, which is the thing to record. With the two + * above supplied, cpfe fails to COMPILE in src/target_map.h: + * + * target_map.h:106 error: 'TARG_ALIGNOF_PTR_TO_VIRTUAL_BASE_CLASS_linux_i686' + * was not declared in this scope + * target_map.h:302 error: 'TARG_RUNTIME_ELEM_COUNT_INT_KIND_linux_i686' + * target_map.h:338 error: 'TARG_SIZEOF_PTR_TO_VIRTUAL_BASE_CLASS_linux_i686' + * + * The Cfront ABI needs three target quantities the IA-64 ABI does not, + * and this build is MULTI-TARGET: the platform cmakedef + * (cmake/macro-conf/support/platform/linux-x86_64/base.cmakedef:14-38) + * declares TARGET_CONFIGURATION_1..7, and target.c instantiates the + * whole target map once per configuration, each needing a + * _ spelling. The generated cmake_defines.h carries + * those suffixed variants only for the macros reachable under + * IA64_ABI=1, which is what it was generated for. Setting + * EDG_CPP_RT_LIBS="" does NOT help: that list is separate from + * TARGET_CONFIGURATION_n. + * + * Two of the three are mechanical (targ_def.h:2837,2842 derive them + * from TARG_SIZEOF_POINTER / TARG_ALIGNOF_POINTER) but the suffixed + * spellings still have to be written out by hand for all seven + * secondary targets, and TARG_RUNTIME_ELEM_COUNT_INT_KIND has no + * derived default at all -- that one would be invented. + * + * So the Cfront ABI is reachable by REGENERATING the macro + * configuration for it, not by setting switches, and it is a large + * semantic change (mangling, ctor/dtor model, vtable layout) that + * wants its own round and its own validation. Not done here. + */ +#endif /* defined(APEXP_TRY_CFRONT_ABI) */ + +/* ---- integer model: LLP64 (= EDG's win64) ----------------------- */ +#define TARG_LITTLE_ENDIAN 1 /* amd64 */ +#define TARG_CHAR_BIT 8 +#define TARG_HAS_SIGNED_CHARS 1 /* win64 1; APE's own + limits_generic.h:44,52 make + CHAR_MAX==SCHAR_MAX and + CHAR_MIN==SCHAR_MIN */ +#define TARG_SIZEOF_SHORT 2 +#define TARG_ALIGNOF_SHORT 2 +#define TARG_SIZEOF_INT 4 /* win64 4 */ +#define TARG_ALIGNOF_INT 4 +#define TARG_SIZEOF_LONG 4 /* win64 4 -- NOT 8; kencc long + is 32-bit on every target */ +#define TARG_ALIGNOF_LONG 4 /* win64 4 */ +#define TARG_SIZEOF_LONG_LONG 8 /* win64 8 */ +#define TARG_ALIGNOF_LONG_LONG 8 /* win64 8 */ +#define TARG_SIZEOF_POINTER 8 /* win64 8 */ +#define TARG_ALIGNOF_POINTER 8 /* win64 8 */ + +/* ---- floating point --------------------------------------------- * + * kencc has no extended precision: cc/sub.c's simplet() maps + * BDOUBLE|BLONG to types[TDOUBLE], so long double IS double. + * EDG's win64 says 8 for the same reason (MSVC does the same). + * targ_def.h:3954 requires DOUBLE == LONG_DOUBLE in that case. + */ +#define TARG_SIZEOF_FLOAT 4 +#define TARG_ALIGNOF_FLOAT 4 +#define TARG_SIZEOF_DOUBLE 8 /* win64 8 */ +#define TARG_ALIGNOF_DOUBLE 8 /* win64 8 */ +#define TARG_SIZEOF_LONG_DOUBLE 8 /* win64 8 */ +#define TARG_ALIGNOF_LONG_DOUBLE 8 /* win64 8 */ + +/* + * The SIZE alone is not enough: floating.h:216 cross-checks it against + * the long double FORMAT, and cmake_defines.h:166 asserts the host's + * 80-bit extended. Saying 8 bytes while the format says 80 bits is + * "long double type is mis-configured", which is the check doing its + * job. binary64 is the format that matches kencc's long-double-is- + * double, and it is one of the three floating.h already names. + */ +#define FP_LONG_DOUBLE_IS_BINARY64 1 +#define FP_LONG_DOUBLE_IS_80BIT_EXTENDED 0 +#define FP_LONG_DOUBLE_IS_BINARY128 0 + +/* ---- derived library types -------------------------------------- * + * Read from APE's own headers rather than inferred: + * amd64/include/ape/stddef_arch.h:4,10,14 + * _ptrdiff_t = long long, size_t = unsigned long long, + * ssize_t = long long + * sys/include/ape/stddef.h:50 wchar_t = unsigned int + * The first three are exactly win64's kinds; wchar_t is not + * (win64 uses unsigned short), which is the one place APExp and + * EDG's LLP64 configuration differ. + */ +#define TARG_SIZE_T_INT_KIND ((an_integer_kind)ik_unsigned_long_long) +#define TARG_SSIZE_T_INT_KIND ((an_integer_kind)ik_long_long) +#define TARG_PTRDIFF_T_INT_KIND ((an_integer_kind)ik_long_long) +#define TARG_WCHAR_T_INT_KIND ((an_integer_kind)ik_unsigned_int) + +#endif /* defined(USE_CMAKE_DEFINES) */ +#endif /* APEXP_KENCC_TARG_H */