Compare commits

...
325 Commits
Author SHA1 Message Date
Justine Tunney 17a85e4790 Release Cosmopolitan v3.9.3 2024-10-08 19:58:32 -07:00
Justine Tunney ad11fc32ad Avoid an --ftrace crash on Windows 2024-10-07 18:39:25 -07:00
Justine Tunney dcf9596620 Make more fixups and quality assurance 2024-10-07 15:29:53 -07:00
Justine Tunney 85c58be942 Fix an async signal delivery flake on Windows 2024-10-02 04:55:06 -07:00
Justine Tunney e4d6eb382a Make memchr() and memccpy() faster 2024-09-30 05:54:34 -07:00
Justine Tunney fef24d622a Work around copy_file_range() bug in eCryptFs
When programs like ar.ape and compile.ape are run on eCryptFs partitions
on Linux, copy_file_range() will fail with EINVAL which is wrong because
eCryptFs which doesn't support this system call, should raise EOPNOTSUPP

See https://github.com/jart/cosmopolitan/discussions/1305
2024-09-29 16:35:38 -07:00
Justine Tunney 12cc2de22e Make contended mutexes 30% faster on aarch64
On Raspberry Pi 5, benchmark_mu_contended takes 359µs in *NSYNC upstream
and in Cosmopolitan it takes 272µs.
2024-09-26 09:24:25 -07:00
Justine Tunney 70603fa6ea Fix makedev() prototype
Fixes #1281
2024-09-26 04:42:41 -07:00
Justine Tunney 9255113011 Delete some magic numbers 2024-09-26 04:27:51 -07:00
Gabriel Ravier 333c3d1f0a Add the uppercase B conversion specifier to printf (#1300)
The (uppercase) B conversion specifier is specified by the C standard to
have the same behavior as the (lowercase) b conversion specifier, except
that whenever the # flag is used, the (uppercase) B conversion specifier
alters a nonzero result by prefixing it with "0B", instead of with "0b".

This commit adds this conversion specifier alongside a few tests for it.
2024-09-26 04:27:45 -07:00
Justine Tunney 518eabadf5 Further optimize poll() on Windows 2024-09-22 22:28:59 -07:00
Justine Tunney 556a294363 Improve Windows mode bits
We were too zealous about security before by only setting the owner bits
and that would cause issues for projects like redbean that check "other"
bits to determine if it's safe to serve a file. Since that doesn't exist
on Windows, it's better to have things work than not work. So what we'll
do instead is return modes like 0664 for files and 0775 for directories.
2024-09-22 16:51:57 -07:00
Justine Tunney 80804ccfff Upgrade to cosmocc v3.9.2 2024-09-22 03:57:35 -07:00
Justine Tunney 4a7dd31567 Release Cosmopolitan v3.9.2 2024-09-22 01:40:51 -07:00
Justine Tunney d730fc668c Make NESEMU1 demo more reliable
This program was originally ported to Cosmopolitan before we had threads
so it was designed to use a single thread. That caused issues for people
with slower computers, like an Intel Core i5, where Gyarados would go so
slow that the audio would skip. I would also get audio skipping when the
terminal was put in full screen mode. Now we use two threads and smarter
timing, so NESEMU1 should go reliably fast on everyone's computer today.
2024-09-22 01:21:10 -07:00
Justine Tunney e975245102 Upgrade to superconfigure z0.0.56 2024-09-22 01:21:10 -07:00
Justine Tunney 126a44dc49 Write more tests attempting to break windows
This time I haven't succeeded in breaking anything which is a good sign.
2024-09-22 01:21:10 -07:00
Gabriel Ravier 476926790a Make printf %La test-case work properly on AArch64 (#1298)
As the size of long double changes between x86 and AArch64, this results
in one of the printf a conversion specifier test-cases getting different
output between the two. Note that both outputs (and a few more) are 100%
standards-conforming, but the testcase currently only expects a specific
one - the one that had been seen on x86 when initially writing the test.

This patch fixes the testcase so it accepts either of those two outputs.
2024-09-22 01:21:03 -07:00
Justine Tunney dd8c4dbd7d Write more tests for signal handling
There's now a much stronger level of assurance that signaling on Windows
will be atomic, low-latency, low tail latency, and shall never deadlock.
2024-09-21 05:24:56 -07:00
Justine Tunney 0e59afb403 Fix conflicting RTTI related symbol 2024-09-19 20:34:43 -07:00
Justine Tunney f68fc1f815 Put more thought into new signaling code 2024-09-19 20:21:33 -07:00
Justine Tunney 6107eb38f9 Fix m=tinylinux build 2024-09-19 04:25:34 -07:00
Justine Tunney d50f4c02f6 Make revision to previous change 2024-09-19 03:29:39 -07:00
Justine Tunney 0d74673213 Introduce interprocess signaling on Windows
This change gets rsync working without any warning or errors. On Windows
we now create a bunch of C:\var\sig\x\y.pid shared memory files, so sigs
can be delivered between processes. WinMain() creates this file when the
process starts. If the program links signaling system calls then we make
a thread at startup too, which allows asynchronous delivery each quantum
and cancelation points can spot these signals potentially faster on wait

See #1240
2024-09-19 03:02:13 -07:00
Justine Tunney 8527462b95 Fix ECHILD with WNOHANG on Windows
This change along with a patch for rsync's safe_write() function that'll
that'll soon be added to superconfigure, gets rsync working. There's one
remaining issue (which isn't a blocker) which is how rsync logs an error
about abnormal process termination since there's currently no way for us
to send non-fatal signals between processes. rsync in cosmos is restored

Fixes #1240
2024-09-18 23:26:02 -07:00
Justine Tunney 8313dca982 Show file descriptors on crash on Windows 2024-09-18 21:53:09 -07:00
Justine Tunney 87a6669900 Make more Windows socket fixes and improvements
This change makes send() / sendto() always block on Windows. It's needed
because poll(POLLOUT) doesn't guarantee a socket is immediately writable
on Windows, and it caused rsync to fail because it made that assumption.
The only exception is when a SO_SNDTIMEO is specified which will EAGAIN.

Tests are added confirming MSG_WAITALL and MSG_NOSIGNAL work as expected
on all our supported OSes. Most of the platform-specific MSG_FOO magnums
have been deleted, with the exception of MSG_FASTOPEN. Your --strace log
will now show MSG_FOO flags as symbols rather than numbers.

I've also removed cv_wait_example_test because it's 0.3% flaky with Qemu
under system load since it depends on a process being readily scheduled.
2024-09-18 20:29:42 -07:00
Justine Tunney ce2fbf9325 Write network audio programs 2024-09-18 17:17:02 -07:00
Steven Dee (Jōshin) 1bfb348403 Add weak self make_shared variant (#1299)
This extends the CTL version of make_shared with functionality not found
in the STL, with inspiration taken from Rust's Rc class.
2024-09-17 15:46:23 -07:00
Justine Tunney aaed879ec7 Release Cosmopolitan v3.9.1 2024-09-17 02:55:07 -07:00
Justine Tunney 8201ef2b3d Fix regression in package.ape build tool 2024-09-17 02:54:17 -07:00
Justine Tunney b1c9801897 Support more TCP socket options on Windows 2024-09-17 02:46:05 -07:00
Justine Tunney f7754ab608 Fix strace result code for recv() 2024-09-17 02:16:56 -07:00
Justine Tunney 96abe91c29 Reveal another Qemu bug 2024-09-17 01:31:55 -07:00
Justine Tunney bb7942e557 Improve socket option story 2024-09-17 01:17:07 -07:00
Justine Tunney b14dddcc18 Emulate Linux socket timeout signaling on Windows 2024-09-17 00:24:08 -07:00
Justine Tunney 65e425fbca Slightly optimize iovec on Windows 2024-09-16 21:36:22 -07:00
Justine Tunney 774c67fcd3 Make send() block in non-blocking mode 2024-09-16 21:09:28 -07:00
Justine Tunney 3c58ecd00c Fix bug with send() on Windows in O_NONBLOCK mode
There is a bug in WIN32 where using CancelIoEx() on an overlapped i/o op
initiated by WSASend() will cause WSAGetOverlappedResult() to report the
operation failed when it actually succeeded. We now work around that, by
having send and sendto initially consult WSAPoll() on O_NONBLOCK sockets
2024-09-16 20:49:58 -07:00
Justine Tunney 5aa970bc4e Fix strace logging of ipv6 port 2024-09-16 02:19:17 -07:00
Justine Tunney 56ca00b022 Release Cosmopolitan v3.9.0 2024-09-15 22:39:09 -07:00
Justine Tunney ecbf453464 Upgrade to superconfigure z0.0.55 2024-09-15 22:29:49 -07:00
Justine Tunney c3482af66d Fix file descriptor assignment issues on Windows 2024-09-15 22:16:38 -07:00
Justine Tunney b73673e984 Freshen bootstrap binaries 2024-09-15 20:37:32 -07:00
Gabriel Ravier e260d90096 Fix 0 before decimal-point in hex float printf fns (#1297)
The C standard specifies that, upon handling the a conversion specifier,
the argument is converted to a string in which "there is one hexadecimal
digit (which is nonzero [...]) before the decimal-point character", this
being a requirement which cosmopolitan does not currently always handle,
sometimes printing numbers like "0x0.1p+5", where a correct output would
have been e.g. "0x1.0p+1" (despite both representing the same value, the
first one illegally has a '0' digit before the decimal-point character).
2024-09-15 18:02:47 -07:00
Gabriel Ravier 81bc8d0963 Fix printing decimal-point character on printf %#a (#1296)
The C standard indicates that when processing the a conversion specifier
"if the precision is zero *and* the # flag is not specified, no decimal-
point character appears.". This means that __fmt needs to ensure that it
prints the decimal-point character not only when the precision is non-0,
but also when the # flag is specified - cosmopolitan currently does not.

This patch fixes this, along with adding a few tests for this behaviour.
2024-09-15 16:42:51 -07:00
Steven Dee (Jōshin) ef62730ae4 Enable STL-style enable_shared_from_this (#1295) 2024-09-15 16:32:13 -07:00
mierenhoop 6397999fca Fix unicode look-alike in define (#1294) 2024-09-15 12:13:25 -07:00
Gabriel Ravier b55e4d61a9 Hopefully completely fix printf-family %a rounding (#1287)
The a conversion specifier to printf had some issues w.r.t. rounding, in
particular in edge cases w.r.t. "to nearest, ties to even" rounding (for
instance, "%.1a" with 0x1.78p+4 outputted 0x1.7p+4 instead of 0x1.8p+4).

This patch fixes this and adds several tests w.r.t ties to even rounding
2024-09-15 12:11:27 -07:00
Justine Tunney e65fe614b7 Fix shocking memory leak on Windows
Spawning processes would leak lots of memory, due to a missing free call
in ntspawn(). Our tooling never caught this since ntspawn() must use the
WIN32 memory allocator. It means every time posix_spawn, fork, or execve
got called, we would leak 162kb of memory. I'm proud to say that's fixed
2024-09-15 04:32:39 -07:00
Justine Tunney 949c398327 Clean up more code 2024-09-15 02:45:16 -07:00
Justine Tunney baf70af780 Make read() and write() signal handling atomic
You would think this is an important bug fix, but unfortunately all UNIX
implementations I've evaluated have a bug in read that causes signals to
not be handled atomically. The only exception is the latest iteration of
Cosmopolitan's read/write polyfill on Windows, which is somewhat ironic.
2024-09-15 01:18:27 -07:00
Justine Tunney c260144843 Introduce sigtimedwait() on Windows 2024-09-15 01:18:27 -07:00
Steven Dee (Jōshin) 37e2660c7f make_shared should work with nontrivial objects (#1293) 2024-09-15 01:18:19 -07:00
Gabriel Ravier 675abfa029 Add POSIX's apostrophe flag for printf-based funcs (#1285)
POSIX specifies the <apostrophe> flag character for printf as formatting
decimal conversions with the thousands' grouping characters specified by
the current locale. Given that cosmopolitan currently has no support for
obtaining the locale's grouping character, all that is required (when in
the C/POSIX locale) for supporting this flag is ignoring it, and as it's
already used to indicate quoting (for non-decimal conversions), all that
has to be done is to avoid having it be an alias for the <space> flag so
that decimal conversions don't accidentally behave as though the <space>
flag has also been specified whenever the <apostrophe> flag is utilized.

This patch adds this flag, as described above, along with a test for it.
2024-09-14 17:17:40 -07:00
Gabriel Ravier e3d28de8a6 Fix UB in gdtoa hexadecimal float scanf and strtod (#1288)
When reading hexadecimal floats, cosmopolitan would previously sometimes
print a number of warnings relating to undefined behavior on left shift:

third_party/gdtoa/gethex.c:172: ubsan warning: signed left shift changed
sign bit or overflowed 12 'int' 28 'int' is undefined behavior

This is because gdtoa assumes left shifts are safe when overflow happens
even on signed integers - this is false: the C standard considers it UB.
This is easy to fix, by simply casting the shifted value to unsigned, as
doing so does not change the value or the semantics of the left shifting
(except for avoiding the undefined behavior, as the C standard specifies
that unsigned overflow yields wraparound, avoiding undefined behaviour).

This commit does this, and adds a testcase that previously triggered UB.
(this also adds test macros to test for exact float equality, instead of
the existing {EXPECT,ASSERT}_FLOAT_EQ macros which only tests inputs for
being "almost equal" (with a significant epsilon) whereas exact equality
makes more sense for certain things such as reading floats from strings,
and modifies other testcases for sscanf/fscanf of floats to utilize it).
2024-09-14 17:11:04 -07:00
Gabriel Ravier 7f21547122 Fix occasional crash in test/libc/intrin/mmap_test (#1289)
This test would sometimes crash due to the EZBENCH2() macro occasionally
running the first benchmark (BenchMmapPrivate()) less times than it does
the second benchmark (BenchUnmap()) - this would then lead to a crash in
BenchUnmap() because BenchUnmap() expects that BenchMmapPrivate() has to
previously have been called at least as many times as it has itself such
that a region of memory has been mapped, for BenchUnmap() to then unmap.

This commit fixes this by utilizing the newer BENCHMARK() macro (instead
of the EZBENCH2() macro) which runs the benchmark using an count of runs
specified directly by the benchmark itself, which allows us to make sure
that the two benchmark functions get ran the exact same amount of times.
2024-09-14 17:07:56 -07:00
Gabriel Ravier 19563d37c1 Make the pledge sandbox .so object work with UBSAN (#1290)
Currently, cosmopolitan's pledge sandbox .so shared object wrongly tries
to use a bunch of UBSAN symbols, which are not defined when outside of a
cosmopolitan-based context (save if the sandboxed binary also happens to
be itself using UBSAN, but that's obviously very commonly not the case).

Fix this by making it such that the sandbox .so shared object traps when
UBSAN is triggered, avoiding any attempt to call into the UBSAN runtime.
2024-09-14 17:07:04 -07:00
Justine Tunney ed1f992cb7 Fix default open mode in redbean unix.open() 2024-09-14 00:10:21 -07:00
Gabriel Ravier 7d2c363963 Fix statx not being allowed on rpath/wpath pledges (#1291)
While always blocking statx did not lead to particularly bad results for
most cases (most code that uses statx appears to utilize a fallback when
statx is unavailable), it does lead to using usually far less used (thus
far less well tested) code: for example, musl's current fstatat fallback
for statx fails to set any values for stx_rdev_major and stx_rdev_minor,
which the raw syscall wouldn't (I've have sent a patch to musl for this,
but this won't fix older versions of musl and binaries/OSes using them).
Along with the fact that statx extends stat in several useful ways, this
seems to indicate it is far better to simply allow statx whenever pledge
also allows stat-family syscalls, i.e. for both rpath and wpath pledges.
2024-09-13 14:31:29 -07:00
Justine Tunney 462ba6909e Speed up unnamed POSIX semaphores
When sem_wait() used its futexes it would always use process shared mode
which can be problematic on platforms like Windows, where that causes it
to use the slow futex polyfill. Now when sem_init() is called in private
mode that'll be passed along so we can use a faster WaitOnAddress() call
2024-09-13 06:25:27 -07:00
Justine Tunney b5fcb59a85 Implement more bf16/fp16 compiler runtimes
Fixes #1259
2024-09-13 05:06:34 -07:00
Justine Tunney 6b10f4d0b6 Fix ioctl() and FIONREAD for sockets on Windows
This change fixes an issue where using FIONREAD would cause control flow
to jump to null, due to a _weaken() reference that I refactored long ago
2024-09-13 01:47:33 -07:00
Justine Tunney 1260f9d0ed Add more tests for strlcpy()
I asked ChatGPT o1 for an optimized version of strlcpy() but it couldn't
produce an implementation that didn't crash. Eventually it just gave up.
2024-09-13 01:14:35 -07:00
Justine Tunney e142124730 Rewrite Windows connect()
Our old code wasn't working with projects like Qt that call connect() in
O_NONBLOCK mode multiple times. This change overhauls connect() to use a
simpler WSAConnect() API and follows the same pattern as cosmo accept().
This change also reduces the binary footprint of read(), which no longer
needs to depend on our enormous clock_gettime() function.
2024-09-12 23:07:52 -07:00
Justine Tunney 5469202ea8 Get monorepo fully building on Windows again
The mkdeps tool was failing, because it used a clever mmap() hack that's
no longer supported. I've also removed tinymalloc.inc from build tooling
because Windows doesn't like the way it uses overcommit memory. Sadly it
means our build tool binaries will be larger. It's less of an issue, now
that we are no longer putting build tool binaries in the git repository.
2024-09-12 05:07:21 -07:00
Justine Tunney acd6c32184 Rewrite Windows accept()
This change should fix the Windows issues Qt Creator has been having, by
ensuring accept() and accept4() work in O_NONBLOCK mode. I switched away
from AcceptEx() which is buggy, back to using WSAAccept(). This requires
making a tradeoff where we have to accept a busy loop. However it is low
latency in nature, just like our new and improved Windows poll() code. I
was furthermore able to eliminate a bunch of Windows-related test todos.
2024-09-12 04:23:38 -07:00
Justine Tunney 6f868fe1de Fix polling of files on Windows 2024-09-11 17:13:23 -07:00
Justine Tunney 0f3457c172 Add debug log to cosmoaudio and add examples 2024-09-11 03:49:29 -07:00
Justine Tunney a5c0189bf6 Make vim startup faster
It appears that GetFileAttributes(u"\\etc\\passwd") can take two seconds
on Windows 10 at unpredictable times for reasons which are mysterious to
me. Let's try avoiding that path entirely and pray to Microsoft it works
2024-09-11 00:52:34 -07:00
Justine Tunney deb5e07b5a Remove exponential backoff from chdir()
This issue probably only impacted the earliest releases of Windows 7 and
we only support Windows 10+ these days, so it's not worth adding 2000 ms
of startup latency to vim when ~/.vim doesn't exist.
2024-09-10 21:21:52 -07:00
Gabriel Ravier 4d05060aac Partially fix printf hex float numbers/%a rounding (#1286)
Hexadecimal printing of floating-point numbers in cosmopolitan (that is,
using the the conversion specifier) is improved to have correct rounding
of results in rounding modes other than the default one (ie. FE_NEAREST)

This commit fixes that, and adds tests for the change (note that there's
still some rounding issues with the a conversion specifier in general in
relatively rare cases (that is without non-default rounding modes) where
I've left commented-out tests for anyone interested in improving it more
2024-09-10 20:42:52 -07:00
jeromew 51c0f44d1c Fix rare corner case in ntspawn.c (#1284)
This change fixes a CreateProcess failure when a process is spawned with
no handles inherited. This is due to violating a common design rule in C
that works as follows: when you have (ptr, size) the ptr must be ignored
when size is zero. That's because cosmo's malloc(0) always returns a non
null pointer, which was happening in __describe_fds(), but ntspawn() was
basing its decision off the nullness of the pointer rather than its size
2024-09-10 20:17:26 -07:00
Justine Tunney fbdf9d028c Rewrite Windows poll()
We can now await signals, files, pipes, and console simultaneously. This
change also gives a deeper review and testing to changes made yesterday.
2024-09-10 20:04:02 -07:00
Justine Tunney cceddd21b2 Reduce latency of poll() on Windows
When polling sockets poll() can now let you know about an event in about
10µs rather than 10ms. If you're not polling sockets then poll() reports
console events now in microseconds instead of milliseconds.
2024-09-10 04:12:21 -07:00
Justine Tunney a0a404a431 Fix issues with previous commit 2024-09-10 01:59:46 -07:00
Justine Tunney 2f48a02b44 Make recursive mutexes faster
Recursive mutexes now go as fast as normal mutexes. The tradeoff is they
are no longer safe to use in signal handlers. However you can still have
signal safe mutexes if you set your mutex to both recursive and pshared.
You can also make functions that use recursive mutexes signal safe using
sigprocmask to ensure recursion doesn't happen due to any signal handler

The impact of this change is that, on Windows, many functions which edit
the file descriptor table rely on recursive mutexes, e.g. open(). If you
develop your app so it uses pread() and pwrite() then your app should go
very fast when performing a heavily multithreaded and contended workload

For example, when scaling to 40+ cores, *NSYNC mutexes can go as much as
1000x faster (in CPU time) than the naive recursive lock implementation.
Now recursive will use *NSYNC under the hood when it's possible to do so
2024-09-10 00:08:59 -07:00
Justine Tunney 58d252f3db Support more keystrokes in DECCKM mode 2024-09-09 20:01:52 -07:00
Justine Tunney 95fee8614d Test recursive mutex code more 2024-09-09 00:19:23 -07:00
Justine Tunney d50d954a3c Remove callback from cosmoaudio API
Using callbacks is still problematic with cosmo_dlopen() due to the need
to restore the TLS register. So using callbacks is even more strict than
using signal handlers. We are better off introducing a cosmoaudio_poll()
function. It makes the API more UNIX-like. How bad could the latency be?
2024-09-08 19:47:14 -07:00
Justine Tunney d99f066114 Add clang-format to cosmocc toolchain
The clang-format binary is only 6mb so how can we resist?
2024-09-07 18:26:36 -07:00
Gabriel Ravier 4754f200ee Fix printf-family long double prec/rounding issues (#1283)
Currently, in cosmopolitan, there is no handling of the current rounding
mode for long double conversions, such that round-to-nearest gets always
used, regardless of the current rounding mode. %Le also improperly calls
gdtoa with a too small precision (which led to relatively similar bugs).

This patch fixes these issues, in particular by modifying the FPI object
passed to gdtoa such that it is modifiable (so that __fmt can adjust its
rounding field to correspond to FLT_ROUNDS (note that this is not needed
for dtoa, which checks FLT_ROUNDS directly)) and ors STRTOG_Neg into the
kind field in both of the __fmt_dfpbits and __fmt_ldfpbits functions, as
the gdtoa function also depends on it to be able to accurately round any
negative arguments. The change to kind also requires a few other changes
to make sure kind's upper bits (which include STRTOG_Neg) are masked off
when attempting to only examine the lower bits' value. Furthermore, this
patch also makes exactly one change in gdtoa, which appears to be needed
to fix rounding issues with FE_TOWARDZERO (this seems like a gdtoa bug).

The patch also adds a few tests for these issues, along with also taking
the opportunity to clean up some of the previous tests to do the asserts
in the right order (i.e. with the first argument as the expected result,
and the second one being used as the value that it is compared against).
2024-09-07 18:26:04 -07:00
Gabriel Ravier f882887178 Fix ecvt/fcvt issues w.r.t. value==0 and ndigit==0 (#1282)
Before this commit, cosmopolitan had some issues with handling arguments
of 0 and signs, such as returning an incorrect sign when the input value
== -0.0, and incorrectly handling ndigit == 0 on fcvt (ndigit determines
the amount of digits *after* the radix character on fcvt, thus the parts
before it still must be outputted before fcvt's job is completely done).

This patch fixes these issues, and adds tests with corresponding inputs.
2024-09-07 18:08:11 -07:00
Justine Tunney dc579b79cd Productionize polished cosmoaudio library
This change introduces comsoaudio v1. We're using a new strategy when it
comes to dynamic linking of dso files and building miniaudio device code
which I think will be fast and stable in the long run. You now have your
choice of reading/writing to the internal ring buffer abstraction or you
can specify a device-driven callback function instead. It's now possible
to not open the microphone when you don't need it since touching the mic
causes security popups to happen. The DLL is now built statically, so it
only needs to depend on kernel32. Our NES terminal emulator now uses the
cosmoaudio library and is confirmed to be working on Windows, Mac, Linux
2024-09-07 06:14:09 -07:00
Gabriel Ravier c66abd7260 Implement length modifiers for printf %n conv spec (#1278)
The C Standard specifies that, when a conversion specification specifies
a conversion specifier of n, the type of the passed pointer is specified
by the length modifier (if any), i.e. that e.g. the argument for %hhn is
of type signed char *, but Cosmopolitan currently does not handle this -
instead always simply assuming that the pointer always points to an int.

This patch implements, and tests, length modifiers with the n conversion
specifier, with the tests testing all of the available length modifiers.
2024-09-06 19:34:24 -07:00
Justine Tunney d1157d471f Upgrade pl_mpeg
This change gets printvideo working on aarch64. Performance improvements
have been introduced for magikarp decimation on aarch64. The last of the
old portable x86 intrinsics library is gone, but it still lives in Blink
2024-09-06 19:10:34 -07:00
Justine Tunney 5d3b91d8b9 Get printvideo audio working on Windows and MacOS 2024-09-06 06:48:55 -07:00
Justine Tunney 07fde68d52 Fix Windows console poll() copy/paste regression 2024-09-05 21:12:48 -07:00
Justine Tunney 41fc76c2b8 Fix apelink reproducible deterministic build bug
Thank you @dinosaure for reporting this issue and doing all the analysis
that made this simple and easy to fix. Be sure to check out his projects
like: https://github.com/dinosaure/esperanto, which lets you build OCaml
programs as Actually Portable Executables using cosmocc.

See https://github.com/jart/cosmopolitan/discussions/1265
2024-09-05 19:37:51 -07:00
Justine Tunney 1e9902af8b Support merging many .a files into one .a file 2024-09-05 19:28:14 -07:00
Justine Tunney df04ab846a Fix superconfigure build error 2024-09-05 16:29:13 -07:00
Justine Tunney 0d6ff04b87 Avoid potential build error 2024-09-05 16:11:03 -07:00
Justine Tunney 03875beadb Add missing ICANON features 2024-09-05 03:17:19 -07:00
Justine Tunney dd8544c3bd Delve into clock rabbit hole
The worst issue I had with consts.sh for clock_gettime is how it defined
too many clocks. So I looked into these clocks all day to figure out how
how they overlap in functionality. I discovered counter-intuitive things
such as how CLOCK_MONOTONIC should be CLOCK_UPTIME on MacOS and BSD, and
that CLOCK_BOOTTIME should be CLOCK_MONOTONIC on MacOS / BSD. Windows 10
also has some incredible new APIs, that let us simplify clock_gettime().

  - Linux CLOCK_REALTIME         -> GetSystemTimePreciseAsFileTime()
  - Linux CLOCK_MONOTONIC        -> QueryUnbiasedInterruptTimePrecise()
  - Linux CLOCK_MONOTONIC_RAW    -> QueryUnbiasedInterruptTimePrecise()
  - Linux CLOCK_REALTIME_COARSE  -> GetSystemTimeAsFileTime()
  - Linux CLOCK_MONOTONIC_COARSE -> QueryUnbiasedInterruptTime()
  - Linux CLOCK_BOOTTIME         -> QueryInterruptTimePrecise()

Documentation on the clock crew has been added to clock_gettime() in the
docstring and in redbean's documentation too. You can read that to learn
interesting facts about eight essential clocks that survived this purge.
This is original research you will not find on Google, OpenAI, or Claude

I've tested this change by porting *NSYNC to become fully clock agnostic
since it has extensive tests for spotting irregularities in time. I have
also included these tests in the default build so they no longer need to
be run manually. Both CLOCK_REALTIME and CLOCK_MONOTONIC are good across
the entire amd64 and arm64 test fleets.
2024-09-04 01:32:46 -07:00
Gabriel Ravier 8f8145105c Add POSIX's C conversion specifier to printf funcs (#1276)
POSIX specifies the C conversion specifier as being "equivalent to %lc",
i.e. printf("%C", arg) is equivalent in behaviour to printf("%lc", arg).

This patch implements this conversion specifier, and adds a test for it,
alongside another test, which ensures that va_arg uses the correct size,
even though we set signbit to 63 in the code (which one might think will
result in the wrong size of argument being va_arg-ed, but having signbit
set to 63 is in fact what __fmt_stoa expects and is a requirement for it
properly formatting the wchar_t argument - this does not result in wrong
usage of va_arg because the implementation of the c conversion specifier
(which the implementation of the C conversion specifier fallsthrough to)
always calls va_arg with an argument type of int, to avoid the very same
bug occuring with %lc, as the l length modifier also sets signbit to 63)
2024-09-03 00:33:55 -07:00
Justine Tunney 3c61a541bd Introduce pthread_condattr_setclock()
This is one of the few POSIX APIs that was missing. It lets you choose a
monotonic clock for your condition variables. This might improve perf on
some platforms. It might also grant more flexibility with NTP configs. I
know Qt is one project that believes it needs this. To introduce this, I
needed to change some the *NSYNC APIs, to support passing a clock param.
There's also new benchmarks, demonstrating Cosmopolitan's supremacy over
many libc implementations when it comes to mutex performance. Cygwin has
an alarmingly bad pthread_mutex_t implementation. It is so bad that they
would have been significantly better off if they'd used naive spinlocks.
2024-09-02 23:45:42 -07:00
Justine Tunney 79516bf08e Improve handling of weird reparse points
On Windows file system tools like `ls` would print errors when they find
things like WSL symlinks, which can't be read by WIN32. I don't know how
they got on my hard drive but this change ensures Cosmo will handle them
more gracefully. If a reparse point can't be followed, then fstatat will
return information about the link itself. If readlink encounters reparse
points that are WIN32 symlinks, then it'll log more helpful details when
using MODE=dbg (a.k.a. cosmocc -mdbg). Speaking of which, this change is
also going to help you troubleshoot locks; when you build your app using
the cosmocc -mdbg flag your --strace logs will now show lock acquisition
2024-09-02 19:05:48 -07:00
Justine Tunney 90460ceb3c Make Cosmo mutexes competitive with Apple Libc
While we have always licked glibc and musl libc on gnu/systemd sadly the
Apple Libc implementation of pthread_mutex_t is better than ours. It may
be due to how the XNU kernel and M2 microprocessor are in league when it
comes to scheduling processes and the NSYNC behavior is being penalized.
We can solve this by leaning more heavily on ulock using Drepper's algo.
It's kind of ironic that Linux's official mutexes work terribly on Linux
but almost as good as Apple Libc if used on MacOS.
2024-09-02 19:03:11 -07:00
Justine Tunney 2ec413b5a9 Fix bugs in poll(), select(), ppoll(), and pselect()
poll() and select() now delegate to ppoll() and pselect() for assurances
that both polyfill implementations are correct and well-tested. Poll now
polyfills XNU and BSD quirks re: the hanndling of POLLNVAL and the other
similar status flags. This change resolves a misunderstanding concerning
how select(exceptfds) is intended to map to POLPRI. We now use E2BIG for
bouncing requests that exceed the 64 handle limit on Windows. With pipes
and consoles on Windows our poll impl will now report POLLHUP correctly.

Issues with Windows path generation have been fixed. For example, it was
problematic on Windows to say: posix_spawn_file_actions_addchdir_np("/")
due to the need to un-UNC paths in some additional places. Calling fstat
on UNC style volume path handles will now work. posix_spawn now supports
simulating the opening of /dev/null and other special paths on Windows.

Cosmopolitan no longer defines epoll(). I think wepoll is a nice project
for using epoll() on Windows socket handles. However we need generalized
file descriptor support to make epoll() for Windows work well enough for
inclusion in a C library. It's also not worth having epoll() if we can't
get it to work on XNU and BSD OSes which provide different abstractions.
Even epoll() on Linux isn't that great of an abstraction since it's full
of footguns. Last time I tried to get it to be useful I had little luck.
Considering how long it took to get poll() and select() to be consistent
across platforms, we really have no business claiming to have epoll too.
While it'd be nice to have fully implemented, the only software that use
epoll() are event i/o libraries used by things like nodejs. Event i/o is
not the best paradigm for handling i/o; threads make so much more sense.
2024-09-02 00:29:52 -07:00
Justine Tunney 39e7f24947 Fix handling of paths with dirfd on Windows
This change fixes an issue with all system calls ending with *at(), when
the caller passes `dirfd != AT_FDCWD` and an absolute path. It's because
the old code was turning paths like C:\bin\ls into \\C:\bin\ls\C:\bin\ls
after being converted from paths like /C/bin/ls. I noticed this when the
Emacs dired mode stopped working. It's unclear if it's a regression with
Cosmopolitan Libc or if this was introduced by the Emacs v29 upgrade. It
also impacted posix_spawn() for which a newly minted example now exists.
2024-09-01 17:52:30 -07:00
Gabriel Ravier a089c07ddc Fix printf funcs on memory pressure with floats (#1275)
Cosmopolitan's printf-family functions will currently crash if one tries
formatting a floating point number with a larger precision (large enough
that gdtoa attempts to allocate memory to format the number) while under
memory pressure (i.e. when malloc fails) because gdtoa fails to check if
malloc fails.

The added tests (which would previously crash under cosmopolitan without
this patch) show how to reproduce the issue.

This patch fixes this, and adds the aforementioned tests.
2024-09-01 14:42:14 -07:00
Steven Dee (Jōshin) ae57fa2c4e Fix shared_ptr::owner_before (#1274)
This method is supposed to give equivalence iff two shared pointers both
own the same object, even if they point to different addresses. We can't
control the exact order of the control blocks in memory, so the test can
only check that this equivalence/non-equivalence relationship holds, and
this is in fact all that it should check.
2024-09-01 17:34:39 -04:00
Steven Dee (Jōshin) 48b703b3f6 Minor cleanup/improvements in unique_ptr_test (#1266)
I'd previously introduced a bunch of small wrappers around the class and
functions under test to avoid excessive cpp use, but we can achieve this
more expediently with simple using-declarations. This also cuts out some
over-specified tests (e.g. there's no reason a stateful deleter wouldn't
compile.)
2024-09-01 13:47:30 -07:00
Steven Dee (Jōshin) 389d565d46 Use unsigned-signed conversion for refs test (#1272) 2024-09-01 13:45:11 -07:00
Gabriel Ravier 75e161b27b Fix printf-family functions on long double inf (#1273)
Cosmopolitan's printf-family functions currently very poorly handle
being passed a long double infinity.

For instance, a program such as:

```cpp
#include <stdio.h>

int main()
{
    printf("%f\n", 1.0 / 0.0);
    printf("%Lf\n", 1.0L / 0.0L);
    printf("%e\n", 1.0 / 0.0);
    printf("%Le\n", 1.0L / 0.0L);
    printf("%g\n", 1.0 / 0.0);
    printf("%Lg\n", 1.0L / 0.0L);
}
```

will currently output the following:

```
inf
0.000000[followed by 32763 more zeros]
inf
N.aN0000e-32769
inf
N.aNe-32769
```

when the correct expected output would be:

```
inf
inf
inf
inf
inf
inf
```

This patch fixes this, and adds tests for the behavior.
2024-09-01 13:10:48 -07:00
Justine Tunney cca0edd62b Make pthread mutex non-recursive 2024-09-01 02:05:17 -07:00
Justine Tunney 7c83f4abc8 Make improvements
- wcsstr() is now linearly complex
- strstr16() is now linearly complex
- strstr() is now vectorized on aarch64 (10x)
- strstr() now uses KMP on pathological cases
- memmem() is now vectorized on aarch64 (10x)
- memmem() now uses KMP on pathological cases
- Disable shared_ptr::owner_before until fixed
- Make iswlower(), iswupper() consistent with glibc
- Remove figure space from iswspace() implementation
- Include line and paragraph separator in iswcntrl()
- Use Musl wcwidth(), iswalpha(), iswpunct(), towlower(), towupper()
2024-09-01 01:27:47 -07:00
Steven Dee (Jōshin) e1528a71e2 Basic CTL shared_ptr implementation (#1267) 2024-08-31 14:00:56 -04:00
jeromew a6fe62cf13 Fix redbean OnLogLatency documentation (#1270)
The handler is called in the child worker process.
2024-08-31 10:13:14 -07:00
Justine Tunney c9152b6f14 Release Cosmopolitan v3.8.0
This change switches c++ exception handling from sjlj to standard dwarf.
It's needed because clang for aarch64 doesn't support sjlj. It turns out
that libunwind had a bare-metal configuration that made this easy to do.

This change gets the new experimental cosmocc -mclang flag in a state of
working so well that it can now be used to build all of llamafile and it
goes 3x faster in terms of build latency, without trading away any perf.

The int_fast16_t and int_fast32_t types are now always defined as 32-bit
in the interest of having more abi consistency between cosmocc -mgcc and
-mclang mode.
2024-08-30 20:14:07 -07:00
Justine Tunney 5b9862907c Delete superfluous function 2024-08-29 23:51:22 -07:00
Justine Tunney c2420860e6 Fix --ftrace 2024-08-29 23:51:05 -07:00
Gabriel Ravier 6baf6cdb10 Fix vfprintf and derived functions badly handling +/` flag conflict (#1269) 2024-08-29 19:07:05 -07:00
Gabriel Ravier 06a1193b4d Make it so the test harness closes fds up to 100 (#1268) 2024-08-29 16:12:53 -07:00
Justine Tunney 884d89235f Harden against aba problem 2024-08-26 20:01:55 -07:00
Justine Tunney 610c951f71 Fix the build 2024-08-26 16:44:05 -07:00
Justine Tunney 12ecaf8650 Modernize ipv4.games server
The server was originally written before I implemented support for POSIX
thread cancelation. We now use standard pthreads APIs instead of talking
directly to *NSYNC. This means we're no longer using *NSYNC notes, which
aren't as good as the POSIX thread cancelation support I added to *NSYNC
which was only made possible by making *NSYNC part of libc. I believe it
will solve a crash we observed recently with ipv4.games, courtesy of the
individual who goes by the hacker alias Lambro.
2024-08-26 16:05:23 -07:00
Justine Tunney 185e957696 Detect implicit function declarations
This was suppressed recently and it's the worst possible idea when doing
greenfield software development with C. I'm so sorry it slipped through.
If the C standards committee was smart they would change the standard so
that implicit int becomes implicit long. Then problems such as this will
never occur and we could even use traditional C safely if we wanted too.
2024-08-26 15:34:08 -07:00
Justine Tunney ebe1cbb1e3 Add crash proofing to ipv4.games server 2024-08-26 12:57:28 -07:00
Justine Tunney e7b586e7f8 Add preliminary support for cosmocc -mclang
C++ code compiles very slowly with cosmocc, possibly because we're using
LLVM LIBCXX with GCC, and LLVM doesn't work as hard to make GCC go fast.
Therefore, it should be possible, to ask cosmocc to favor Clang over GCC
under the hood. On llamafile, my intention's to use this to make certain
files, e.g. llama.cpp/common.cpp, go from taking 17 seconds to 5 seconds

This new -mclang flag isn't ready for production yet since there's still
the question of how to get Clang to generate SJLJ exception code. If you
use this, then it's recommended you also pass -fno-exceptions.

The tradeoff is we're adding a 121mb binary to the cosmocc distribution.
There are no plans as of yet to fully migrate to Clang since GCC is very
good and has always treated us well.
2024-08-26 12:33:35 -07:00
Justine Tunney 111ec9a989 Fix bug we added to *NSYNC a while ago
This is believed to fix a crash, that's possible in nsync_waiter_free_()
when you call pthread_cond_timedwait(), or nsync_cv_wait_with_deadline()
where an assertion can fail. Thanks ipv4.games for helping me find this!
2024-08-26 12:25:50 -07:00
Justine Tunney f3ce684aef Fix getpeername() bug on Windows
The WIN32 getpeername() function returns ENOTCONN when it uses connect()
the SOCK_NONBLOCK way. So we simply store the address, provided earlier.
2024-08-25 11:28:53 -07:00
Justine Tunney 908b7a82ca Add VSCode settings 2024-08-25 11:02:31 -07:00
Justine Tunney bb06230f1e Avoid linker conflicts on DescribeFoo symbols
These symbols belong to the user. It caused a confusing error for Blink.
2024-08-24 18:10:22 -07:00
Justine Tunney 38cc4b3c68 Get rid of some legacy code 2024-08-24 17:53:30 -07:00
Justine Tunney 37ca1badaf Make Emacs load 2x faster 2024-08-23 20:08:05 -07:00
Justine Tunney 1a9f82bc9f Romanize Hindi, Yiddish, Arabic, Cyrillic, etc. 2024-08-20 16:27:16 -07:00
Justine Tunney df1aee7ce5 Upgrade superconfigure and monorepo toolchain
See #1260
2024-08-20 08:46:21 -07:00
Justine Tunney 2d44142444 Get Meson builds working
See #917
2024-08-19 08:40:18 -07:00
Justine Tunney 4bbc16e2cc Add helpful error messages 2024-08-19 07:28:49 -07:00
Justine Tunney 863c704684 Add string similarity function 2024-08-17 16:45:07 -07:00
Justine Tunney 60e697f7b2 Move LoadZipArgs() to cosmo.h 2024-08-17 12:06:27 -07:00
Justine Tunney 4389f4709a Expose wmempcpy() to _GNU_SOURCE 2024-08-17 08:13:22 -07:00
Justine Tunney ca2c30c977 Release redbean v3.0.0 2024-08-17 06:45:35 -07:00
Justine Tunney eb6e96f036 Change InfoZIP to not auto-append .zip to pathname 2024-08-17 06:45:23 -07:00
Justine Tunney 77be460290 Make Windows REPLs great again 2024-08-17 06:32:10 -07:00
Justine Tunney 8e14b27749 Make fread() more consistent with glibc 2024-08-17 02:57:22 -07:00
Justine Tunney 1d532ba3f8 Disable some anti-Musl Lua tests 2024-08-17 02:20:08 -07:00
Justine Tunney b2a1811c01 Add missing pragma 2024-08-16 21:49:28 -07:00
Justine Tunney 2eda50929b Add stdfloat header
Fixes #1260
2024-08-16 21:38:00 -07:00
Justine Tunney 098638cc6c Fix pthread_kill_test flake on qemu 2024-08-16 21:18:26 -07:00
Justine Tunney 732554ce3a Release Cosmopolitan v3.7.1 2024-08-16 11:56:47 -07:00
Gavin Hayes 914d521090 Fix relative Windows path normalization (#1261)
Fixes #1223
2024-08-16 11:55:49 -07:00
Justine Tunney 11d9fb521d Make atomics faster on aarch64
This change implements the compiler runtime for ARM v8.1 ISE atomics and
gets rid of the mandatory -mno-outline-atomics flag. It can dramatically
speed things up, on newer ARM CPUs, as indicated by the changed lines in
test/libc/thread/footek_test.c. In llamafile dispatching on hwcap atomic
also shaved microseconds off synchronization barriers.
2024-08-16 11:14:46 -07:00
Justine Tunney de0cde8def Release Cosmopolitan v3.7.0 2024-08-16 07:43:10 -07:00
Justine Tunney 5bd22aef12 Experiment with supporting Windows Arm64 natively
So far I haven't found any way to run native Arm64 code on Windows Arm64
without using MSVC. When I build a PE binary from scratch that should be
a valid Windows Arm64 program, the OS refuses to run it. Possibly due to
requiring additional content like XML manifests or relocation or control
flow integrity data that isn't normally required on x64. I've also tried
using VirtualAlloc2() to JIT an Arm64 native function, but VirtualAlloc2
always fails with invalid parameter. I tried using MSVC to create an ARM
DLL that my x64 emulated program can link at runtime, to pass a function
pointer with ARM code, but LoadLibrary() rejects ARM DLLs as invalid exe

The only option left, is likely to write a new program like ape/ape-m1.c
which can be compiled by MSVC to load and run an AARCH64 ELF executable.
The emulated x64 binary would detect emulation using IsWow64Process2 and
then drop the loader executable in a temporary folder, and re-launch the
original executable, using the Arm64 segments of the cosmocc fat binary.
2024-08-16 06:43:59 -07:00
Justine Tunney 1671283f1a Avoid clobbering errno 2024-08-15 23:54:14 -07:00
Justine Tunney 0a79c6961f Make malloc scalable on all platforms
It turns out sched_getcpu() didn't work on many platforms. So the system
call now has tests and is well documented. We now employ new workarounds
on platforms where it isn't supported in our malloc() implementation. It
was previously the case that malloc() was only scalable on Linux/Windows
for x86-64. Now the other platforms are scalable too.
2024-08-15 23:32:53 -07:00
Justine Tunney 3fd275f59f Import optimized routines changes to exp10 2024-08-15 18:37:33 -07:00
Justine Tunney 2045e87b7c Fix build issues 2024-08-15 18:37:33 -07:00
Jacob Hummer 24666e121d add nightly cosmocc (artifact) builds (#1254)
Using https://nightly.link/ with GitHub actions artifacts you can have a
nightly build (but not a _release_ -- there's no releasing or
pre-releasing happening) of cosmocc.

Example URL if this PR were merged:


https://nightly.link/jart/cosmopolitan/workflows/nightly-cosmocc/master/cosmocc.zip

Or you can just download it directly from the GitHub "Actions"
https://github.com/jart/cosmopolitan/actions workflow summary page of a
particular run

example from my own fork:


![image](https://github.com/user-attachments/assets/8ba708dd-8289-4f8b-932c-cf535ee86f62)
could download by clicking on the artifact

or by using third-party service to provide a link for unauthenticated
requests (like wget or curl)

https://nightly.link/jcbhmr/cosmopolitan/workflows/tool-cosmocc-package-sh/master/cosmocc.zip

this would be useful for users who don't want to or can't figure out how
to build cosmocc themselves (like Windows) but still want to use a
nightly build since a fix hasn't been released as a release version yet.

this would also be a good way to test the release process but instead of
pushing the `cosmocc.zip` to _wherever it goes now_ you publish it as a
github actions artifact for the very few nightly bleeding edge users to
use & test.

you don't have to use https://nightly.link or recommend it or anything;
i just know its a cool way to wget or curl the URLs instead of
downloading it via your browser web UI. particularly useful for
remote/ssh/web-ide development.
2024-08-15 00:47:40 -04:00
Justine Tunney ff1a0d1c40 Upgrade to superconfigure z0.0.51 2024-08-04 14:59:53 -07:00
Justine Tunney 7f0db3e3b9 Add last commit to .git-blame-ignore-revs 2024-08-04 12:54:30 -07:00
Justine Tunney 31194165d2 Remove .internal from more header filenames 2024-08-04 12:52:25 -07:00
Justine Tunney c265c17d54 Fix the build 2024-08-04 07:08:28 -07:00
Justine Tunney 7499367060 Ignore -Wimplicit-function-declaration in cosmocc 2024-08-03 21:36:36 -07:00
Justine Tunney 3f26dfbb31 Share file offset across execve() on Windows
This is a breaking change. It defines the new environment variable named
_COSMO_FDS_V2 which is used for inheriting non-stdio file descriptors on
execve() or posix_spawn(). No effort has been spent thus far integrating
with the older variable. If a new binary launches the older ones or vice
versa they'll only be able to pass stdin / stdout / stderr to each other
therefore it's important that you upgrade all your cosmo binaries if you
depend on this functionality. You'll be glad you did because inheritance
of file descriptors is more aligned with the POSIX standard than before.
2024-08-03 17:48:00 -07:00
Justine Tunney 761c6ad615 Share file offset across processes
This change ensures that if a file descriptor for an open disk file gets
shared by multiple processes within a process tree, then lseek() changes
will be visible across processes, and read() / write() are synchronized.
Note this only applies to Windows, because UNIX kernels already do this.
2024-08-03 01:39:11 -07:00
Justine Tunney a80ab3f8fe Implement bf16 compiler runtime library 2024-08-02 02:04:53 -07:00
Gautham 9ebacb7892 Convert GCC 14 errors back to warnings (#1247)
https://gcc.gnu.org/gcc-14/porting_to.html#warnings-as-errors

Changing these to warnings helps build code with `cosmocc`. Perhaps this
can be a patch to `cosmocc` or skipped entirely.
2024-08-01 21:42:40 -07:00
Justine Tunney 6ac3d3b804 Add precompiled header support to cosmocc 2024-07-31 06:04:41 -07:00
Justine Tunney f8cfc89eba Allow -c to be specified with -E in cosmocc 2024-07-31 02:09:15 -07:00
Justine Tunney 4ed4a1095a Improve build latency 2024-07-31 01:21:27 -07:00
Justine Tunney 8d8aecb6d9 Avoid legacy instruction penalties on x86 2024-07-31 01:02:38 -07:00
Justine Tunney 1fba310e22 Delete mislocated headers 2024-07-31 01:01:00 -07:00
Justine Tunney bb815eafaf Update Musl Libc code
We now have implement all of Musl's localization code, the same way that
Musl implements localization. You may need setlocale(LC_ALL, "C.UTF-8"),
just in case anything stops working as expected.
2024-07-30 22:51:29 -07:00
Justine Tunney d0360bf4bd Introduce cosmoranlib 2024-07-29 19:18:52 -07:00
Justine Tunney 8cdb3e136b Check in ruler summation experiments 2024-07-29 18:02:16 -07:00
Justine Tunney 3dab207351 Remove mkfifo() prototype 2024-07-29 07:42:54 -07:00
Justine Tunney 1092d9b7e8 Remove old usages of %n 2024-07-29 01:39:36 -07:00
Justine Tunney d40acc60b1 Detect more x86 features 2024-07-29 00:16:29 -07:00
Justine Tunney cf1559c448 Remove __threaded variable 2024-07-28 23:43:30 -07:00
Justine Tunney 01b09bc817 Support printf %n directive 2024-07-28 22:27:06 -07:00
Justine Tunney c1a0b017e9 Fix the build 2024-07-28 21:02:04 -07:00
Justine Tunney 77d3a07ff2 Fix std::filesystem
This change makes a second pass, at fixing the errno issue with libcxx's
filesystem code. Previously, 89.01% of LLVM's test suite was passing and
now 98.59% of their tests pass. Best of all, it's now possible for Clang
to be built as a working APE binary that can to compile the Cosmopolitan
repository. Please note it has only been vetted so far for some objects,
and more work would obviously need to be done in cosmo, to fix warnings.
2024-07-28 17:31:21 -07:00
Justine Tunney 0d7c272d3f Don't use sendfile() in libcxx 2024-07-28 17:31:21 -07:00
Justine Tunney 18964e5d76 Fix remove() directory on Windows 2024-07-28 17:31:21 -07:00
Justine Tunney e18fe1e112 Freshen build/bootstrap/cocmd
See https://news.ycombinator.com/item?id=41055121
2024-07-27 23:22:11 -07:00
Justine Tunney 8621034d42 Release Cosmopolitan v3.6.2 2024-07-27 20:20:54 -07:00
Justine Tunney 32292aee84 Fix build determinism issue 2024-07-27 19:03:32 -07:00
Justine Tunney 81dd9639ed Fix bug in tool/decode/zip 2024-07-27 18:34:21 -07:00
Justine Tunney f147d3dde9 Fix some static analysis issues 2024-07-27 09:16:54 -07:00
Justine Tunney fb54604b31 Upgrade to superconfigure z0.0.48
Our cosmocc binaries are now built with GCC 14.1, using the Cosmo commit
efb3a34608 from yesterday.

GCC is now configured using --enable-analyzer so you can use -fanalyzer.
2024-07-27 08:35:36 -07:00
Justine Tunney cdfcee51ca Properly serialize fork() operations
This change solves an issue where many threads attempting to spawn forks
at once would cause fork() performance to degrade with the thread count.
Things got real nasty on NetBSD, which slowed down the whole test fleet,
because there's no vfork() and we're forced to use fork() in our server.

   threads      count task
         1       1062 fork+exit+wait
         2        668 fork+exit+wait
         4         66 fork+exit+wait
         8         19 fork+exit+wait
        16         22 fork+exit+wait
        32         16 fork+exit+wait

Things are now much less bad on NetBSD, but not great, since it does not
have futexes; we rely on its semaphore file descriptors to do conditions

   threads      count task
         1       1085 fork+exit+wait
         2        842 fork+exit+wait
         4        532 fork+exit+wait
         8        400 fork+exit+wait
        16        276 fork+exit+wait
        32         66 fork+exit+wait

With OpenBSD which also lacks vfork(), things were just as bad as NetBSD

   threads      count task
         1        584 fork+exit+wait
         2        687 fork+exit+wait
         4        206 fork+exit+wait
         8         24 fork+exit+wait
        16         33 fork+exit+wait
        32         26 fork+exit+wait

But since OpenBSD has futexes fork() works terrifically thanks to *NSYNC

   threads      count task
         1        525 fork+exit+wait
         2        580 fork+exit+wait
         4        451 fork+exit+wait
         8        479 fork+exit+wait
        16        408 fork+exit+wait
        32        373 fork+exit+wait

This issue would most likely only manifest itself, when pthread_atfork()
callers manage to slip a spin lock into the outermost position of fork's
list of locks. Since fork() is very slow, a spin lock can be devastating

Needless to say vfork() rules and anyone who says differently is kidding
themselves. Look at what a FreeBSD 14.1 virtual machine with equal specs
can do over the course of three hundred milliseconds.

   threads      count task
         1       2559 vfork+exit+wait
         2       5389 vfork+exit+wait
         4      34933 vfork+exit+wait
         8      43273 vfork+exit+wait
        16      49648 vfork+exit+wait
        32      40247 vfork+exit+wait

So it's a shame that so few OSes support vfork(). It creates an unsavory
situation, where someone wanting to build a server that spawns processes
would be better served to not use threads and favor a multiprocess model
2024-07-27 08:23:44 -07:00
Justine Tunney 18a620cc1a Make some improvements of little consequence 2024-07-27 08:20:18 -07:00
Justine Tunney 690d3df66e Expand the virtual address space on Windows 2024-07-27 08:19:05 -07:00
Justine Tunney efb3a34608 Fix package.sh build error 2024-07-26 06:57:24 -07:00
Justine Tunney 642e9cb91a Introduce cosmocc flags -mdbg -mtiny -moptlinux
The cosmocc.zip toolchain will now include four builds of the libcosmo.a
runtime libraries. You can pass the -mdbg flag if you want to debug your
cosmopolitan runtime. You can pass the -moptlinux flag if you don't want
windows code lurking in your binary. See tool/cosmocc/README.md for more
details on how these flags may be used and their important implications.
2024-07-26 05:10:25 -07:00
Justine Tunney 59692b0882 Make spinlocks faster (take two)
This change is green on x86 and arm test fleet.
2024-07-26 00:45:24 -07:00
Justine Tunney 02e1cbcd00 Revert "Make spin locks go faster"
This reverts commit c8e25d811c.
2024-07-25 22:24:32 -07:00
Justine Tunney 0679cfeb41 Fix build 2024-07-25 22:12:08 -07:00
Justine Tunney edd5e2c8e3 Expose gethostbyname() 2024-07-25 19:21:35 -07:00
Justine Tunney c8e25d811c Make spin locks go faster 2024-07-25 17:37:11 -07:00
Justine Tunney a31d5ea399 Remove cosmoc++ compiler warning 2024-07-25 15:20:41 -07:00
Justine Tunney 7d88343973 Release Cosmopolitan v3.6.1 2024-07-25 13:34:02 -07:00
Justine Tunney 3915ca0f71 Have cosmocc define -Wno-implicit-int
GCC 13+ changed its policies to be very aggressive about breaking builds
that have anything resembling K&R C. I very strongly disagree with these
decisions. Users who think their compiler should should also be a linter
are perfectly welcome to opt-in to -Wimplicit-int.
2024-07-25 05:51:57 -07:00
Justine Tunney 2c4b88753b Add special errno handling to libcxx 2024-07-25 01:23:02 -07:00
Justine Tunney 0f486a13c8 Fix fdlibm license 2024-07-24 20:42:08 -07:00
Justine Tunney 1020dd41cc bzero() should be defined without special defines 2024-07-24 16:15:30 -07:00
Justine Tunney d3a13e8d70 Improve lock hierarchy
- NetBSD no longer needs a spin lock to create semaphores
- Windows fork() now locks process manager in correct order
2024-07-24 16:05:48 -07:00
Justine Tunney 7ba9a73840 Remove more _Atomic keywords from public headers
It's been thirteen years and C++ still hasn't implemented this wonderful
simple builtin keyword. In C++23 a solution was provided for making this
work in C++ which is libcxx's stdatomic.h. Including that header schleps
in literally 253 unique header files!! Many of the header files it needs
are libc header files like pthread.h where we need to have the _Atomic()
keyword, but since <atomic> depends on pthreads we can't have it include
the <stdatomic.h> header that defines _Atomic for C++ users, and instead
we simply make the type non-atomic, hoping and praying only C code shall
use those internal data structures. This just shows how STL clowns can't
be trusted to define the innermost primitives of a language. They should
instead be focusing on being the best at algorithms and data structures.
2024-07-24 13:56:03 -07:00
Justine Tunney 4a1ae86124 Make some code build faster 2024-07-24 12:26:52 -07:00
Justine Tunney 5dd7ddb9ea Remove bad defines from early days of project
These definitions were causing issues with building LLVM. It is possible
they also caused crashes we've seen with our MacOS ARM64 OpenMP support.
2024-07-24 12:11:21 -07:00
Justine Tunney f25fbbaaeb Use libcxx abi v1 2024-07-24 09:49:48 -07:00
Justine Tunney fbc4b03d4c Restore support for AMD K8 2024-07-24 08:59:29 -07:00
Justine Tunney e398f3887c Make more improvements to threads and mappings
- NetBSD should now have faster synchronization
- POSIX barriers may now be shared across processes
- An edge case with memory map tracking has been fixed
- Grand Central Dispatch is no longer used on MacOS ARM64
- POSIX mutexes in normal mode now use futexes across processes
2024-07-24 01:19:54 -07:00
Justine Tunney 2187d6d2dd Fix MODE=optlinux for GitHub Actions 2024-07-23 04:17:22 -07:00
Justine Tunney 0602ff6bab Fix MODE=optlinux and MODE=tiny builds 2024-07-23 04:04:19 -07:00
Justine Tunney 5660ec4741 Release Cosmopolitan v3.6.0
This release is an atomic upgrade to GCC 14.1.0 with C23 and C++23
2024-07-23 03:28:19 -07:00
Justine Tunney 62ace3623a Release Cosmopolitan v3.5.9 2024-07-22 21:02:40 -07:00
Justine Tunney 6e809ee49b Add unit test for process shared conditions 2024-07-22 18:48:54 -07:00
Justine Tunney 61c36c1dd6 Allow pthread_condattr_setpshared() to set shared 2024-07-22 18:41:45 -07:00
Justine Tunney 0a9a6f86bb Support process shared condition variables 2024-07-22 16:35:29 -07:00
Justine Tunney 3de6632be6 Graduate some clock_gettime() constants to #define
- CLOCK_THREAD_CPUTIME_ID
- CLOCK_PROCESS_CPUTIME_ID

Cosmo now supports the above constants universally across supported OSes
therefore it's now safe to let programs detect their presence w/ #ifdefs
2024-07-22 07:14:35 -07:00
Justine Tunney c83ec5fdd9 Fix more issues 2024-07-22 02:28:41 -07:00
Justine Tunney 23611cd854 Talk more about alignment 2024-07-22 02:11:09 -07:00
Justine Tunney 62a97c919f Fix typos in APE specification
Fixes #1244
2024-07-22 01:41:44 -07:00
Justine Tunney 16d244614e Mention red zone in APE ABI specification 2024-07-21 21:18:12 -07:00
Justine Tunney 41cc053419 Add more content to APE specification 2024-07-21 20:47:24 -07:00
Justine Tunney 5d2d9e9640 Add back missing TlsAlloc() call
Cosmopolitan Libc once called this important function although somewhere
along the way, possibly in a refactoring, it got removed and __tls_alloc
has always been zero ever since.
2024-07-21 20:45:27 -07:00
Justine Tunney e08a4cd99e Release Cosmopolitan v3.5.8 2024-07-21 17:01:33 -07:00
Justine Tunney 7ebaff34c6 Fix ctype.h and wctype.h 2024-07-21 15:54:17 -07:00
Justine Tunney e7be5a5e2b Upgrade to latest superconfigure 2024-07-21 15:30:47 -07:00
Justine Tunney 30afd6ddbb Improve multithreading 2024-07-21 14:40:45 -07:00
Justine Tunney d3167126aa Fix regression with last commit 2024-07-20 16:43:48 -07:00
Justine Tunney d3f87f4c64 Upgrade to cosmocc v3.5.7 2024-07-20 11:21:26 -07:00
Justine Tunney 29ce25c767 Start writing formal specification for APE 2024-07-20 10:04:22 -07:00
Justine Tunney 7996bf67b5 Release Cosmopolitan v3.5.7 2024-07-20 03:48:57 -07:00
Justine Tunney 626a5d02ee Add missing lock statement 2024-07-20 03:47:22 -07:00
Justine Tunney 527aaa41eb Prevent MODE=tiny ShowCrashReports() looping 2024-07-20 03:34:37 -07:00
Justine Tunney 421a819d88 Fix bug in munmap_test 2024-07-20 03:23:37 -07:00
Justine Tunney 3374cbba73 Release Cosmopolitan v3.5.6 2024-07-20 02:43:10 -07:00
Justine Tunney 2018cac11f Use better memory strategy on Windows
Rather than using the the rollo global to pick addresses, we select them
randomly now using a conservative vaspace.
2024-07-20 02:20:03 -07:00
Justine Tunney 6a5d4ed65b Fix bug with disabling sigaltstack() 2024-07-20 01:00:16 -07:00
Justine Tunney 493ffc9b7f Release Cosmopolitan v3.5.5 2024-07-19 22:33:17 -07:00
Justine Tunney 101fb3d9b3 Make some new Windows 10 memory APIs available 2024-07-19 22:26:49 -07:00
Justine Tunney f6ba270ff3 Add last commit to .git-blame-ignore-revs 2024-07-19 19:38:53 -07:00
Justine Tunney 86d884cce2 Get rid of .internal.h convention in LIBC_INTRIN 2024-07-19 19:38:00 -07:00
Justine Tunney 0ed916ad5c Fix a bug in example code 2024-07-19 19:11:28 -07:00
Justine Tunney 1029dcc597 Reduce default stack size from 256kb to 81kb
This is the same as Musl Libc. Please note it only applies to threads.
2024-07-19 14:18:06 -07:00
Ikko Eltociear Ashimine c697133a2d Fix typo in accept4-sysv.c (#1235) 2024-07-19 05:46:29 -07:00
Justine Tunney 1ff037df3c Add some documentation 2024-07-19 04:46:26 -07:00
Justine Tunney 567d8fe32d Create variables for page size 2024-07-18 21:16:53 -07:00
Justine Tunney 23dfb79d33 Fix minor suboptimalities in memory manager 2024-07-18 19:19:51 -07:00
Justine Tunney 76cea6c687 Squeeze more performance out of memory manager 2024-07-08 03:08:42 -07:00
Justine Tunney 63065cdd70 Make a test less intensive by default 2024-07-07 19:35:09 -07:00
Justine Tunney 3f2a1b696e Fix greenbean example
The memory leak detector was crashing. When using gc() you shouldn't use
the CheckForMemoryLeaks() function from inside the same function, due to
how it runs the atexit handlers.
2024-07-07 17:52:33 -07:00
Justine Tunney f590e96abd Work around QEMU bugs 2024-07-07 15:42:46 -07:00
Justine Tunney f7780de24b Make realloc() go 100x faster on Linux/NetBSD
Cosmopolitan now supports mremap(), which is only supported on Linux and
NetBSD. First, it allows memory mappings to be relocated without copying
them; this can dramatically speed up data structures like std::vector if
the array size grows larger than 256kb. The mremap() system call is also
10x faster than munmap() when shrinking large memory mappings.

There's now two functions, getpagesize() and getgransize() which help to
write portable code that uses mmap(MAP_FIXED). Alternative sysconf() may
be called with our new _SC_GRANSIZE. The madvise() system call now has a
better wrapper with improved documentation.
2024-07-07 12:40:30 -07:00
Justine Tunney 196942084b Recomment out accidental code 2024-07-06 19:57:47 -07:00
Justine Tunney 6be030cd7c Fix MODE=tinylinux build 2024-07-06 01:51:08 -07:00
Justine Tunney 8c645fa1ee Make mmap() scalable
It's now possible to create thousands of thousands of sparse independent
memory mappings, without any slowdown. The memory manager is better with
tracking memory protection now, particularly on Windows in a precise way
that can be restored during fork(). You now have the highest quality mem
manager possible. It's even better than some OSes like XNU, where mmap()
is implemented as an O(n) operation which means sadly things aren't much
improved over there. With this change the llamafile HTTP server endpoint
at /tokenize with a prompt of 50 tokens is now able to handle 2.6m r/sec
2024-07-05 23:26:00 -07:00
Justine Tunney 3756870635 Implement new red-black tree 2024-07-05 12:56:03 -07:00
Justine Tunney fc65422660 Remove __mmap() and __munmap() 2024-07-05 12:55:46 -07:00
Justine Tunney 01587de761 Simplify memory manager 2024-07-05 05:47:15 -07:00
Justine Tunney 5a9a08d1cf Fix regression in elf2pe program 2024-07-04 04:02:20 -07:00
Justine Tunney bd6d9ff99a Get deathstar demo working again on metal 2024-07-04 03:44:17 -07:00
Justine Tunney 15ea0524b3 Reduce code size of mandatory runtime
This change reduces o/tiny/examples/life from 44kb to 24kb in size since
it avoids linking mmap() when unnecessary. This is important, to helping
cosmo not completely lose touch with its roots.
2024-07-04 02:50:20 -07:00
Justine Tunney fdab49b30e Demonstrate signal safety of recursive mutexes 2024-07-04 02:47:52 -07:00
Justine Tunney 135d538b1d Make ctl::set use 30% less memory than libcxx 2024-07-04 02:46:27 -07:00
Justine Tunney 6dbc3fba18 Add AMD cache sizes to o//tool/viz/cpuid 2024-07-04 02:45:45 -07:00
Justine Tunney 70f77aad33 Release Cosmopolitan v3.5.4 2024-07-01 07:17:57 -07:00
Justine Tunney d0cd719375 Make more CTL fixes 2024-07-01 07:17:57 -07:00
Justine Tunney 61370983e1 Complete the Windows TLS fix made in e437bed00 2024-07-01 07:17:57 -07:00
Terror 72511ff0ac [Redbean] Add UuidV7 method (#1213)
To Complete #1140 add UUID version 7 to Redbean
2024-07-01 06:06:56 -07:00
Justine Tunney c1f8d0678c Mark ctl::to_string() noexcept 2024-07-01 05:54:59 -07:00
Justine Tunney e627bfa359 Introduce ctl::to_string() 2024-07-01 05:40:38 -07:00
Justine Tunney acbabedf27 Make CTL definitions less ambiguous 2024-07-01 03:48:28 -07:00
Justine Tunney 239f8ce76e Release Cosmopolitan v3.5.3 2024-07-01 02:07:56 -07:00
Justine Tunney ca4cf67eb8 Include more programs in cosmocc
The Cosmopolitan Compiler Collection now includes the following programs

- `ar.ape` is a faster alternative to `ar rcsD` for creating determistic
  static archives. It's ~10x faster than GNU because it isn't quadratic.
  It'll even outperform LLVM ar by 2x, thanks to writev/copy_file_range.

- `sha256sum.ape` is a faster alternative to the `sha256sum` command. It
  goes 2x faster since it leverages vectorized assembly implementations.

- `resymbol` is a brand new program we invented, like objcopy, that lets
  you rename all the global symbols in a .o file to have a new suffix or
  prefix. In the future, this will be used by cosmocc automatically when
  building -O3 math kernels, that need to be vectorized for all hardware

- `gzip.ape` is a faster version of the `gzip` command, that is included
  by most Linux distros. It gains better performance using Chromium Zlib
  which, once again, includes highly optimized assembly, that Mark Adler
  won't merge into the official MS-DOS compatible zlib codebase.

- `cocmd` is the cosmopolitan shell. It can function as a faster `sh -c`
  alternative than bash and dash as the `SHELL = /opt/cosmocc/bin/cocmd`
  at the top of your Makefile. Please note you should be using the cosmo
  fork of GNU make (already included), since normal make won't recognize
  this as a bourne-compatible shell and remove the execve() optimization
  which makes things slower. In some ways that's true. This doesn't have
  a complete POSIX shell implementation. However it's enough for cosmo's
  mono repo. It also implements faster behaviors in some respects.

The following programs are also introduced, which aren't as interesting.
The main reason why they're here is so Cosmopolitan's mono repo shall be
able to remove build/bootstrap/ in future editions. That way we can keep
build utilities better up to date, without bloating the git history much

- `chmod.ape` for hermeticity
- `cp.ape` for hermeticity
- `echo.ape` for hermeticity
- `objbincopy` is an objcopy-like tool that's used to build ape loader
- `package.ape` is used for strict dependency checking of object graph
- `rm.ape` for hermeticity
- `touch.ape` for hermeticity
2024-07-01 02:05:25 -07:00
Justine Tunney 78d3b86ec7 Fix Android support
Thanks to @aj47 (techfren.net) the new Cosmo memory manager is confirmed
to be working on Android!! The only issue turned out to be forgetting to
update the program address in the linker script. We now know w/ absolute
certainty that APE binaries as complex as llamafile, now work correctly.
2024-07-01 01:06:47 -07:00
Justine Tunney 44191b3f50 Add more type traits to CTL 2024-06-30 20:59:38 -07:00
Justine Tunney e437bed006 Fix crash caused when Windows needs a lot of TLS 2024-06-30 20:53:43 -07:00
Justine Tunney 76957983cf Make POSIX threads improvements
- Ensure SIGTHR isn't blocked in newly created threads
- Use TIB rather than thread_local for thread atexits
- Make POSIX thread keys atomic within thread
- Don't bother logging prctl() to --strace
- Log thread destructor names to --strace
2024-06-30 15:38:59 -07:00
Justine Tunney 387310c659 Fix issue with ctl::vector constructor 2024-06-30 02:26:38 -07:00
Justine Tunney 4cb5e21ba8 Introduce pthread_decimate_np() api
This is useful with CheckForMemoryLeaks().
2024-06-30 02:26:06 -07:00
Justine Tunney 1bf2d8e308 Further improve mmap() locking story
The way to use double linked lists, is to remove all the things you want
to work on, insert them into a new list on the stack. Then once you have
all the work items, you release the lock, do your work, and then lock it
again, to add the shelled out items back to a global freelist.
2024-06-29 17:12:43 -07:00
Justine Tunney 98e684622b Add iostream to CTL 2024-06-29 15:45:09 -07:00
Justine Tunney 617ddfee93 Release Cosmopolitan v3.5.2 2024-06-29 10:58:47 -07:00
Justine Tunney 464858dbb4 Fix bugs with new memory manager
This fixes a regression in mmap(MAP_FIXED) on Windows caused by a recent
revision. This change also fixes ZipOS so it no longer needs a MAP_FIXED
mapping to open files from the PKZIP store. The memory mapping mutex was
implemented incorrectly earlier which meant that ftrace and strace could
cause cause crashes. This lock and other recursive mutexes are rewritten
so that it should be provable that recursive mutexes in cosmopolitan are
asynchronous signal safe.
2024-06-29 10:53:57 -07:00
Justine Tunney 6de12c1032 Upgrade to superconfigure z0.0.44 2024-06-29 05:07:25 -07:00
Justine Tunney a16eb76f5e Fix build break 2024-06-29 04:34:27 -07:00
Justine Tunney 021c53ba32 Add more CTL content 2024-06-28 19:09:54 -07:00
Justine Tunney 38921dc46b Introduce more CTL content
This change introduces accumulate, addressof, advance, all_of, distance,
array, enable_if, allocator_traits, back_inserter, bad_alloc, is_signed,
any_of, copy, exception, fill, fill_n, is_same, is_same_v, out_of_range,
lexicographical_compare, is_integral, uninitialized_fill_n, is_unsigned,
numeric_limits, uninitialized_fill, iterator_traits, move_backward, min,
max, iterator_tag, move_iterator, reverse_iterator, uninitialized_move_n

This change experiments with rewriting the ctl::vector class to make the
CTL design more similar to the STL. So far it has not slowed things down
to have 42 #include lines rather than 2, since it's still almost nothing
compared to LLVM's code. In fact the closer we can flirt with being just
like libcxx, the better chance we might have of discovering exactly what
makes it so slow to compile. It would be an enormous discovery if we can
find one simple trick to solving the issue there instead.

This also fixes a bug in `ctl::string(const string &s)` when `s` is big.
2024-06-27 22:42:32 -07:00
Steven Dee (Jōshin) 054da021d0 ctl::string benchmarking code (#1200) 2024-06-26 21:30:05 -04:00
Justine Tunney 199662071a Make std::random_device use getentropy() 2024-06-24 07:32:07 -07:00
Justine Tunney 572ac7d100 Release Cosmopolitan v3.5.1 2024-06-24 06:54:15 -07:00
Justine Tunney d461c6f47d Do more quality assurance work 2024-06-24 06:53:49 -07:00
Justine Tunney 67b19ae733 Release Cosmopolitan v3.5.0 2024-06-23 22:45:14 -07:00
Justine Tunney c4c812c154 Introduce ctl::set and ctl::map
We now have a C++ red-black tree implementation that implements standard
template library compatible APIs while compiling 10x faster than libcxx.
It's not as beautiful as the red-black tree implementation in Plinko but
this will get the job done and the test proves it upholds all invariants

This change also restores CheckForMemoryLeaks() support and fixes a real
actual bug I discovered with Doug Lea's dlmalloc_inspect_all() function.
2024-06-23 22:27:11 -07:00
Justine Tunney 388e236360 Revert misguided dlmalloc optimization 2024-06-22 09:55:02 -07:00
Justine Tunney f2c8ddbbe3 Fix --strace use-after-free in pthread_join() 2024-06-22 06:05:52 -07:00
Justine Tunney d1d4388201 Delete ASAN
It hasn't been helpful enough to be justify the maintenance burden. What
actually does help is mprotect(), kprintf(), --ftrace and --strace which
can always be counted upon to work correctly. We aren't losing much with
this change. Support for ASAN on AARCH64 was never implemented. Applying
ASAN to the core libc runtimes was disabled many months ago. If there is
some way to have an ASAN runtime for user programs that is less invasive
we can potentially consider reintroducing support. But now is premature.
2024-06-22 05:45:49 -07:00
Justine Tunney 6ffed14b9c Rewrite memory manager
Actually Portable Executable now supports Android. Cosmo's old mmap code
required a 47 bit address space. The new implementation is very agnostic
and supports both smaller address spaces (e.g. embedded) and even modern
56-bit PML5T paging for x86 which finally came true on Zen4 Threadripper

Cosmopolitan no longer requires UNIX systems to observe the Windows 64kb
granularity; i.e. sysconf(_SC_PAGE_SIZE) will now report the host native
page size. This fixes a longstanding POSIX conformance issue, concerning
file mappings that overlap the end of file. Other aspects of conformance
have been improved too, such as the subtleties of address assignment and
and the various subtleties surrounding MAP_FIXED and MAP_FIXED_NOREPLACE

On Windows, mappings larger than 100 megabytes won't be broken down into
thousands of independent 64kb mappings. Support for MAP_STACK is removed
by this change; please use NewCosmoStack() instead.

Stack overflow avoidance is now being implemented using the POSIX thread
APIs. Please use GetStackBottom() and GetStackAddr(), instead of the old
error-prone GetStackAddr() and HaveStackMemory() APIs which are removed.
2024-06-22 05:45:11 -07:00
Justine Tunney 7f6d0b8709 Support -x LANG flag in cosmocc 2024-06-20 23:55:46 -07:00
Steven Dee (Jōshin) d7b1919b29 ctl::unique_ptr improvements and cleanup (#1221)
Explicitly value-initializes the deleter, even though I have not found a
way to get the deleter to act like it’s been default-initialized in unit
tests so far.

Uses auto in reset. The static cast is apparently not needed (unless I’m
missing some case I didn’t think of.)

Implements the general move constructor - turns out that the reason this
didn’t work before was that default_delete<U> was not move constructible
from default_delete<T>.

Drop inline specifiers from functions defined entirely inside the struct
definition since they are implicitly inline.

* Cleans up reset to match spec

Remove the variants from the T[] specialization. Also follow the spec on
the order of operations in reset, which may matter if we are deleting an
object that has a reference to the unique_ptr that is being reset. (?)

* Tests Base/Derived reset.

* Adds some constexpr declarations.

* Adds default_delete specialization for T[].

* Makes parameters const.
2024-06-20 18:44:31 -04:00
Steven Dee (Jōshin) f86e6f8eb0 Make new.cc definitions weak (#1233)
The STL says that these should be replaceable by user code.

new.cc now defines only a few direct functions (including a free wrapper
that perplexingly is needed since g++ didn’t want to alias "free".) Now,
all of the operators are weak references to those functions.
2024-06-20 15:20:54 -04:00
Steven Dee (Jōshin) 7e780e57d4 More ctl::string optimization (#1232)
Moves some isbig checks into string.h, enabling smarter optimizations to
be made on small strings. Also we no longer zero out our string prior to
calling the various constructors, buying back the performance we lost on
big strings when we made the small-string optimization. We further add a
little optimization to the big_string copy constructor: if the string is
using half or more of its capacity, then we don’t recompute capacity and
just take the old string’s. As well, the copy constructor always makes a
small string when it will fit, even if copied from a big string that got
truncated.

This also reworks the test to follow the idiom adopted elsewhere re stl,
and adds a helper function to tell if a string is small based on data().
2024-06-20 14:52:12 -04:00
Steven Dee (Jōshin) 9a5a13854d CTL: utility.h, use ctl::swap in string (#1227)
* Add ctl utility.h

Implements forward, move, swap, and declval. This commit also adds a def
for nullptr_t to cxx.inc. We need it now because the CTL headers stopped
including anything from libc++, so we no longer get their basic types.

* Use ctl::swap in string

The STL spec says that swap is located in the string_view header anyawy.
Performance-wise this is a noop, but it’s slightly cleaner.
2024-06-19 01:00:59 -04:00
Steven Dee (Jōshin) a795017416 Fix c.inc _Atomic define for C++ (#1231)
c.inc (AFAICT erroneously) defined _Atomic(t) as `volatile t *`, when it
should have just said `volatile t`, when __STDC_VERSION__ was too small.
This happens when we’re compiling C++, but in C++11, _Atomic is a define
supplied by the STL rather than a keyword supplied by the compiler. Wait
though, it gets better: in C++11, _Atomic hooks you into the morass that
is stdatomic.h, and ultimately refers everything back to std::atomic<T>.

The gory, horrifying details are in libcxx's __atomic/cxx_atomic_impl.h.
The tldr is that for our purposes it’s fine to just say volatile and use
the normal libc/intrin/atomic.h functions.
2024-06-17 21:12:02 -07:00
Brian 8e3b361aeb Remove testing label from labeler.yml (#1220)
#1219 had an issue with noisy testing label. Investigated if there is a
syntax to make it more exclusive, but turns out there isn't one yet. So
let's remove an manually add it in as needed.

Fixes #1219.
2024-06-16 11:45:57 -04:00
Steven Dee (Jōshin) f9dd5683a4 Implement ctl::unique_ptr (#1216)
The way unique_ptr is supposed to work is as a purely compile-time check
that your raw pointers are getting deleted when they go out of scope. It
should ideally emit the same exact machine code as if you were using raw
pointers with manual deletes.

Part of what this means is that under normal circumstances, a unique_ptr
shouldn’t take up more space than a raw pointer - in other words, sizeof
unique_ptr<T> should == sizeof(T*).

The present PR doesn’t bother with the specialization for array types. I
also left a couple other parts of the STL API unimplemented. I’d love to
see someone else implement these, or I’ll get to them at some point.
2024-06-15 22:54:52 -04:00
Steven Dee (Jōshin) e38a6e7996 ctl string const/value tweaks (#1218)
The mangled name of a C++ function will typically not vary by const-ness
of a by-value parameter; in other words, there is no meaning to a const-
qualified by-value parameter in a function prototype. However, the const
keyword _does_ matter at function _definition_ time, like it does with a
variable declared in the body. So for prototypes, we strip out const for
by-value parameters; but for definitions, we leave them alone.

At function definition (as opposed to prototype), we add const to values
in parameters by default, unless we’re going to mutate them.

This commit also changes a couple of const string_view& to be simply by-
value string_view. A string_view is only two words; it rarely ever makes
sense to pass one by reference if it’s not going to be mutated.
2024-06-15 18:09:30 -07:00
Steven Dee (Jōshin) ddfaf3fee0 Explain the clang-format off in new.h 2024-06-15 17:17:04 -07:00
Michael Lenaghan 0dbf01bf1d Bring Lua to 5.4.6. (#1214)
This essentially re-does the work of #875 on top of master.

This is what I did to check that Cosmo's Lua extensions still worked:

```
$ build/bootstrap/make MODE=aarch64 o/aarch64/third_party/lua/lua
$ ape o/aarch64/third_party/lua/lua
>: 10
10
>: 010
8
>: 0b10
2
>: string.byte("\e")
27
>: "Hello, %s" % {"world"}
Hello, world
>: "*" * 3
***
```

`luaL_traceback2` was used to show the stack trace with parameter
values; it's used in `LuaCallWithTrace`, which is used in Redbean to run
Lua code. You should be able to see the extended stack trace by running
something like this: `redbean -e "function a(b)c()end a(2)"` (with
"params" indicating the extended stack trace):

```
stack traceback:
 [string "function a(b)c()end a(2)"]:1: in function 'a', params: b = 2;
 [string "function a(b)c()end a(2)"]:1: in main chunk
```
@pkulchenko confirmed that I get the expected result with the updated
code.

This is what I did to check that Lua itself still worked:

```
$ cd third_party/lua/test/
$ ape ../../../o/aarch64/third_party/lua/lua all.lua
```

There's one test failure, in `files.lua`:

```
***** FILE 'files.lua'*****
testing i/o
../../../o/aarch64/third_party/lua/lua: files.lua:84: assertion failed!
stack traceback:
[C]: in function 'assert'
files.lua:84: in main chunk
(...tail calls...)
all.lua:195: in main chunk
[C]: in ?
.>>> closing state <<<
```

That isn't a result of these changes; the same test is failing in
master.

The failure is here:

```lua
if not _port then   -- invalid seek
  local status, msg, code = io.stdin:seek("set", 1000)
  assert(not status and type(msg) == "string" and type(code) == "number")
end
```

The test expects a seek to offset 1,000 on stdin to fail — but it
doesn't. `status` ends up being the new offset rather than `nil`.

If I comment out that one test, the remaining tests succeed.
2024-06-15 20:13:08 -04:00
Jōshin 3a599bfbe1 Update .git-blame-ignore-revs 2024-06-15 13:36:07 -07:00
Jōshin 89fc95fefd Rerun clang-format on the repo (#1217)
🚨 clang-format changes output per version!

This is with version 19.0.0. The modifications seem to be fixing the old
version’s errors - mainly involving omitted whitespace around binary ops
and inserted whitespace between goto labels and colons (if followed by a
curly brace.)

Also fixes a few mistakes made by e.g. someone (ahem) forgetting to pass
his ctl/string.h modifications through it.

We should add this to .git-blame-ignore-revs once we have its final hash
on master.
2024-06-15 16:34:48 -04:00
Jōshin 8e37ee2598 ctl::string cleanup (#1215)
We now fully initialize a ctl::string’s memory, so that it is always set
to a well-defined value, thus making it always safe to memcpy out of it.
This incidentally makes our string::swap function legal, which it wasn’t
before. This also saves us a store in string::reserve.

Now that we have made both big_string and small_string POD, I believe it
is safe to elide the launder calls, and have done so, thus cleaning up a
lot of the blob-related code.

I also got rid of set_big_capacity and replaced it with a set_big_string
that leaves us in a well-defined state afterwards. This function also is
able to be somewhat simpler; rather than delicate bit-twiddling, it just
reaches straight into blob and rewrites it wholesale.

Overall, this shaves about 1–2ns off of most benchmarks, and adds 1ns to
only one of them - creating a string from a char *.
2024-06-15 10:49:52 -07:00
Jōshin d9b4f647d8 Uncomment swap test (#1210) 2024-06-10 21:51:19 -07:00
Jōshin 0dde3a0e70 Get rid of preprocessor stuff in test (#1202)
Also it's a bit more idiomatic to say s.npos rather than string::npos.
2024-06-10 07:00:37 -07:00
Jōshin 32643e9fa7 Decouple swap from std (#1211)
This allows you to implement your own swap function without it having to
be part of the std namespace. std::swap is still used if it's available.
2024-06-10 03:40:17 -07:00
Jōshin 0a92c78035 Remove erroneous ctl:: prefixes 2024-06-08 15:07:39 -07:00
Jōshin 118db71121 Provide a minimal new.h for CTL (#1205)
This replaces the STL <new> header. Mainly, it defines a global operator
new and operator delete, as well as the placement versions of these. The
placement versions are required to not get compile errors when trying to
write a placement new statement.

Each of these operators is defined with many, many different variants. A
glance at new.cc is recommended followed by a chaser of the Alexandrescu
talk "std::allocator is to Allocation as std::vector is to Vexation". We
must provide a global-namespace source-level definition of each operator
and it is illegal for any of them to be marked inline, so here we are.

The upshot is that we no longer need to include <new>, and our optional/
vector headers are self-contained.
2024-06-08 15:05:38 -07:00
Alkis Evlogimenos a0410f0170 Make big_string pod (#1204)
`big_string` is not pod which means it needs to be properly constructed
and destroyed. Instead make it POD and destroy it manually in `string`
destructor.
2024-06-08 10:02:33 -07:00
Alkis Evlogimenos d44a7dc603 Fix bugs in in ctl::optional (#1203)
Manually manage the lifetime of `value_` by using an anonymous
`union`. This fixes a bunch of double-frees and double-constructs.

Additionally move the `present_` flag last. When `T` has padding
`present_` will be placed there saving `alignof(T)` bytes from
`sizeof(optional<T>)`.
2024-06-07 20:47:24 -04:00
Jōshin 2ba6b0158f Fix some memory issues with ctl::string (#1201)
There were a few errors in how capacity and memory was being handled for
small strings. The capacity errors meant that small strings would become
big strings too soon, and the memory error introduced undefined behavior
that was caught by CheckMemoryLeaks in our test file but only sometimes.

The crucial change is in reserve: we only copy n bytes into p2, and then
we manually set the null terminator instead of expecting it to have been
there already. (E.g. it might not be there for an empty small string.)

We also fix one other doozy in append when we were exactly at the small-
to-big string boundary: we set the last byte (i.e., the remainder field)
to 0, then decremented it, giving us size_t max. Whoops. We boneheadedly
fix this by setting the 0 byte after we've fixed up the remainder, so it
is at worst a no-op.

Otherwise, capacity now works the same for small strings as it does with
big strings: it's the amount of space available including the null byte.

We test all of this with a new test that only gets included if our class
under test is not std::string (presumably meaning it's ctl::string.) The
test manually verifies that the small string optimization behaves how we
expect.

Since this test checks against std::string, we go ahead and include that
other header from the STL.

Also modifies the new test we introduced to also run on std::string, but
it just does the append without expecting anything about how its data is
stored. We also check that the string has the right value afterwards.
2024-06-07 01:15:37 -04:00
Jōshin f3effcb703 One more SSO erratum from #1199
Making a string_view from a string appears to take about 1.3ns no matter
what. 100% definitely no point deviating from the STL API over that.
2024-06-06 18:01:26 -07:00
Jōshin 03b476f943 Minor small-string errata from #1199
These commits were sitting on a local branch that I neglected to push
before merging. :(

* Use memcpy for string::reserve

* Remove fence comments
2024-06-06 17:56:30 -07:00
Jōshin 8b3e368e9a ctl::string small-string optimization (#1199)
A small-string optimization is a way of reusing inline storage space for
sufficiently small strings, rather than allocating them on the heap. The
current approach takes after an old Facebook string class: it reuses the
highest-order byte for flags and small-string size, in such a way that a
maximally-sized small string will have its last byte zeroed, making it a
null terminator for the C string.

The only flag we have is in the highest-order bit, that says whether the
string is big (set) or small (cleared.) Most of the logic switches based
on the value of this bit; e.g. data() returns big()->p if it's set, else
small()->buf if it's cleared. For a small string, the capacity is always
fixed at sizeof(string) - 1 bytes; we store the length in the last byte,
but we store it as the number of remaining bytes of capacity, so that at
max size, the last byte will read zero and serve as our null terminator.

Morally speaking, our class's storage is a union over two POD C structs.
For now I gravitated towards a slightly more obtuse approach: the string
class itself contains a blob of the right size, and we alias that blob's
pointer for the two structs, taking some care not to run afoul of object
lifetime rules in C++. If anyone wants to improve on this, contributions
are welcome.

This commit also introduces the `ctl::__` namespace. It can't be legally
spelled by library users, and serves as our version of boost's "detail".

We introduced a string::swap function, and we now use that in operator=.
operator= now takes its argument by value, so we never need to check for
the case where the pointers are equal and can just swap the entire store
of the argument with our own, leaving the C++ destructor to free our old
storage afterwards.

There are probably still a few places where our capacity is slightly off
and we grow too fast, although there don't appear to be any where we are
too slow. I will leave these to be fixed in future changes.
2024-06-06 20:50:51 -04:00
Brian df6b384e31 github: add labeler action (#1196)
Bit easier to do this as everything seems to be sorted into logical
folders. You may need to add new labels to support this however.
2024-06-06 05:51:36 -07:00
Brian 280bdec817 github: add issue template (#1195)
copy paste and adapted from llamafile but added a research template as
well for the more technical research tickets
2024-06-06 05:51:06 -07:00
Jōshin 2c5e7ec547 Add terminating :vi on some modelines
Noticed because the settings they specified weren't getting picked up by
editor sessions in those files.
2024-06-05 20:36:55 -07:00
Jōshin fdcb8b2f7e add formatting commit 2024-06-05 16:36:34 -07:00
Jōshin 04c6bc478e vim C++ filetype is still spelled "cpp" 2024-06-05 16:34:47 -07:00
Justine Tunney cc2c1893c5 Fix some nits 2024-06-05 04:05:49 -07:00
5321 changed files with 481620 additions and 320788 deletions

No files matched your search

+8
View File
@@ -1,6 +1,10 @@
# Run this command to always ignore formatting commits in git blame
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Upgraded clang-format to 19.0.0git
89fc95fefd40413706ff1bdaac2e8d98b328dbf1
# vim c++ filetype in modelines
04c6bc478e082263d67c41bedbd033dde2d429eb
# Ran clang-format
f032b5570b4cd87c6bb4abb54c0b98e69c939955
# Applied clang-format update to repo
@@ -21,3 +25,7 @@ c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
da8baf2aa5ce93b958aca90a0ae69f537806324b
# Run clang-format on most sources
369f9740de4534c28d0e81ab2afc99decbb9a3e6
# Get rid of .internal.h convention in LIBC_INTRIN
86d884cce24d773e298a2714c1e3d91ecab9be45
# Remove .internal from more header filenames
31194165d2afca36c2315a6e7ca2f0797dde09e3
+7 -1
View File
@@ -1,4 +1,10 @@
# -*- conf -*-
*.gz binary
/build/bootstrap/*.com binary
*.so binary
*.dll binary
*.dylib binary
/build/bootstrap/* binary
/usr/share/terminfo/* binary
/usr/share/terminfo/*/* binary
/usr/share/zoneinfo/* binary
/usr/share/zoneinfo/*/* binary
+59
View File
@@ -0,0 +1,59 @@
name: Low Severity Bugs
description: Used to report low severity bugs in cosmopolitan (e.g. cosmetic issues, non critical UI glitches)
title: "Bug: "
labels: ["bug", "low severity"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please include information about your system, the steps to reproduce the bug,
and the version of cosmopolitan that you are using.
If possible, please provide a minimal code example that reproduces the bug.
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
for additional technical logging that may allow us to narrow down where the fault occurred.
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. [email protected]
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: What version of our software are you running? (use `--version` to get a version string)
placeholder: "cosmocc (GCC) 12.3.0"
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: What operating system are you seeing the problem on?
multiple: true
options:
- Linux
- Mac
- Windows
- FreeBSD
- OpenBSD
- NetBSD
- BIOS
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
+59
View File
@@ -0,0 +1,59 @@
name: Medium Severity Bug
description: Used to report medium severity bugs in cosmopolitan (e.g. Malfunctioning Features but generally still useable)
title: "Bug: "
labels: ["bug", "medium severity"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please include information about your system, the steps to reproduce the bug,
and the version of cosmopolitan that you are using.
If possible, please provide a minimal code example that reproduces the bug.
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
for additional technical logging that may allow us to narrow down where the fault occurred.
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. [email protected]
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: What version of our software are you running? (use `--version` to get a version string)
placeholder: "cosmocc (GCC) 12.3.0"
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: What operating system are you seeing the problem on?
multiple: true
options:
- Linux
- Mac
- Windows
- FreeBSD
- OpenBSD
- NetBSD
- BIOS
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
+59
View File
@@ -0,0 +1,59 @@
name: High Severity Bug
description: Used to report high severity bugs in cosmopolitan (e.g. Malfunctioning features hindering important common workflow)
title: "Bug: "
labels: ["bug", "high severity"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please include information about your system, the steps to reproduce the bug,
and the version of cosmopolitan that you are using.
If possible, please provide a minimal code example that reproduces the bug.
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
for additional technical logging that may allow us to narrow down where the fault occurred.
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. [email protected]
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: What version of our software are you running? (use `--version` to get a version string)
placeholder: "cosmocc (GCC) 12.3.0"
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: What operating system are you seeing the problem on?
multiple: true
options:
- Linux
- Mac
- Windows
- FreeBSD
- OpenBSD
- NetBSD
- BIOS
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
@@ -0,0 +1,59 @@
name: Critical Severity Bug
description: Used to report critical severity bugs in cosmopolitan (e.g. Crashing, Corrupted, Dataloss)
title: "Bug: "
labels: ["bug", "critical severity"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please include information about your system, the steps to reproduce the bug,
and the version of cosmopolitan that you are using.
If possible, please provide a minimal code example that reproduces the bug.
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
for additional technical logging that may allow us to narrow down where the fault occurred.
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. [email protected]
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: What version of our software are you running? (use `--version` to get a version string)
placeholder: "cosmocc (GCC) 12.3.0"
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: What operating system are you seeing the problem on?
multiple: true
options:
- Linux
- Mac
- Windows
- FreeBSD
- OpenBSD
- NetBSD
- BIOS
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
+51
View File
@@ -0,0 +1,51 @@
name: Enhancement template
description: Used to request enhancements for cosmopolitan
title: "Feature Request: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
[Please post your idea first in Discussion if there is not yet a consensus for this enhancement request. This will help to keep this issue tracker focused on enhancements that the community has agreed needs to be implemented.](https://github.com/jart/cosmopolitan/discussions/categories/ideas)
- type: checkboxes
id: prerequisites
attributes:
label: Prerequisites
description: Please confirm the following before submitting your enhancement request.
options:
- label: I am running the latest code. Mention the version if possible as well.
required: true
- label: I carefully followed the [README.md](https://github.com/jart/cosmopolitan/blob/master/README.md).
required: true
- label: I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
required: true
- label: I reviewed the [Discussions](https://github.com/jart/cosmopolitan/discussions), and have a new and useful enhancement to share.
required: true
- type: textarea
id: feature-description
attributes:
label: Feature Description
description: Please provide a detailed written description of what you were trying to do, and what you expected `cosmopolitan` to do as an enhancement.
placeholder: Detailed description of the enhancement
validations:
required: true
- type: textarea
id: motivation
attributes:
label: Motivation
description: Please provide a detailed written description of reasons why this feature is necessary and how it is useful to `cosmopolitan` users.
placeholder: Explanation of why this feature is needed and its benefits
validations:
required: true
- type: textarea
id: possible-implementation
attributes:
label: Possible Implementation
description: If you have an idea as to how it can be implemented, please write a detailed description. Feel free to give links to external sources or share visuals that might be helpful to understand the details better.
placeholder: Detailed description of potential implementation
validations:
required: false
+52
View File
@@ -0,0 +1,52 @@
name: Research
description: Track new technical research area
title: "Research: "
labels: ["research"]
body:
- type: markdown
attributes:
value: |
Don't forget to check for any [duplicate research issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3A%22research+%F0%9F%94%AC%22)
- type: checkboxes
id: research-stage
attributes:
label: Research Stage
description: Track general state of this research ticket
options:
- label: Background Research (Let's try to avoid reinventing the wheel)
- label: Hypothesis Formed (How do you think this will work and it's effect?)
- label: Strategy / Implementation Forming
- label: Analysis of results
- label: Debrief / Documentation (So people in the future can learn from us)
- type: textarea
id: background
attributes:
label: Previous existing literature and research
description: Whats the current state of the art and whats the motivation for this research?
- type: textarea
id: hypothesis
attributes:
label: Hypothesis
description: How do you think this will work and it's effect?
- type: textarea
id: implementation
attributes:
label: Implementation
description: Got an approach? e.g. a PR ready to go?
- type: textarea
id: analysis
attributes:
label: Analysis
description: How does the proposed implementation behave?
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
+28
View File
@@ -0,0 +1,28 @@
name: Refactor (Maintainers)
description: Used to track refactoring opportunities
title: "Refactor: "
labels: ["refactor"]
body:
- type: markdown
attributes:
value: |
Don't forget to [check for existing refactor issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3Arefactoring) in case it's already covered.
Also you may want to check [Pull request refactor label as well](https://github.com/jart/cosmopolitan/pulls?q=is%3Aopen+is%3Apr+label%3Arefactoring) for duplicates too.
- type: textarea
id: background-description
attributes:
label: Background Description
description: Please provide a detailed written description of the pain points you are trying to solve.
placeholder: Detailed description behind your motivation to request refactor
validations:
required: true
- type: textarea
id: possible-approaches
attributes:
label: Possible Refactor Approaches
description: If you have some idea of possible approaches to solve this problem. You may want to make it a todo list.
placeholder: Your idea of possible refactoring opportunity/approaches
validations:
required: false
+15
View File
@@ -0,0 +1,15 @@
blank_issues_enabled: true
contact_links:
- name: FAQ
url: https://github.com/jart/cosmopolitan/wiki/FAQ
about: Is your question a common one? You may want to check here first.
- name: Got an idea?
url: https://github.com/jart/cosmopolitan/discussions/categories/ideas
about: Pop it there. It may then become an enhancement ticket.
- name: Got a question?
url: https://github.com/jart/cosmopolitan/discussions/categories/q-a
about: Ask a question there!
- name: Want to contribute?
url: https://github.com/jart/cosmopolitan/wiki/contribute
about: Head to the contribution guide page of the wiki for areas you can help with
+49
View File
@@ -0,0 +1,49 @@
# https://github.com/actions/labeler
documentation:
- changed-files:
- any-glob-to-any-file:
- README.md
- LICENSE
- CONTRIBUTING.md
- libc/README.md
- tool/cosmocc/README.md
- third_party/getopt/README.txt
build:
- changed-files:
- any-glob-to-any-file:
- build/**
- Makefile
- '*/*.mk'
examples:
- changed-files:
- any-glob-to-any-file: examples/**
devops:
- changed-files:
- any-glob-to-any-file:
- .github/**
- .clang-format
dsp:
- changed-files:
- any-glob-to-any-file:
- dsp/**
ape:
- changed-files:
- any-glob-to-any-file:
- ape/**
libc:
- changed-files:
- any-glob-to-any-file:
- libc/**
net:
- changed-files:
- any-glob-to-any-file:
- net/**
third_party:
- changed-files:
- any-glob-to-any-file:
- third_party/**
tool:
- changed-files:
- any-glob-to-any-file:
- tool/**
+17
View File
@@ -0,0 +1,17 @@
name: "Pull Request Labeler"
on:
- pull_request_target
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
repository: "jart/cosmopolitan"
- uses: actions/labeler@v5
with:
configuration-path: '.github/labeler.yml'
+24
View File
@@ -0,0 +1,24 @@
name: Nightly cosmocc
on:
schedule:
# https://crontab.guru/#37_4_*_*_*
- cron: "37 4 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
jobs:
build-cosmocc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
sudo cp build/bootstrap/ape.elf /usr/bin/ape
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
- run: tool/cosmocc/package.sh
# https://github.com/actions/upload-artifact/issues/590
- uses: actions/[email protected]
with:
name: cosmocc
path: cosmocc
compression-level: 9
+36
View File
@@ -0,0 +1,36 @@
{
"C_Cpp.default.compilerPath": ".cosmocc/3.9.2/bin/aarch64-linux-cosmo-c++",
"C_Cpp.default.compilerArgs": [
"-nostdinc",
"-nostdlib",
"-iquote.",
"-isystemlibc/isystem",
"-isystemthird_party/libcxx",
"-includelibc/integral/normalize.inc",
"-D_COSMO_SOURCE",
"-D__aarch64__"
],
"[c]": {
"editor.tabSize": 2,
"editor.insertSpaces": true
},
"[cpp]": {
"editor.tabSize": 2,
"editor.insertSpaces": true
},
"[makefile]": {
"editor.tabSize": 8,
"editor.insertSpaces": false
},
"[make]": {
"editor.tabSize": 8,
"editor.insertSpaces": false
},
"[assembly]": {
"editor.tabSize": 8,
"editor.insertSpaces": true
},
"files.associations": {
"log.h": "c"
}
}
+82 -78
View File
@@ -101,23 +101,22 @@ XARGS ?= xargs -P4 -rs8000
DOT ?= dot
CLANG = clang
TMPDIR = o/tmp
AR = build/bootstrap/ar
CP = build/bootstrap/cp
RM = build/bootstrap/rm -f
GZIP = build/bootstrap/gzip
ECHO = build/bootstrap/echo
CHMOD = build/bootstrap/chmod
TOUCH = build/bootstrap/touch
PKG = build/bootstrap/package
MKDEPS = build/bootstrap/mkdeps
ZIPOBJ = build/bootstrap/zipobj
ZIPCOPY = build/bootstrap/zipcopy
PECHECK = build/bootstrap/pecheck
FIXUPOBJ = build/bootstrap/fixupobj
MKDIR = build/bootstrap/mkdir -p
COMPILE = build/bootstrap/compile -V9 -M2048m -P8192 $(QUOTA)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
AR = $(BOOTSTRAP)/ar.ape
CP = $(BOOTSTRAP)/cp.ape
RM = $(BOOTSTRAP)/rm.ape -f
GZIP = $(BOOTSTRAP)/gzip.ape
ECHO = $(BOOTSTRAP)/echo.ape
CHMOD = $(BOOTSTRAP)/chmod.ape
TOUCH = $(BOOTSTRAP)/touch.ape
PKG = $(BOOTSTRAP)/package.ape
MKDEPS = $(BOOTSTRAP)/mkdeps
ZIPOBJ = $(BOOTSTRAP)/zipobj
ZIPCOPY = $(BOOTSTRAP)/zipcopy
PECHECK = $(BOOTSTRAP)/pecheck
FIXUPOBJ = $(BOOTSTRAP)/fixupobj
OBJBINCOPY = $(BOOTSTRAP)/objbincopy
MKDIR = $(BOOTSTRAP)/mkdir.ape -p
COMPILE = $(BOOTSTRAP)/compile.ape -V9 -M2048m -P8192 $(QUOTA)
# the default build modes is empty string
# on x86_64 hosts, MODE= is the same as MODE=x86_64
@@ -133,14 +132,13 @@ endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi studio freebsdarm
HOSTS ?= pi pi5 studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu openbsd netbsd win10
endif
ZIPOBJ_FLAGS += -a$(ARCH)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
export ADDR2LINE
export LC_ALL
@@ -149,9 +147,12 @@ export MODE
export SOURCE_DATE_EPOCH
export TMPDIR
COSMOCC = .cosmocc/3.3.5
COSMOCC = .cosmocc/3.9.2
BOOTSTRAP = $(COSMOCC)/bin
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.9.2 f4ff13af65fcd309f3f1cfd04275996fb7f72a4897726628a8c9cf732e850193)
IGNORE := $(shell $(MKDIR) $(TMPDIR))
AS = $(TOOLCHAIN)as
CC = $(TOOLCHAIN)gcc
@@ -256,7 +257,6 @@ include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
include libc/proc/BUILD.mk # │ You can now use threads
include libc/dlopen/BUILD.mk # │ You can now use processes
include libc/thread/BUILD.mk # │ You can finally call malloc()
include ctl/BUILD.mk # │
include third_party/zlib/BUILD.mk # │
include libc/stdio/BUILD.mk # │
include tool/hello/BUILD.mk # │
@@ -278,6 +278,8 @@ include libc/x/BUILD.mk # │
include dsp/scale/BUILD.mk # │
include dsp/mpeg/BUILD.mk # │
include dsp/tty/BUILD.mk # │
include dsp/audio/BUILD.mk # │
include dsp/prog/BUILD.mk # │
include dsp/BUILD.mk # │
include third_party/stb/BUILD.mk # │
include third_party/mbedtls/BUILD.mk # │
@@ -285,14 +287,14 @@ include third_party/ncurses/BUILD.mk # │
include third_party/readline/BUILD.mk # │
include third_party/libunwind/BUILD.mk # |
include third_party/libcxxabi/BUILD.mk # |
include third_party/double-conversion/BUILD.mk # │
include ctl/BUILD.mk # │
include third_party/libcxx/BUILD.mk # │
include third_party/openmp/BUILD.mk # │
include third_party/double-conversion/BUILD.mk # │
include third_party/pcre/BUILD.mk # │
include third_party/less/BUILD.mk # │
include net/https/BUILD.mk # │
include third_party/regex/BUILD.mk # │
include third_party/bash/BUILD.mk #─┘
include third_party/regex/BUILD.mk #─┘
include third_party/tidy/BUILD.mk
include third_party/BUILD.mk
include third_party/nsync/testing/BUILD.mk
@@ -428,67 +430,69 @@ HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MO
loc: private .UNSANDBOXED = 1
loc: o/$(MODE)/tool/build/summy
find -name \*.h -or -name \*.c -or -name \*.S | \
find -name \*.h -or -name \*.hpp -or -name \*.c -or -name \*.cc -or -name \*.cpp -or -name \*.S -or -name \*.mk | \
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
# FROM HIGHEST LEVEL TO LOWEST LEVEL
COSMOPOLITAN_OBJECTS = \
TOOL_ARGS \
NET_HTTP \
LIBC_SOCK \
LIBC_NT_WS2_32 \
LIBC_NT_IPHLPAPI \
LIBC_X \
THIRD_PARTY_GETOPT \
LIBC_LOG \
THIRD_PARTY_TZ \
THIRD_PARTY_OPENMP \
THIRD_PARTY_MUSL \
THIRD_PARTY_ZLIB_GZ \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
LIBC_STDIO \
THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \
LIBC_THREAD \
LIBC_PROC \
THIRD_PARTY_NSYNC_MEM \
COSMOPOLITAN = \
CTL \
LIBC_MEM \
THIRD_PARTY_DLMALLOC \
LIBC_DLOPEN \
LIBC_RUNTIME \
THIRD_PARTY_NSYNC \
LIBC_ELF \
LIBC_IRQ \
DSP_AUDIO \
LIBC_CALLS \
LIBC_SYSV_CALLS \
LIBC_VGA \
LIBC_NT_PSAPI \
LIBC_NT_POWRPROF \
LIBC_NT_PDH \
LIBC_NT_GDI32 \
LIBC_NT_COMDLG32 \
LIBC_NT_USER32 \
LIBC_NT_NTDLL \
LIBC_NT_ADVAPI32 \
LIBC_NT_SYNCHRONIZATION \
LIBC_DLOPEN \
LIBC_ELF \
LIBC_FMT \
THIRD_PARTY_ZLIB \
THIRD_PARTY_PUFF \
THIRD_PARTY_COMPILER_RT \
LIBC_TINYMATH \
THIRD_PARTY_XED \
LIBC_INTRIN \
LIBC_IRQ \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_COMDLG32 \
LIBC_NT_GDI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_PDH \
LIBC_NT_POWRPROF \
LIBC_NT_PSAPI \
LIBC_NT_REALTIME \
LIBC_NT_SYNCHRONIZATION \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_INTRIN \
LIBC_NT_BCRYPTPRIMITIVES \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E
LIBC_SYSV_CALLS \
LIBC_THREAD \
LIBC_TINYMATH \
LIBC_VGA \
LIBC_X \
NET_HTTP \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
THIRD_PARTY_MUSL \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_OPENMP \
THIRD_PARTY_PUFF \
THIRD_PARTY_REGEX \
THIRD_PARTY_TZ \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
THIRD_PARTY_ZLIB_GZ \
TOOL_ARGS \
COSMOPOLITAN_H_PKGS = \
APE \
DSP_AUDIO \
LIBC \
LIBC_CALLS \
LIBC_ELF \
@@ -532,14 +536,14 @@ COSMOCC_PKGS = \
THIRD_PARTY_INTEL
o/$(MODE)/cosmopolitan.a: \
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x))))
COSMOCC_HDRS = \
$(wildcard libc/integral/*) \
$(foreach x,$(COSMOCC_PKGS),$($(x)_HDRS)) \
$(foreach x,$(COSMOCC_PKGS),$($(x)_INCS))
o/cosmocc.h.txt: Makefile
o/cosmocc.h.txt: Makefile libc $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x)))) $(HDRS) $(INCS)
$(file >$@, $(call uniq,$(COSMOCC_HDRS)))
COSMOPOLITAN_H_ROOT_HDRS = \
+1 -1
View File
@@ -244,7 +244,7 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
| Platform | Min Version | Circa |
| :--- | ---: | ---: |
| AMD | K8 Venus | 2005 |
| AMD | K8 | 2003 |
| Intel | Core | 2006 |
| Linux | 2.6.18 | 2007 |
| Windows | 8 [1] | 2012 |
+12 -16
View File
@@ -45,10 +45,10 @@ o/$(MODE)/ape: $(APE)
o/$(MODE)/ape/aarch64.lds: \
ape/aarch64.lds \
libc/zip.internal.h \
libc/zip.h \
libc/thread/tls.h \
libc/calls/struct/timespec.h \
libc/macros.internal.h \
libc/macros.h \
libc/str/str.h
APE_LOADER_LDFLAGS = \
@@ -162,9 +162,8 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
libc/dce.h \
libc/elf/def.h \
libc/thread/tls.h \
libc/intrin/asancodes.h \
libc/macho.internal.h \
libc/macros.internal.h \
libc/macho.h \
libc/macros.h \
libc/nexgen32e/uart.internal.h \
libc/calls/metalfile.internal.h \
libc/nt/pedef.internal.h \
@@ -189,9 +188,8 @@ o/$(MODE)/ape/ape-copy-self.o: \
libc/dce.h \
libc/elf/def.h \
libc/thread/tls.h \
libc/intrin/asancodes.h \
libc/macho.internal.h \
libc/macros.internal.h \
libc/macho.h \
libc/macros.h \
libc/nexgen32e/uart.internal.h \
libc/calls/metalfile.internal.h \
libc/nt/pedef.internal.h \
@@ -220,10 +218,10 @@ o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -f -o $@ $<
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -f -o $@ $<
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy -fm -o $@ $<
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -fm -o $@ $<
APE_LOADER_LDFLAGS = \
-static \
@@ -248,8 +246,6 @@ o/$(MODE)/ape: $(APE_CHECKS) \
o/$(MODE)/ape/ape.lds \
o/$(MODE)/ape/ape.elf \
o/$(MODE)/ape/ape.macho \
o/$(MODE)/ape/ape-copy-self.o \
o/$(MODE)/ape/ape-no-modify-self.o
endif
@@ -263,8 +259,8 @@ o/$(MODE)/ape/ape.o: \
libc/thread/tls.h \
ape/ape.internal.h \
ape/macros.internal.h \
libc/macho.internal.h \
libc/macros.internal.h \
libc/macho.h \
libc/macros.h \
libc/sysv/consts/prot.h \
libc/nt/pedef.internal.h \
libc/runtime/pc.internal.h \
@@ -285,7 +281,7 @@ o/$(MODE)/ape/ape.lds: \
libc/dce.h \
libc/elf/def.h \
libc/elf/pf2prot.internal.h \
libc/macros.internal.h \
libc/macros.h \
libc/nt/pedef.internal.h \
libc/str/str.h \
libc/zip.internal.h
libc/zip.h
+8 -8
View File
@@ -1,6 +1,7 @@
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/sysv/consts/prot.h"
#include "libc/thread/tls.h"
ENTRY(_start)
@@ -11,7 +12,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
SECTIONS {
. = SEGMENT_START("text-segment", 0x010000000000);
. = SEGMENT_START("text-segment", 0x000800000000);
__executable_start = .;
. += SIZEOF_HEADERS;
@@ -102,10 +103,8 @@ SECTIONS {
*(.eh_frame_entry .eh_frame_entry.*)
}
.eh_frame : ONLY_IF_RO {
KEEP(*(.eh_frame))
*(.eh_frame.*)
}
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
.gcc_except_table : ONLY_IF_RO {
*(.gcc_except_table .gcc_except_table.*)
@@ -126,9 +125,11 @@ SECTIONS {
. += CONSTANT(MAXPAGESIZE);
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
.eh_frame : ONLY_IF_RW {
.eh_frame : {
__eh_frame_start = .;
KEEP(*(.eh_frame))
*(.eh_frame.*)
__eh_frame_end = .;
}
.gnu_extab : ONLY_IF_RW {
@@ -285,8 +286,7 @@ SECTIONS {
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
ape_stack_round = -ape_stack_align;
ape_stack_prot = PROT_READ | PROT_WRITE;
_tls_size = _tbss_end - _tdata_start;
_tdata_size = _tdata_end - _tdata_start;
+6
View File
@@ -16,6 +16,12 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#ifndef __APPLE__
#error "ape/ape-m1.c is for apple silicon. chances you want ape/loader.c"
#endif
#ifndef __aarch64__
#error "ape/ape-m1.c is for apple silicon; you want: make o//ape/ape.macho"
#endif
#include <assert.h>
#include <dispatch/dispatch.h>
#include <dlfcn.h>
+2 -2
View File
@@ -37,7 +37,7 @@
#include "libc/calls/metalfile.internal.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/macho.internal.h"
#include "libc/macho.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/nt/pedef.internal.h"
#include "libc/runtime/pc.internal.h"
@@ -761,7 +761,7 @@ ape_phdrs:
.quad 0
.quad 0
.quad 0
.stub ape_stack_align,quad
.quad 16
#if SupportsOpenbsd() || SupportsNetbsd()
.long PT_NOTE
+13 -3
View File
@@ -310,7 +310,7 @@ SECTIONS {
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
/*END: morphable code */
__privileged_start = .;
*(.privileged)
*(.privileged .privileged.*)
__privileged_end = .;
KEEP(*(.ape.pad.text))
@@ -329,6 +329,10 @@ SECTIONS {
*(.ubsan.types)
*(.ubsan.data)
__eh_frame_hdr_start_actual = .;
*(.eh_frame_hdr)
__eh_frame_hdr_end_actual = .;
/* Legal Notices */
__notices = .;
KEEP(*(.notice))
@@ -422,6 +426,11 @@ SECTIONS {
KEEP(*(.dtors))
__fini_array_end = .;
__eh_frame_start = .;
KEEP(*(.eh_frame))
*(.eh_frame.*)
__eh_frame_end = .;
/*BEGIN: Post-Initialization Read-Only */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
@@ -588,8 +597,6 @@ ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
ape_stack_filesz = 0;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
ape_stack_round = -ape_stack_align;
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
ape_note_filesz = ape_note_end - ape_note;
@@ -603,6 +610,9 @@ ape_text_memsz = ape_text_filesz;
ape_text_align = CONSTANT(COMMONPAGESIZE);
ape_text_rva = RVA(ape_text_vaddr);
__eh_frame_hdr_start = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_start_actual : 0;
__eh_frame_hdr_end = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_end_actual : 0;
/* we roundup here because xnu wants the file load segments page-aligned */
/* but we don't want to add the nop padding to the ape program, so we'll */
/* let ape.S dd read past the end of the file into the wrapping binaries */
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
// Calls _start() function of loaded program.
//
+2 -2
View File
@@ -16,10 +16,10 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macho.internal.h"
#include "libc/macho.h"
#include "libc/sysv/consts/prot.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
// Apple Mach-O Executable Headers
// Fixups are applied by objbincopy
+9 -8
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#ifndef APE_MACROS_H_
#define APE_MACROS_H_
#include "libc/macros.internal.h"
#include "libc/macros.h"
#ifdef __ASSEMBLER__
/* clang-format off */
@@ -84,9 +84,10 @@
/* clang-format on */
#elif defined(__LINKER__)
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
#define BCX_NIBBLE(X) \
((((X) & 0xf) > 0x9) ? ((X) & 0xf) + 0x37 : ((X) & 0xf) + 0x30)
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
#define BCXSTUB(SYM, X) \
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
@@ -98,12 +99,12 @@
*
* <p>This allows linker scripts to generate printf commands.
*/
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
#define BCO_OCTET(X) (((X) & 0x7) + 0x30)
#define BCOB_UNIT(X) \
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
(BCO_OCTET(((X) & 0xff) >> 6) << 8) | 0x5c)
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I) * 8)))
#define PFSTUB2(SYM, X) \
HIDDEN(SYM = (X)); \
PFBYTE(SYM, X, 0); \
@@ -132,7 +133,7 @@
#define SHSTUB2(SYM, X) \
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
#define BCD_SMEAR(X) ((X) + (X)*10000)
#define BCD_SMEAR(X) ((X) + (X) * 10000)
#define BCD_LEFT(X) \
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
+703
View File
@@ -0,0 +1,703 @@
# Actually Portable Executable Specification v0.1
Actually Portable Executable (APE) is an executable file format that
polyglots the Windows Portable Executable (PE) format with a UNIX Sixth
Edition style shell script that doesn't have a shebang. This makes it
possible to produce a single file binary that executes on the stock
installations of the many OSes and architectures.
## Supported OSes and Architectures
- AMD64
- Linux
- MacOS
- Windows
- FreeBSD
- OpenBSD
- NetBSD
- BIOS
- ARM64
- Linux
- MacOS
- FreeBSD
- Windows (non-native)
## File Header
APE defines three separate file magics, all of which are 8 characters
long. Any file that starts with one of these magic values can be
considered an APE program.
### (1) APE MZ Magic
- ASCII: `MZqFpD='`
- Hex: 4d 5a 71 46 70 44 3d 27
This is the canonical magic used by almost all APE programs. It enables
maximum portability between OSes. When interpreted as a shell script, it
is assigning a single quoted string to an unused variable. The shell
will then ignore subsequent binary content that's placed inside the
string.
It is strongly recommended that this magic value be immediately followed
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
Zsh impose a binary safety check before handing off files that don't
have a shebang to `/bin/sh`. That check applies to the first line, which
can't contain NUL characters.
The letters were carefully chosen so as to be valid x86 instructions in
all operating modes. This makes it possible to store a BIOS bootloader
disk image inside an APE binary. For example, simple CLI programs built
with Cosmopolitan Libc will boot from BIOS into long mode if they're
treated as a floppy disk image.
The letters also allow for the possibility of being treated on x86-64 as
a flat executable, where the PE / ELF / Mach-O executable structures are
ignored, and execution simply begins at the beginning of the file,
similar to how MS-DOS .COM binaries work.
The 0x4a relative offset of the magic causes execution to jump into the
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
Libc use tricks in the MS-DOS stub to check the operating mode and then
jump to the appropriate entrypoint, e.g. `_start()`.
#### Decoded as i8086
```asm
dec %bp
pop %dx
jno 0x4a
jo 0x4a
```
#### Decoded as i386
```asm
push %ebp
pop %edx
jno 0x4a
jo 0x4a
```
#### Decoded as x86-64
```asm
rex.WRB
pop %r10
jno 0x4a
jo 0x4a
```
### (2) APE UNIX-Only Magic
- ASCII: `jartsr='`
- Hex: 6a 61 72 74 73 72 3d 27
Being a novel executable format that was first published in 2020, the
APE file format is less understood by industry tools compared to the PE,
ELF, and Mach-O executable file formats, which have been around for
decades. For this reason, APE programs that use the MZ magic above can
attract attention from Windows AV software, which may be unwanted by
developers who aren't interested in targeting the Windows platform.
Therefore the `jartsr='` magic is defined which enables the creation of
APE binaries that can safely target all non-Windows platforms. Even
though this magic is less common, APE interpreters and binfmt-misc
installations MUST support this.
It is strongly recommended that this magic value be immediately followed
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
Zsh impose a binary safety check before handing off files that don't
have a shebang to `/bin/sh`. That check applies to the first line, which
can't contain NUL characters.
The letters were carefully chosen so as to be valid x86 instructions in
all operating modes. This makes it possible to store a BIOS bootloader
disk image inside an APE binary. For example, simple CLI programs built
with Cosmopolitan Libc will boot from BIOS into long mode if they're
treated as a floppy disk image.
The letters also allow for the possibility of being treated on x86-64 as
a flat executable, where the PE / ELF / Mach-O executable structures are
ignored, and execution simply begins at the beginning of the file,
similar to how MS-DOS .COM binaries work.
The 0x78 relative offset of the magic causes execution to jump into the
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
Libc use tricks in the MS-DOS stub to check the operating mode and then
jump to the appropriate entrypoint, e.g. `_start()`.
#### Decoded as i8086 / i386 / x86-64
```asm
push $0x61
jb 0x78
jae 0x78
```
### (3) APE Debug Magic
- ASCII: `APEDBG='`
- Hex: 41 50 45 44 42 47 3d 27
While APE files must be valid shell scripts, in practice, UNIX systems
will oftentimes be configured to provide a faster safer alternative to
loading an APE binary through `/bin/sh`. The Linux Kernel can be patched
to have execve() recognize the APE format and directly load its embedded
ELF header. Linux systems can also use binfmt-misc to recognize APE's MZ
and jartsr magic, and pass them to a userspace program named `ape` that
acts as an interpreter. In such environments, the need sometimes arises
to be able to test that the `/bin/sh` is working correctly, in which
case the `APEDBG='` magic is RECOMMENDED.
APE interpreters, execve() implementations, and binfmt-misc installs
MUST ignore this magic. If necessary, steps can be taken to help files
with this magic be passed to `/bin/sh` like a normal shebang-less shell
script for execution.
## Embedded ELF Header
APE binaries MAY embed an ELF header inside them. Unlike conventional
executable file formats, this header is not stored at a fixed offset.
It's instead encoded as octal escape codes in a shell script `printf`
statement. For example:
```
printf '\177ELF\2\1\1\011\0\0\0\0\0\0\0\0\2\0\076\0\1\0\0\0\166\105\100\000\000\000\000\000\060\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\165\312\1\1\100\0\070\0\005\000\0\0\000\000\000\000'
```
This `printf` statement MUST appear in the first 8192 bytes of the APE
executable, so as to limit how much of the initial portion of a file an
interpreter must load.
Multiple such `printf` statements MAY appear in the first 8192 bytes, in
order to specify multiple architectures. For example, fat binaries built
by the `apelink` program (provided by Cosmo Libc) will have two encoded
ELF headers, for AMD64 and ARM64, each of which point into the proper
file offsets for their respective native code. Therefore, kernels and
interpreters which load the APE format directly MUST check the
`e_machine` field of the `Elf64_Ehdr` that's decoded from the octal
codes, before accepting a `printf` shell statement as valid.
These printf statements MUST always use only unescaped ASCII characters
or octal escape codes. These printf statements MUST NOT use space saving
escape codes such as `\n`. For example, rather than saying `\n` it would
be valid to say `\012` instead. It's also valid to say `\12` but only if
the encoded characters that follow aren't an octal digit.
For example, the following algorithm may be used for parsing octal:
```c
static int ape_parse_octal(const unsigned char page[8192], int i, int *pc)
{
int c;
if ('0' <= page[i] && page[i] <= '7') {
c = page[i++] - '0';
if ('0' <= page[i] && page[i] <= '7') {
c *= 8;
c += page[i++] - '0';
if ('0' <= page[i] && page[i] <= '7') {
c *= 8;
c += page[i++] - '0';
}
}
*pc = c;
}
return i;
}
```
APE aware interpreters SHOULD only take `e_machine` into consideration.
It is the responsibility of the `_start()` function to detect the OS.
Therefore, multiple `printf` statements are only embedded in the shell
script for different CPU architectures.
The OS ABI field of an APE embedded `Elf64_Ehdr` SHOULD be set to
`ELFOSABI_FREEBSD`, since it's the only UNIX OS APE supports that
actually checks the field. However different values MAY be chosen for
binaries that don't intend to have FreeBSD in their support vector.
Counter-intuitively, the ARM64 ELF header is used on the MacOS ARM64
platform when loading from fat binaries.
## Embedded Mach-O Header (x86-64 only)
APE shell scripts that support MacOS on AMD64 must use the `dd` command
in a very specific way to specify how the embedded binary Macho-O header
is copied backward to the start of the file. For example:
```
dd if="$o" of="$o" bs=8 skip=433 count=66 conv=notrunc
```
These `dd` statements have traditionally been generated by the GNU as
and ld.bfd programs by encoding ASCII into 64-bit linker relocations,
which necessitated a fixed width for integer values. It took several
iterations over APE's history before we eventually got it right:
- `arg=" 9293"` is how we originally had ape do it
- `arg=$(( 9293))` b/c busybox sh disliked quoted space
- `arg=9293 ` is generated by modern apelink program
Software that parses the APE file format, which needs to extract the
Macho-O x86-64 header SHOULD support the old binaries that use the
previous encodings. To make backwards compatibility simple the following
regular expression may be used, which generalizes to all defined
formats:
```c
regcomp(&rx,
"bs=" // dd block size arg
"(['\"] *)?" // #1 optional quote w/ space
"(\\$\\(\\( *)?" // #2 optional math w/ space
"([[:digit:]]+)" // #3
"( *\\)\\))?" // #4 optional math w/ space
"( *['\"])?" // #5 optional quote w/ space
" +" //
"skip=" // dd skip arg
"(['\"] *)?" // #6 optional quote w/ space
"(\\$\\(\\( *)?" // #7 optional math w/ space
"([[:digit:]]+)" // #8
"( *\\)\\))?" // #9 optional math w/ space
"( *['\"])?" // #10 optional quote w/ space
" +" //
"count=" // dd count arg
"(['\"] *)?" // #11 optional quote w/ space
"(\\$\\(\\( *)?" // #12 optional math w/ space
"([[:digit:]]+)", // #13
REG_EXTENDED);
```
For further details, see the canonical implementation in
`cosmopolitan/tool/build/assimilate.c`.
## Static Linking
Actually Portable Executables are always statically linked. This
revision of the specification does not define any facility for storing
code in dynamic shared objects.
Cosmopolitan Libc provides a solution that enables APE binaries have
limited access to dlopen(). By manually loading a platform-specific
executable and asking the OS-specific libc's dlopen() to load
OS-specific libraries, it becomes possible to use GPUs and GUIs. This
has worked great for AI projects like llamafile.
There is no way for an Actually Portable Executable to interact with
OS-specific dynamic shared object extension modules to programming
languages. For example, a Lua interpreter compiled as an Actually
Portable Executable would have no way of linking extension libraries
downloaded from the Lua Rocks package manager. This is primarily because
different OSes define incompatible ABIs.
While it was possible to polyglot PE+ELF+MachO to create multi-OS
executables, it simply isn't possible to do that same thing for
DLL+DYLIB+SO. Therefore, in order to have DSOs, APE would need to either
choose one of the existing formats or invent one of its own, and then
develop its own parallel ecosystem of extension software. In the future,
the APE specification may expand to encompass this. However the focus to
date has been exclusively on executables with limited dlopen() support.
## Application Binary Interface (ABI)
APE binaries use the System V ABI, as defined by:
- [System V ABI - AMD64 Architecture Processor Supplement](https://gitlab.com/x86-psABIs/x86-64-ABI)
- AARCH64 has a uniform consensus defined by ARM Limited
There are however a few changes we've had to make.
### No Red Zone
Actually Portable Executables that have Windows and/or bare metal in
their support vector MUST be compiled using `-mno-red-zone`. This is
because, on Windows, DLLs and other software lurking in the va-space
might use tricks like SetThreadContext() to take control of a thread
whereas on bare metal, it's also generally accepted that kernel-mode
code cannot assume a red zone either due to hardware interrupts that
pull the exact same kinds of stunts.
APE software that only has truly System V ABI conformant OSes (e.g.
Linux) in their support vector MAY use the red zone optimization.
### Thread Local Storage
#### aarch64
Here's the TLS memory layout on aarch64:
```
x28
%tpidr_el0
│
│ _Thread_local
┌───┼───┬──────────┬──────────┐
│tib│dtv│ .tdata │ .tbss │
├───┴───┴──────────┴──────────┘
│
__get_tls()
```
The ARM64 code in actually portable executables use the `x28` register
to store the address of the thread information block. All aarch64 code
linked into these executables SHOULD be compiled with `-ffixed-x28`
which is supported by both Clang and GCC.
The runtime library for an actually portable executables MAY choose to
use `tpidr_el0` instead, if OSes like MacOS aren't being targeted. For
example, if the goal is to create a Linux-only fat binary linker program
for Musl Libc, then choosing to use the existing `tpidr_el0` convention
would be friction-free alternative.
It's not possible for an APE runtime that targets the full range of OSes
to use the `tpidr_el0` register for TLS because Apple won't allow it. On
MacOS ARM64 systems, this register can only be used by a runtime to
implement the `sched_getcpu()` system call. It's reserved by MacOS.
#### x86-64
Here's the TLS memory layout on x86_64:
```
__get_tls()
│
%fs OpenBSD/NetBSD
_Thread_local │
┌───┬──────────┬──────────┼───┐
│pad│ .tdata │ .tbss │tib│
└───┴──────────┴──────────┼───┘
│
Linux/FreeBSD/Windows/Mac %gs
```
Quite possibly the greatest challenge in Actually Portable Executable
working, has been overcoming the incompatibilities between OSes in how
thread-local storage works on x86-64. The AMD64 architecture defines two
special segment registers. Every OS uses one of these segment registers
to implement TLS support. However not all OSes agree on which register
to use. Some OSes grant userspace the power to define either of these
registers to hold any value that is desired. Some OSes only effectively
allow a single one of them to be changed. Lastly, some OSes, e.g.
Windows, claim ownership of the memory layout these registers point
towards too.
Here's a breakdown on how much power is granted to userspace runtimes by
each OS when it comes to changing amd64 segment registers.
| | %fs | %gs |
|---------|--------------|--------------|
| Linux | unrestricted | unrestricted |
| MacOS | inaccessible | unrestricted |
| Windows | inaccessible | restricted |
| FreeBSD | unrestricted | unrestricted |
| NetBSD | unrestricted | broken |
| OpenBSD | unrestricted | inaccessible |
Therefore, regardless of which register one we choose, some OSes are
going to be incompatible.
APE binaries are always built with a Linux compiler. So another issue
arises in the fact that our Linux-flavored GCC and Clang toolchains
(which are used to produce cross-OS binaries) are also only capable of
producing TLS instructions that use the %fs convention.
To solve these challenges, the `cosmocc` compiler will rewrite binary
objects after they've been compiled by GCC, so that the `%gs` register
is used, rather than `%fs`. Morphing x86-64 binaries after they've been
compiled is normally difficult, due to the complexity of the machine
instruction language. However GCC provides `-mno-tls-direct-seg-refs`
which greatly reduces the complexity of this task. This flag forgoes
some optimizations to make the generated code simpler. Rather than doing
clever arithmetic with `%fs` prefixes, the compiler will always generate
the thread information block address load as a separate instruction.
```c
// Change AMD code to use %gs:0x30 instead of %fs:0
// We assume -mno-tls-direct-seg-refs has been used
static void ChangeTlsFsToGs(unsigned char *p, size_t n) {
unsigned char *e = p + n - 9;
while (p <= e) {
// we're checking for the following expression:
// 0144 == p[0] && // %fs
// 0110 == (p[1] & 0373) && // rex.w (and ignore rex.r)
// (0213 == p[2] || // mov reg/mem → reg (word-sized)
// 0003 == p[2]) && // add reg/mem → reg (word-sized)
// 0004 == (p[3] & 0307) && // mod/rm (4,reg,0) means sib → reg
// 0045 == p[4] && // sib (5,4,0) → (rbp,rsp,0) → disp32
// 0000 == p[5] && // displacement (von Neumann endian)
// 0000 == p[6] && // displacement
// 0000 == p[7] && // displacement
// 0000 == p[8] // displacement
uint64_t w = READ64LE(p) & READ64LE("\377\373\377\307\377\377\377\377");
if ((w == READ64LE("\144\110\213\004\045\000\000\000") ||
w == READ64LE("\144\110\003\004\045\000\000\000")) &&
!p[8]) {
p[0] = 0145; // change %fs to %gs
p[5] = 0x30; // change 0 to 0x30
p += 9;
} else {
++p;
}
}
}
```
By favoring `%gs` we've now ensured friction-free compatibility for the
APE runtime on MacOS, Linux, and FreeBSD which are all able to conform
easily to this convention. However additional work needs to be done at
runtime when an APE program is started on Windows, OpenBSD, and NetBSD.
On these platforms, all executable pages must be faulted and morphed to
fixup the TLS instructions.
On OpenBSD and NetBSD, this is as simple as undoing the example
operation above. Earlier at compile-time we turned `%fs` into `%gs`.
Now, at runtime, `%gs` must be turned back into `%fs`. Since the
executable is morphing itself, this is easier said than done.
OpenBSD for example enforces a `W^X` invariant. Code that's executing
can't modify itself at the same time. The way Cosmopolitan solves this
is by defining a special part of the binary called `.text.privileged`.
This section is aligned to page boundaries. A GNU ld linker script is
used to ensure that code which morphs code is placed into this section,
through the use of a header-defined cosmo-specific keyword `privileged`.
Additionally, the `fixupobj` program is used by the Cosmo build system
to ensure that compiled objects don't contain privileged functions that
call non-privileged functions. Needless to say, `mprotect()` needs to be
a privileged function, so that it can be used to disable the execute bit
on all other parts of the executable except for the privileged section,
thereby making it writable. Once this has been done, code can change.
On Windows the displacement bytes of the TLS instruction are changed to
use the `%gs:0x1480+i*8` ABI where `i` is a number assigned by the WIN32
`TlsAlloc()` API. This avoids the need to call `TlsGetValue()` which is
implemented this exact same way under the hood. Even though 0x1480 isn't
explicitly documented by MSDN, this ABI is believed to be stable because
MSVC generates binaries that use this offset directly. The only caveat
is that `TlsAlloc()` must be called as early in the runtime init as
possible, to ensure an index less than 64 is returned.
### Thread Information Block (TIB)
The Actually Portable Executable Thread Information Block (TIB) is
defined by this version of the specification as follows:
- The 64-bit TIB self-pointer is stored at offset 0x00.
- The 64-bit TIB self-pointer is also stored at offset 0x30.
- The 32-bit `errno` value is stored at offset 0x3c.
All other parts of the thread information block should be considered
unspecified and therefore reserved for future specifications.
The APE thread information block is aligned on a 64-byte boundary.
Cosmopolitan Libc v3.5.8 (c. 2024-07-21) currently implements a thread
information block that's 512 bytes in size.
### Foreign Function Calls
Even though APE programs always use the System V ABI, there arises the
occasional need to interface with foreign functions, e.g. WIN32. The
`__attribute__((__ms_abi__))` annotation introduced by GCC v6 is used
for this purpose.
The ability to change a function's ABI on a case-by-case basis is
surprisingly enough supported by GCC, Clang, NVCC, and even the AMD HIP
compilers for both UNIX systems and Windows. All of these compilers
support both the System V ABI and the Microsoft x64 ABI.
APE binaries will actually favor the Microsoft ABI even when running on
UNIX OSes for certain dlopen() use-cases. For example, if we control the
code to a CUDA module, which we compile on each OS separately from our
main APE binary, then any function that's inside the APE binary whose
pointer may be passed into a foreign module SHOULD be compiled to use
the Microsoft ABI. This is because in practice the OS-specific module
may need to be compiled by MSVC, where MS ABI is the *only* ABI, which
forces our UNIX programs to partially conform. Thankfully, all UNIX
compilers support doing it on a case-by-case basis.
### Char Signedness
Actually Portable Executable defines `char` as signed.
Therefore conformant APE software MUST use `-fsigned-char` when building
code for aarch64, as well as any other architecture that (unlike x86-64)
would otherwise define `char` as being `unsigned char` by default.
This decision was one of the cases where it made sense to offer a more
consistent runtime experience for fat multi-arch binaries. However you
SHOULD still write code to assume `char` can go either way. But if all
you care about is using APE, then you CAN assume `char` is signed.
### Long Double
On AMD64 platforms, APE binaries define `long double` as 80-bit.
On ARM64 platforms, APE binaries define `long double` as 128-bit.
We accept inconsistency in this case, because hardware acceleration is
far more valuable than stylistic consistency in the case of mathematics.
One challenge arises on AMD64 for supporting `long double` across OSes.
Unlike UNIX systems, the Windows Executive on x86-64 initializes the x87
FPU to have double (64-bit) precision rather than 80-bit. That's because
code compiled by MSVC treats `long double` as though it were `double` to
prefer always using the more modern SSE instructions. However System V
requires genuine 80-bit `long double` support on AMD64.
Therefore, if an APE program detects that it's been started on a Windows
x86-64 system, then it SHOULD use the following assembly to initialize
the x87 FPU in System V ABI mode.
```asm
fldcw 1f(%rip)
.rodata
.balign 2
// 8087 FPU Control Word
// IM: Invalid Operation ───────────────┐
// DM: Denormal Operand ───────────────┐│
// ZM: Zero Divide ───────────────────┐││
// OM: Overflow ─────────────────────┐│││
// UM: Underflow ───────────────────┐││││
// PM: Precision ──────────────────┐│││││
// PC: Precision Control ───────┐ ││││││
// {float,∅,double,long double}│ ││││││
// RC: Rounding Control ──────┐ │ ││││││
// {even, →-∞, →+∞, →0} │┌┤ ││││││
// ┌┤││ ││││││
// d││││rr││││││
1: .short 0b00000000000000000001101111111
.previous
```
## Executable File Alignment
Actually Portable Executable is a statically-linked flat executable file
format that is, as a thing in itself, agnostic to file alignments. For
example, the shell script payload at the beginning of the file and its
statements have no such requirements. Alignment requirements are however
imposed by the executable formats that APE wraps.
1. ELF requires that file offsets be congruent with virtual addresses
modulo the CPU page size. So when we add a shell script to the start
of an executable, we need to round up to the page size in order to
maintain ELF's invariant. Although no such roundup is required on the
program segments once the invariant is restored. ELF loaders will
happily map program headers from arbitrary file intervals (which may
overlap) onto arbitrarily virtual intervals (which don't need to be
contiguous). In order to do that, the loaders will generally use
UNIX's mmap() function which is more restrictive and only accepts
addresses and offsets that are page aligned. To make it possible to
map an unaligned ELF program header that could potentially start and
stop at any byte, ELF loaders round-out the intervals, which means
adjacent unrelated data might also get mapped, which may need to be
explicitly zero'd. Thanks to the cleverness of ELF, it's possible to
have an executable file be very tiny, without needing any alignment
bytes, and it'll be loaded into a properly aligned virtual space
where segments can be as sparse as we want them to be.
2. PE doesn't care about congruence and instead defines two separate
kinds of alignment. First, PE requires that the layout of segment
memory inside the file be aligned on at minimum the classic 512 byte
MS-DOS page size. This means that, unlike ELF, some alignment padding
may need to be encoded into the file, making it slightly larger. Next
PE imposes an alignment restriction on segments once they've been
mapped into the virtual address space, which must be rounded to the
system page size. Like ELF, PE segments need to be properly ordered
but they're allowed to drift apart once mapped in a non-contiguous
sparsely mapped way. When inserting shell script content at the start
of a PE file, the most problematic thing is the need to round up to
the 64kb system granularity, which results in a lot of needless bytes
of padding being inserted by a naive second-pass linker.
3. Apple's Mach-O format is the strictest of them all. While both ELF
and PE are defined in such a way that invites great creativity, XNU
will simply refuse to an executable that does anything creative with
alignment. All loaded segments need to both start and end on a page
aligned address. XNU also wants segments to be contiguous similar to
portable executable, except it applies to both the file and virtual
spaces, which must follow the same structure.
Actually Portable Executables must conform to the strictest requirements
demanded by the support vector. Therefore an APE binary that has headers
for all three of the above executable formats MUST conform to the Apple
way of doing things. GNU ld linker scripts aren't very good at producing
ELF binaries that rigidly conform to this simple naive layout. There are
so many ways things can go wrong, where third party code might slip its
own custom section name in-between the linker script sections that are
explicitly defined, thereby causing ELF's powerful features to manifest
and the resulting content overlapping. The best `ld` flag that helps is
`--orphan-handling=error` which can help with explaining such mysteries.
While Cosmopolitan was originally defined to just use stock GNU tools,
this proved intractable over time, and the project has been evolving in
the direction of building its own. Inventing the `apelink` program was
what enabled the project to achieve multi-architecture binaries whereas
previously it was only possible to do multi-OS binaries. In the future,
our hope is that a fast power linker like Mold can be adapted to produce
fat APE binaries directly from object files in one pass.
## Position Independent Code
APE doesn't currently support position independent executable formats.
This is because APE was originally written for the GNU linker, where PIC
and PIE were after-thoughts and never fully incorporated with the older
more powerful linker script techniques upon which APE relies. Future
iterations of this specification are intended to converge on modern
standards, as our tooling becomes developed enough to support it.
However this only applies to the wrapped executable formats themselves.
While our convention to date has been to always load ELF programs at the
4mb mark, this is not guaranteed across OSes and architectures. Programs
should have no expectations that a program will be loaded to any given
address. For example, Cosmo currently implements APE on AARCH64 as
loading executables to a starting address of 0x000800000000. This
address occupies a sweet spot of requirements.
## Address Space
In order to create a single binary that supports as many platforms as
possible without needing to be recompiled, there's a very narrow range
of addresses that can be used. That range is somewhere between 32 bits
and 39 bits.
- Embedded devices that claim to be 64-bit will oftentimes only support
a virtual address space that's 39 bits in size.
- We can't load executable images on AARCH64 beneath 0x100000000 (4gb)
because Apple forbids doing that, possibly in an effort to enforce a
best practice for spotting 32-bit to 64-bit transition bugs. Please
note that this restriction only applies to Apple ARM64 systems. The
x86-64 version of XNU will happily load APE binaries to 0x00400000.
- The AMD64 architecture on desktops and servers can usually be counted
upon to provide a 47-bit address space. The Linux Kernel for instance
grants each userspace program full dominion over addresses 0x00200000
through 0x00007fffffffffff provided the hardware supports this. On
modern workstations supporting Intel and AMD's new PML5T feature which
virtualizes memory using a radix trie that's five layers deep, Linux
is able to offer userspace its choice of fixed addresses from
0x00200000 through 0x00ffffffffffffff. The only exception to this rule
we've encountered so far is that Windows 7 and Windows Vista behaved
similar to embedded devices in reducing the number of va bits.
## Page Size
APE software MUST be page size agnostic. For many years the industry had
converged on a strong consensus of having a page size that's 4096 bytes.
However this convention was never guaranteed. New computers have become
extremely popular, such as Apple Silicon, that use a 16kb page size.
By convention, Cosmopolitan Libc currently generates ELF headers for
x86-64 that are strictly aligned on a 4096-byte page size. On ARM64
Cosmopolitan is currently implemented to always generate ELF headers
aligned on a 16kb page size.
In addition to being page size agnostic, APE software that cares about
working correctly on Windows needs to be aware of the concept of
allocation granularity. While the page size on Windows is generally 4kb
in size, memory mappings can only be created on addresses that aligned
to the system allocation granularity, which is generally 64kb. If you
use a function like mmap() with Cosmopolitan Libc, then the `addr` and
`offset` parameters need to be aligned to `sysconf(_SC_GRANSIZE)` or
else your software won't work on Windows. Windows has other limitations
too, such as lacking the ability to carve or punch holes in mappings.
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/dce.h"
#include "ape/ape.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#ifdef __aarch64__
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
// Invokes system call.
//
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+37 -49
View File
@@ -14,7 +14,6 @@ ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
ifeq ($(MODE), x86_64)
ENABLE_FTRACE = 1
@@ -64,7 +63,6 @@ ENABLE_FTRACE = 1
CONFIG_CCFLAGS += $(BACKTRACES) -O
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
CONFIG_LDFLAGS += -S
TARGET_ARCH ?= -msse3
endif
# Optimized Mode
@@ -84,7 +82,7 @@ ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
TARGET_ARCH ?= -march=native
CONFIG_TARGET_ARCH ?= -march=native
endif
# Optimized Linux Mode
@@ -102,7 +100,20 @@ CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
CONFIG_COPTS += -mred-zone
TARGET_ARCH ?= -march=native
CONFIG_TARGET_ARCH ?= -march=native
endif
ifeq ($(MODE), x86_64-optlinux)
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
CONFIG_COPTS += -mred-zone
CONFIG_TARGET_ARCH ?= -march=native
endif
ifeq ($(MODE), aarch64-optlinux)
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
CONFIG_COPTS += -mred-zone
endif
# Release Mode
@@ -123,36 +134,13 @@ endif
ifeq ($(MODE), rel)
CONFIG_CPPFLAGS += -DNDEBUG -DDWARFLESS
CONFIG_CCFLAGS += $(BACKTRACES) -O2
TARGET_ARCH ?= -msse3
PYFLAGS += -O1
endif
# Asan Mode
#
# Safer binaries good for backend production serving.
#
# - `make MODE=asan`
# - Memory safety
# - Production worthy
# - Backtraces
# - Debuggability
# - Larger binaries
#
ifeq ($(MODE), asan)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
CONFIG_COPTS += -fsanitize=address
TARGET_ARCH ?= -msse3
QUOTA ?= -C64 -L300
endif
# Debug Mode
#
# - `make MODE=dbg`
# - Backtraces
# - Enables asan
# - Enables ubsan
# - Stack canaries
# - No optimization
@@ -161,18 +149,32 @@ endif
ifeq ($(MODE), dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
TARGET_ARCH ?= -msse3
OVERRIDE_CFLAGS += -O0
OVERRIDE_CXXFLAGS += -O0
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
CONFIG_COPTS += -fsanitize=undefined
OVERRIDE_CCFLAGS += -fno-pie
QUOTA ?= -C64 -L300
endif
ifeq ($(MODE), x86_64-dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
OVERRIDE_CFLAGS += -O0
OVERRIDE_CXXFLAGS += -O0
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
CONFIG_COPTS += -fsanitize=undefined
OVERRIDE_CCFLAGS += -fno-pie
QUOTA ?= -C64 -L300
endif
ifeq ($(MODE), aarch64-dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline -fdce
OVERRIDE_CFLAGS += -O0 -fdce
OVERRIDE_CXXFLAGS += -O0 -fdce
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
CONFIG_COPTS += -fsanitize=undefined
QUOTA ?= -C64 -L300
endif
@@ -192,7 +194,6 @@ ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g -ggdb
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
TARGET_ARCH ?= -msse3
endif
# Tiny Mode
@@ -222,8 +223,6 @@ CONFIG_CCFLAGS += \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls \
-DDWARFLESS
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
-O2 \
-B
@@ -243,8 +242,6 @@ CONFIG_CCFLAGS += \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls \
-DDWARFLESS
TARGET_ARCH ?= \
-msse3
PYFLAGS += \
-O2 \
-B
@@ -296,8 +293,6 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
TARGET_ARCH ?= \
-msse3
endif
# Linux+BSD Tiny Mode
@@ -327,8 +322,6 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
TARGET_ARCH ?= \
-msse3
endif
# Unix Tiny Mode
@@ -357,8 +350,6 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
TARGET_ARCH ?= \
-msse3
endif
# Tiny Metallic Unix Mode
@@ -387,8 +378,6 @@ CONFIG_CCFLAGS += \
-fno-align-jumps \
-fno-align-labels \
-fno-align-loops
TARGET_ARCH ?= \
-msse3
endif
# no x87 instructions mode
@@ -410,7 +399,6 @@ ENABLE_FTRACE = 1
CONFIG_COPTS += -mlong-double-64
CONFIG_CCFLAGS += $(BACKTRACES) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
TARGET_ARCH ?= -msse3
endif
# LLVM Mode
@@ -423,7 +411,6 @@ endif
#
ifeq ($(MODE), llvm)
.STRICT = 0
TARGET_ARCH ?= -msse3
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
AS = clang
CC = clang
@@ -466,7 +453,6 @@ ifeq ($(MODE), ansi)
CONFIG_CFLAGS += -std=c11
#CONFIG_CPPFLAGS += -ansi
CONFIG_CXXFLAGS += -std=c++11
TARGET_ARCH ?= -msse3
endif
ifneq ($(ENABLE_FTRACE),)
@@ -524,3 +510,5 @@ ifeq ($(ARCH), aarch64)
CONFIG_CCFLAGS += -fpatchable-function-entry=7,6
endif
endif
TARGET_ARCH ?= $(CONFIG_TARGET_ARCH)
+4 -16
View File
@@ -64,9 +64,6 @@ BACKTRACES = \
-fno-optimize-sibling-calls \
-mno-omit-leaf-frame-pointer
SANITIZER = \
-fsanitize=address
NO_MAGIC = \
-ffreestanding \
-fno-stack-protector \
@@ -95,10 +92,7 @@ DEFAULT_COPTS ?= \
-fno-gnu-unique \
-fstrict-aliasing \
-fstrict-overflow \
-fno-semantic-interposition \
-fno-dwarf2-cfi-asm \
-fno-unwind-tables \
-fno-asynchronous-unwind-tables
-fno-semantic-interposition
ifeq ($(ARCH), x86_64)
# Microsoft says "[a]ny memory below the stack beyond the red zone
@@ -118,14 +112,10 @@ ifeq ($(ARCH), aarch64)
# - Cosmopolitan Libc uses x28 for thread-local storage because Apple
# forbids us from using tpidr_el0 too.
#
# - Cosmopolitan currently lacks an implementation of the runtime
# libraries needed by the -moutline-atomics flag
#
DEFAULT_COPTS += \
-ffixed-x18 \
-ffixed-x28 \
-fsigned-char \
-mno-outline-atomics
-fsigned-char
endif
MATHEMATICAL = \
@@ -142,12 +132,10 @@ DEFAULT_CPPFLAGS += \
-isystem libc/isystem
DEFAULT_CFLAGS = \
-std=gnu2x
-std=gnu23
DEFAULT_CXXFLAGS = \
-std=gnu++20 \
-fno-rtti \
-fno-exceptions \
-std=gnu++23 \
-fuse-cxa-atexit \
-Wno-int-in-bool-context \
-Wno-narrowing \
+8 -8
View File
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
fi
find_objdump() {
if [ -x .cosmocc/3.3.5/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.3.5/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.3.5/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.3.5/bin/$1-linux-musl-objdump"
if [ -x .cosmocc/3.9.2/bin/$1-linux-cosmo-objdump ]; then
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump
elif [ -x .cosmocc/3.9.2/bin/$1-linux-musl-objdump ]; then
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-musl-objdump
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump"
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump" ]; then
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump"
else
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
exit 1
+1 -1
View File
@@ -4,5 +4,5 @@ UNAMES=$(uname -s)
if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
exec ape "$@"
else
exec "$@"
exec rusage "$@"
fi
+1 -1
View File
@@ -31,7 +31,7 @@ if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then
exit 0
fi
if ! build/bootstrap/echo.com -n; then
if ! build/bootstrap/echo -n; then
cat <<'EOF' >&2
ERROR
+7
View File
@@ -18,7 +18,13 @@ CTL_A_CHECKS = \
CTL_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_STDIO \
LIBC_STR \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_LIBCXXABI \
THIRD_PARTY_LIBUNWIND \
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
@@ -36,6 +42,7 @@ $(CTL_A_OBJS): private \
-Walloca-larger-than=4096 \
-ffunction-sections \
-fdata-sections \
-fexceptions \
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
+1 -1
View File
@@ -12,7 +12,7 @@ This package provides an STL alternative that's designed to:
This code is experimental and mostly for Justine to save herself from
the STL trainwreck. That doesn't mean cosmocc users aren't welcome to
use tihs too. You shouldn't expect the design to not change later on.
use this too. You shouldn't expect the design to not change later on.
## Rationale
+28
View File
@@ -0,0 +1,28 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ACCUMULATE_H_
#define CTL_ACCUMULATE_H_
namespace ctl {
template<class InputIt, class T>
constexpr T
accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first)
init = init + *first;
return init;
}
template<class InputIt, class T, class BinaryOperation>
constexpr T
accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
{
for (; first != last; ++first)
init = op(init, *first);
return init;
}
} // namespace ctl
#endif // CTL_ACCUMULATE_H_
+55
View File
@@ -0,0 +1,55 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ADD_LVALUE_REFERENCE_H_
#define CTL_ADD_LVALUE_REFERENCE_H_
namespace ctl {
template<typename T>
struct add_lvalue_reference
{
typedef T& type;
};
template<typename T>
struct add_lvalue_reference<T&>
{
typedef T& type;
};
template<typename T>
struct add_lvalue_reference<T&&>
{
typedef T& type;
};
template<>
struct add_lvalue_reference<void>
{
typedef void type;
};
template<>
struct add_lvalue_reference<const void>
{
typedef const void type;
};
template<>
struct add_lvalue_reference<volatile void>
{
typedef volatile void type;
};
template<>
struct add_lvalue_reference<const volatile void>
{
typedef const volatile void type;
};
template<typename T>
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
} // namespace ctl
#endif // CTL_ADD_LVALUE_REFERENCE_H_
+43
View File
@@ -0,0 +1,43 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ADD_POINTER_H_
#define CTL_ADD_POINTER_H_
#include "remove_reference.h"
namespace ctl {
// Primary template
template<typename T>
struct add_pointer
{
typedef typename remove_reference<T>::type* type;
};
// Specialization for functions
template<typename R, typename... Args>
struct add_pointer<R(Args...)>
{
typedef R (*type)(Args...);
};
// Specialization for function references
template<typename R, typename... Args>
struct add_pointer<R (&)(Args...)>
{
typedef R (*type)(Args...);
};
// Specialization for rvalue references to functions
template<typename R, typename... Args>
struct add_pointer<R (&&)(Args...)>
{
typedef R (*type)(Args...);
};
// Helper alias template (C++14 and later)
template<typename T>
using add_pointer_t = typename add_pointer<T>::type;
} // namespace ctl
#endif // CTL_ADD_POINTER_H_
+29
View File
@@ -0,0 +1,29 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ADDRESSOF_H_
#define CTL_ADDRESSOF_H_
namespace ctl {
template<typename T>
T*
addressof(T& arg) noexcept
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char&>(arg)));
}
template<typename R, typename... Args>
R (*addressof(R (*&arg)(Args...)) noexcept)
(Args...)
{
return arg;
}
template<typename T>
T*
addressof(T&&) = delete;
} // namespace ctl
#endif // CTL_ADDRESSOF_H_
+24
View File
@@ -0,0 +1,24 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ADVANCE_H_
#define CTL_ADVANCE_H_
namespace ctl {
template<class InputIt, class Distance>
constexpr void
advance(InputIt& it, Distance n)
{
while (n > 0) {
--n;
++it;
}
while (n < 0) {
++n;
--it;
}
}
} // namespace ctl
#endif // CTL_ADVANCE_H_
+20
View File
@@ -0,0 +1,20 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ALL_OF_H_
#define CTL_ALL_OF_H_
namespace ctl {
template<class InputIt, class UnaryPredicate>
constexpr bool
all_of(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first)
if (!p(*first))
return false;
return true;
}
} // namespace ctl
#endif // CTL_ALL_OF_H_
+94
View File
@@ -0,0 +1,94 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ALLOCATOR_H_
#define CTL_ALLOCATOR_H_
#include "bad_alloc.h"
#include "integral_constant.h"
#include "new.h"
#include "utility.h"
namespace ctl {
template<typename T>
class allocator
{
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using propagate_on_container_move_assignment = ctl::true_type;
using is_always_equal = ctl::true_type;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
constexpr allocator() noexcept = default;
constexpr allocator(const allocator&) noexcept = default;
template<class U>
constexpr allocator(const allocator<U>&) noexcept
{
}
constexpr ~allocator() = default;
[[nodiscard]] T* allocate(size_type n)
{
if (n > __SIZE_MAX__ / sizeof(T))
throw ctl::bad_alloc();
if (auto p = static_cast<T*>(::operator new(
n * sizeof(T), ctl::align_val_t(alignof(T)), ctl::nothrow)))
return p;
throw ctl::bad_alloc();
}
void deallocate(T* p, size_type n) noexcept
{
::operator delete(p, n * sizeof(T), ctl::align_val_t(alignof(T)));
}
template<typename U, typename... Args>
void construct(U* p, Args&&... args)
{
::new (static_cast<void*>(p)) U(ctl::forward<Args>(args)...);
}
template<typename U>
void destroy(U* p)
{
p->~U();
}
size_type max_size() const noexcept
{
return __SIZE_MAX__ / sizeof(T);
}
allocator& operator=(const allocator&) = default;
template<typename U>
struct rebind
{
using other = allocator<U>;
};
};
template<class T, class U>
bool
operator==(const allocator<T>&, const allocator<U>&) noexcept
{
return true;
}
template<class T, class U>
bool
operator!=(const allocator<T>&, const allocator<U>&) noexcept
{
return false;
}
} // namespace ctl
#endif // CTL_ALLOCATOR_H_
+70
View File
@@ -0,0 +1,70 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ALLOCATOR_TRAITS_H_
#define CTL_ALLOCATOR_TRAITS_H_
#include "integral_constant.h"
namespace ctl {
template<typename Alloc>
struct allocator_traits
{
using allocator_type = Alloc;
using value_type = typename Alloc::value_type;
using pointer = typename Alloc::value_type*;
using const_pointer = const typename Alloc::value_type*;
using void_pointer = void*;
using const_void_pointer = const void*;
using difference_type = ptrdiff_t;
using size_type = size_t;
using propagate_on_container_copy_assignment = ctl::false_type;
using propagate_on_container_move_assignment = ctl::true_type;
using propagate_on_container_swap = ctl::false_type;
using is_always_equal = ctl::true_type;
template<typename T>
struct rebind_alloc
{
using other = typename Alloc::template rebind<T>::other;
};
template<typename T>
using rebind_traits = allocator_traits<typename rebind_alloc<T>::other>;
static pointer allocate(Alloc& a, size_type n)
{
return a.allocate(n);
}
static void deallocate(Alloc& a, pointer p, size_type n)
{
a.deallocate(p, n);
}
template<typename T, typename... Args>
static void construct(Alloc& a, T* p, Args&&... args)
{
::new ((void*)p) T(static_cast<Args&&>(args)...);
}
template<typename T>
static void destroy(Alloc& a, T* p)
{
p->~T();
}
static size_type max_size(const Alloc& a) noexcept
{
return a.max_size();
}
static Alloc select_on_container_copy_construction(const Alloc& a)
{
return a;
}
};
} // namespace ctl
#endif // CTL_ALLOCATOR_TRAITS_H_
+20
View File
@@ -0,0 +1,20 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ANY_OF_H_
#define CTL_ANY_OF_H_
namespace ctl {
template<class InputIt, class UnaryPredicate>
constexpr bool
any_of(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first)
if (p(*first))
return true;
return false;
}
} // namespace ctl
#endif // CTL_ANY_OF_H_
+248
View File
@@ -0,0 +1,248 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ARRAY_H_
#define CTL_ARRAY_H_
#include "initializer_list.h"
#include "out_of_range.h"
#include "reverse_iterator.h"
namespace ctl {
template<typename T, size_t N>
struct array
{
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using iterator = value_type*;
using const_iterator = const value_type*;
using reverse_iterator = ctl::reverse_iterator<iterator>;
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
T elems[N];
constexpr array() = default;
constexpr array(std::initializer_list<T> init)
{
auto it = init.begin();
for (size_t i = 0; i < N && it != init.end(); ++i, ++it)
elems[i] = *it;
}
constexpr reference at(size_type pos)
{
if (pos >= N)
throw ctl::out_of_range();
return elems[pos];
}
constexpr const_reference at(size_type pos) const
{
if (pos >= N)
throw ctl::out_of_range();
return elems[pos];
}
constexpr reference operator[](size_type pos)
{
if (pos >= N)
__builtin_trap();
return elems[pos];
}
constexpr const_reference operator[](size_type pos) const
{
if (pos >= N)
__builtin_trap();
return elems[pos];
}
constexpr reference front()
{
return elems[0];
}
constexpr const_reference front() const
{
return elems[0];
}
constexpr reference back()
{
return elems[N - 1];
}
constexpr const_reference back() const
{
return elems[N - 1];
}
constexpr T* data() noexcept
{
return elems;
}
constexpr const T* data() const noexcept
{
return elems;
}
constexpr iterator begin() noexcept
{
return elems;
}
constexpr const_iterator begin() const noexcept
{
return elems;
}
constexpr iterator end() noexcept
{
return elems + N;
}
constexpr const_iterator end() const noexcept
{
return elems + N;
}
constexpr reverse_iterator rbegin() noexcept
{
return reverse_iterator(end());
}
constexpr const_reverse_iterator rbegin() const noexcept
{
return const_reverse_iterator(end());
}
constexpr reverse_iterator rend() noexcept
{
return reverse_iterator(begin());
}
constexpr const_reverse_iterator rend() const noexcept
{
return const_reverse_iterator(begin());
}
constexpr const_iterator cbegin() const noexcept
{
return begin();
}
constexpr const_iterator cend() const noexcept
{
return end();
}
constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
constexpr bool empty() const noexcept
{
return N == 0;
}
constexpr size_type size() const noexcept
{
return N;
}
constexpr size_type max_size() const noexcept
{
return N;
}
void fill(const T& value)
{
for (size_type i = 0; i < N; ++i) {
elems[i] = value;
}
}
void swap(array& other) noexcept
{
for (size_type i = 0; i < N; ++i) {
T temp = elems[i];
elems[i] = other.elems[i];
other.elems[i] = temp;
}
}
};
template<typename T, size_t N>
bool
operator==(const array<T, N>& lhs, const array<T, N>& rhs)
{
for (size_t i = 0; i < N; ++i) {
if (!(lhs[i] == rhs[i]))
return false;
}
return true;
}
template<typename T, size_t N>
bool
operator!=(const array<T, N>& lhs, const array<T, N>& rhs)
{
return !(lhs == rhs);
}
template<typename T, size_t N>
bool
operator<(const array<T, N>& lhs, const array<T, N>& rhs)
{
for (size_t i = 0; i < N; ++i) {
if (lhs[i] < rhs[i])
return true;
if (rhs[i] < lhs[i])
return false;
}
return false;
}
template<typename T, size_t N>
bool
operator<=(const array<T, N>& lhs, const array<T, N>& rhs)
{
return !(rhs < lhs);
}
template<typename T, size_t N>
bool
operator>(const array<T, N>& lhs, const array<T, N>& rhs)
{
return rhs < lhs;
}
template<typename T, size_t N>
bool
operator>=(const array<T, N>& lhs, const array<T, N>& rhs)
{
return !(lhs < rhs);
}
template<typename T, size_t N>
void
swap(array<T, N>& lhs, array<T, N>& rhs) noexcept
{
lhs.swap(rhs);
}
} // namespace ctl
#endif // CTL_ARRAY_H_
+64
View File
@@ -0,0 +1,64 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_BACK_INSERTER_H_
#define CTL_BACK_INSERTER_H_
#include "iterator.h"
#include "utility.h"
namespace ctl {
template<class Container>
class back_insert_iterator
{
protected:
Container* container;
public:
using iterator_category = ctl::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
explicit back_insert_iterator(Container& c) : container(&c)
{
}
back_insert_iterator& operator=(const typename Container::value_type& value)
{
container->push_back(value);
return *this;
}
back_insert_iterator& operator=(typename Container::value_type&& value)
{
container->push_back(ctl::move(value));
return *this;
}
back_insert_iterator& operator*()
{
return *this;
}
back_insert_iterator& operator++()
{
return *this;
}
back_insert_iterator operator++(int)
{
return *this;
}
};
template<class Container>
back_insert_iterator<Container>
back_inserter(Container& c)
{
return back_insert_iterator<Container>(c);
}
} // namespace ctl
#endif // CTL_BACK_INSERTER_H_
+23
View File
@@ -0,0 +1,23 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_BAD_ALLOC_H_
#define CTL_BAD_ALLOC_H_
#include "exception.h"
namespace ctl {
class bad_alloc : public ctl::exception
{
public:
bad_alloc() noexcept = default;
~bad_alloc() override = default;
const char* what() const noexcept override
{
return "ctl::bad_alloc";
}
};
} // namespace ctl
#endif // CTL_BAD_ALLOC_H_
+25
View File
@@ -0,0 +1,25 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_CONDITIONAL_H_
#define CTL_CONDITIONAL_H_
namespace ctl {
template<bool B, class T, class F>
struct conditional
{
typedef T type;
};
template<class T, class F>
struct conditional<false, T, F>
{
typedef F type;
};
template<bool B, typename T, typename F>
using conditional_t = typename conditional<B, T, F>::type;
} // namespace ctl
#endif // CTL_CONDITIONAL_H_
+22
View File
@@ -0,0 +1,22 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_COPY_H_
#define CTL_COPY_H_
namespace ctl {
template<class InputIt, class OutputIt>
OutputIt
copy(InputIt first, InputIt last, OutputIt d_first)
{
while (first != last) {
*d_first = *first;
++d_first;
++first;
}
return d_first;
}
} // namespace ctl
#endif // CTL_COPY_H_
+36
View File
@@ -0,0 +1,36 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_DECAY_H_
#define CTL_DECAY_H_
#include "add_pointer.h"
#include "conditional.h"
#include "is_array.h"
#include "is_function.h"
#include "remove_cv.h"
#include "remove_extent.h"
#include "remove_reference.h"
namespace ctl {
template<typename T>
struct decay
{
private:
typedef typename ctl::remove_reference<T>::type U;
public:
typedef typename ctl::conditional<
ctl::is_array<U>::value,
typename ctl::remove_extent<U>::type*,
typename ctl::conditional<ctl::is_function<U>::value,
typename ctl::add_pointer<U>::type,
typename ctl::remove_cv<U>::type>::type>::type
type;
};
template<typename T>
using decay_t = typename decay<T>::type;
} // namespace ctl
#endif // CTL_DECAY_H_
+44
View File
@@ -0,0 +1,44 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_DEFAULT_DELETE_H_
#define CTL_DEFAULT_DELETE_H_
#include "enable_if.h"
#include "is_convertible.h"
namespace ctl {
template<typename T>
struct default_delete
{
constexpr default_delete() noexcept = default;
template<typename U,
typename = typename ctl::enable_if<
ctl::is_convertible<U*, T*>::value>::type>
constexpr default_delete(const default_delete<U>&) noexcept
{
}
constexpr void operator()(T* const p) const noexcept
{
delete p;
}
};
template<typename T>
struct default_delete<T[]>
{
constexpr default_delete() noexcept = default;
template<typename U,
typename = typename ctl::enable_if<
ctl::is_convertible<U (*)[], T (*)[]>::value>::type>
constexpr default_delete(const default_delete<U[]>&) noexcept
{
}
constexpr void operator()(T* const p) const noexcept
{
delete[] p;
}
};
} // namespace ctl
#endif // CTL_DEFAULT_DELETE_H_
+39
View File
@@ -0,0 +1,39 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_DISTANCE_H_
#define CTL_DISTANCE_H_
#include "iterator.h"
#include "iterator_traits.h"
namespace ctl {
template<class InputIter>
constexpr typename ctl::iterator_traits<InputIter>::difference_type
distance_impl(InputIter first, InputIter last, input_iterator_tag)
{
typename ctl::iterator_traits<InputIter>::difference_type res(0);
for (; first != last; ++first)
++res;
return res;
}
template<class RandIter>
constexpr typename ctl::iterator_traits<RandIter>::difference_type
distance_impl(RandIter first, RandIter last, random_access_iterator_tag)
{
return last - first;
}
template<class InputIter>
constexpr typename ctl::iterator_traits<InputIter>::difference_type
distance(InputIter first, InputIter last)
{
return distance_impl(
first,
last,
typename ctl::iterator_traits<InputIter>::iterator_category());
}
} // namespace ctl
#endif // CTL_DISTANCE_H_
+35
View File
@@ -0,0 +1,35 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "dubble.h"
namespace ctl {
const double_conversion::DoubleToStringConverter kDoubleToPrintfG(
double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
double_conversion::DoubleToStringConverter::NO_TRAILING_ZERO,
"inf",
"nan",
'e',
-6,
10, // let 32-bit ints be represented without exponent
6,
0,
0);
} // namespace ctl
+13
View File
@@ -0,0 +1,13 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_DUBBLE_H_
#define COSMOPOLITAN_CTL_DUBBLE_H_
#include "third_party/double-conversion/double-to-string.h"
namespace ctl {
extern const double_conversion::DoubleToStringConverter kDoubleToPrintfG;
} // namespace ctl
#endif // COSMOPOLITAN_CTL_DUBBLE_H_
+23
View File
@@ -0,0 +1,23 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_ENABLE_IF_H_
#define CTL_ENABLE_IF_H_
namespace ctl {
template<bool B, class T = void>
struct enable_if
{};
template<class T>
struct enable_if<true, T>
{
typedef T type;
};
template<bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
} // namespace ctl
#endif // CTL_ENABLE_IF_H_
+64
View File
@@ -0,0 +1,64 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_EQUAL_H_
#define CTL_EQUAL_H_
namespace ctl {
template<class InputIt1, class InputIt2>
bool
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
for (; first1 != last1; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return true;
}
// Overload that takes a predicate
template<class InputIt1, class InputIt2, class BinaryPredicate>
bool
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate pred)
{
for (; first1 != last1; ++first1, ++first2) {
if (!pred(*first1, *first2)) {
return false;
}
}
return true;
}
// Overloads that take two ranges (C++14 and later)
template<class InputIt1, class InputIt2>
bool
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return first1 == last1 && first2 == last2;
}
template<class InputIt1, class InputIt2, class BinaryPredicate>
bool
equal(InputIt1 first1,
InputIt1 last1,
InputIt2 first2,
InputIt2 last2,
BinaryPredicate pred)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
if (!pred(*first1, *first2)) {
return false;
}
}
return first1 == last1 && first2 == last2;
}
} // namespace ctl
#endif /* CTL_EQUAL_H_ */
+22
View File
@@ -0,0 +1,22 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_EXCEPTION_H_
#define CTL_EXCEPTION_H_
namespace ctl {
class exception
{
public:
exception() noexcept = default;
virtual ~exception() = default;
virtual const char* what() const noexcept
{
return "ctl::exception";
}
};
} // namespace ctl
#endif // CTL_EXCEPTION_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_FILL_H_
#define CTL_FILL_H_
namespace ctl {
template<typename ForwardIt, typename T>
void
fill(ForwardIt first, ForwardIt last, const T& value)
{
for (; first != last; ++first)
*first = value;
}
} // namespace ctl
#endif // CTL_FILL_H_
+19
View File
@@ -0,0 +1,19 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_FILL_N_H_
#define CTL_FILL_N_H_
namespace ctl {
template<typename OutputIt, typename Size, typename T>
OutputIt
fill_n(OutputIt first, Size count, const T& value)
{
for (; count > 0; --count, ++first)
*first = value;
return first;
}
} // namespace ctl
#endif // CTL_FILL_N_H_
+64
View File
@@ -0,0 +1,64 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef _LIBCPP_INITIALIZER_LIST
#define _LIBCPP_INITIALIZER_LIST
namespace std {
template<class T>
class initializer_list
{
constexpr initializer_list(const T* b, size_t s) noexcept
: begin_(b), size_(s)
{
}
public:
typedef T value_type;
typedef const T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef const T* iterator;
typedef const T* const_iterator;
constexpr initializer_list() noexcept : begin_(nullptr), size_(0)
{
}
constexpr size_t size() const noexcept
{
return size_;
}
constexpr const T* begin() const noexcept
{
return begin_;
}
constexpr const T* end() const noexcept
{
return begin_ + size_;
}
private:
const T* begin_;
size_t size_;
};
template<class T>
inline constexpr const T*
begin(initializer_list<T> i) noexcept
{
return i.begin();
}
template<class T>
inline constexpr const T*
end(initializer_list<T> i) noexcept
{
return i.end();
}
} // namespace std
#endif // _LIBCPP_INITIALIZER_LIST
+31
View File
@@ -0,0 +1,31 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_INTEGRAL_CONSTANT_H_
#define CTL_INTEGRAL_CONSTANT_H_
namespace ctl {
template<class T, T v>
struct integral_constant
{
static constexpr T value = v;
typedef T value_type;
typedef integral_constant type;
constexpr operator value_type() const noexcept
{
return value;
}
constexpr value_type operator()() const noexcept
{
return value;
}
};
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
} // namespace ctl
#endif // CTL_INTEGRAL_CONSTANT_H_
+39
View File
@@ -0,0 +1,39 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ios.h"
namespace ctl {
ios::ios(FILE* file) : file_(file)
{
}
ios::~ios() = default;
ios&
ios::operator=(ios&& other) noexcept
{
if (this != &other) {
file_ = other.file_;
other.file_ = nullptr;
}
return *this;
}
} // namespace ctl
+27
View File
@@ -0,0 +1,27 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IOS_H_
#define CTL_IOS_H_
#include "ios_base.h"
struct FILE;
namespace ctl {
class ios : public ios_base
{
public:
explicit ios(FILE*);
virtual ~ios();
protected:
ios& operator=(ios&&) noexcept;
FILE* file_;
private:
ios(const ios&) = delete;
};
} // namespace ctl
#endif // CTL_IOS_H_
+118
View File
@@ -0,0 +1,118 @@
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
//
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "ios_base.h"
namespace ctl {
ios_base::ios_base() : state_(goodbit), flags_(skipws | dec)
{
}
ios_base::~ios_base() = default;
ios_base::fmtflags
ios_base::flags() const
{
return static_cast<ios_base::fmtflags>(flags_);
}
ios_base::fmtflags
ios_base::flags(fmtflags fmtfl)
{
int old = flags_;
flags_ = fmtfl;
return static_cast<ios_base::fmtflags>(old);
}
ios_base::fmtflags
ios_base::setf(fmtflags fmtfl)
{
int old = flags_;
flags_ |= fmtfl;
return static_cast<ios_base::fmtflags>(old);
}
ios_base::fmtflags
ios_base::setf(fmtflags fmtfl, fmtflags mask)
{
int old = flags_;
flags_ = (flags_ & ~mask) | (fmtfl & mask);
return static_cast<ios_base::fmtflags>(old);
}
void
ios_base::unsetf(fmtflags mask)
{
flags_ &= ~mask;
}
ios_base::iostate
ios_base::rdstate() const
{
return static_cast<ios_base::iostate>(state_);
}
void
ios_base::clear(int state)
{
state_ = state;
}
void
ios_base::setstate(int state)
{
state_ |= state;
}
bool
ios_base::good() const
{
return state_ == goodbit;
}
bool
ios_base::eof() const
{
return (state_ & eofbit) != 0;
}
bool
ios_base::fail() const
{
return (state_ & (failbit | badbit)) != 0;
}
bool
ios_base::bad() const
{
return (state_ & badbit) != 0;
}
bool
ios_base::operator!() const
{
return fail();
}
ios_base::operator bool() const
{
return !fail();
}
} // namespace ctl
+86
View File
@@ -0,0 +1,86 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IOS_BASE_H_
#define CTL_IOS_BASE_H_
namespace ctl {
class ios_base
{
public:
typedef size_t streamsize;
enum iostate
{
goodbit = 0,
badbit = 1,
failbit = 2,
eofbit = 4
};
enum fmtflags
{
boolalpha = 1 << 0,
dec = 1 << 1,
fixed = 1 << 2,
hex = 1 << 3,
internal = 1 << 4,
left = 1 << 5,
oct = 1 << 6,
right = 1 << 7,
scientific = 1 << 8,
showbase = 1 << 9,
showpoint = 1 << 10,
showpos = 1 << 11,
skipws = 1 << 12,
unitbuf = 1 << 13,
uppercase = 1 << 14,
adjustfield = left | right | internal,
basefield = dec | oct | hex,
floatfield = scientific | fixed
};
enum openmode
{
app = 1 << 0,
binary = 1 << 1,
in = 1 << 2,
out = 1 << 3,
trunc = 1 << 4,
ate = 1 << 5
};
protected:
ios_base();
virtual ~ios_base();
int state_;
int flags_;
public:
fmtflags flags() const;
fmtflags flags(fmtflags);
fmtflags setf(fmtflags);
fmtflags setf(fmtflags, fmtflags);
void unsetf(fmtflags);
iostate rdstate() const;
void clear(int = goodbit);
void setstate(int);
bool good() const;
bool eof() const;
bool fail() const;
bool bad() const;
bool operator!() const;
explicit operator bool() const;
private:
ios_base(const ios_base&) = delete;
ios_base& operator=(const ios_base&) = delete;
};
} // namespace ctl
#endif // CTL_IOS_BASE_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_ABSTRACT_H_
#define CTL_IS_ABSTRACT_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_abstract : public ctl::integral_constant<bool, __is_abstract(T)>
{};
template<typename T>
inline constexpr bool is_abstract_v = __is_abstract(T);
} // namespace ctl
#endif // CTL_IS_ABSTRACT_H_
+26
View File
@@ -0,0 +1,26 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_ARRAY_H_
#define CTL_IS_ARRAY_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_array : ctl::false_type
{};
template<typename T, size_t N>
struct is_array<T[N]> : ctl::true_type
{};
template<typename T>
struct is_array<T[]> : ctl::true_type
{};
template<typename T>
inline constexpr bool is_array_v = is_array<T>::value;
} // namespace ctl
#endif // CTL_IS_ARRAY_H_
+19
View File
@@ -0,0 +1,19 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_BASE_OF_H_
#define CTL_IS_BASE_OF_H_
#include "integral_constant.h"
namespace ctl {
template<typename Base, typename Derived>
struct is_base_of
: public ctl::integral_constant<bool, __is_base_of(Base, Derived)>
{};
template<typename Base, typename Derived>
inline constexpr bool is_base_of_v = __is_base_of(Base, Derived);
} // namespace ctl
#endif // CTL_IS_BASE_OF_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_CLASS_H_
#define CTL_IS_CLASS_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_class : public ctl::integral_constant<bool, __is_class(T)>
{};
template<typename T>
inline constexpr bool is_class_v = __is_class(T);
} // namespace ctl
#endif // CTL_IS_CLASS_H_
+19
View File
@@ -0,0 +1,19 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_CONSTRUCTIBLE_H_
#define CTL_IS_CONSTRUCTIBLE_H_
#include "integral_constant.h"
namespace ctl {
template<class _Tp, class... _Args>
struct is_constructible
: public ctl::integral_constant<bool, __is_constructible(_Tp, _Args...)>
{};
template<class _Tp, class... _Args>
inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
} // namespace ctl
#endif // CTL_IS_CONSTRUCTIBLE_H_
+53
View File
@@ -0,0 +1,53 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_CONVERTIBLE_H_
#define CTL_IS_CONVERTIBLE_H_
#include "ctl/integral_constant.h"
#include "ctl/void_t.h"
namespace ctl {
// Declaration of declval
template<typename T>
T&&
declval() noexcept;
namespace detail {
template<typename From, typename To, typename = void>
struct is_convertible_impl : ctl::false_type
{};
template<typename From, typename To>
struct is_convertible_impl<From,
To,
void_t<decltype(static_cast<To>(declval<From>()))>>
: true_type
{};
// Handle void types separately
template<>
struct is_convertible_impl<void, void> : ctl::true_type
{};
template<typename To>
struct is_convertible_impl<void, To> : ctl::false_type
{};
template<typename From>
struct is_convertible_impl<From, void> : ctl::false_type
{};
} // namespace detail
template<typename From, typename To>
struct is_convertible : detail::is_convertible_impl<From, To>
{};
// Helper variable template (C++17 and later)
template<typename From, typename To>
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
} // namespace ctl
#endif // CTL_IS_CONVERTIBLE_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_EMPTY_H_
#define CTL_IS_EMPTY_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_empty : public ctl::integral_constant<bool, __is_empty(T)>
{};
template<typename T>
inline constexpr bool is_empty_v = __is_empty(T);
} // namespace ctl
#endif // CTL_IS_EMPTY_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_ENUM_H_
#define CTL_IS_ENUM_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_enum : public ctl::integral_constant<bool, __is_enum(T)>
{};
template<typename T>
inline constexpr bool is_enum_v = __is_enum(T);
} // namespace ctl
#endif // CTL_IS_ENUM_H_
+120
View File
@@ -0,0 +1,120 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_FUNCTION_H_
#define CTL_IS_FUNCTION_H_
#include "integral_constant.h"
namespace ctl {
// Primary template
template<class>
struct is_function : ctl::false_type
{};
// Specializations for various function types
// Regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : ctl::true_type
{};
// Functions with cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) const> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile> : ctl::true_type
{};
// Functions with ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...)&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) &&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile&&> : ctl::true_type
{};
// Variadic functions
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...)> : ctl::true_type
{};
// Variadic functions with cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile> : ctl::true_type
{};
// Variadic functions with ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...)&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) &&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) volatile&&> : ctl::true_type
{};
template<class Ret, class... Args>
struct is_function<Ret(Args..., ...) const volatile&&> : ctl::true_type
{};
} // namespace ctl
#endif // CTL_IS_FUNCTION_H_
+78
View File
@@ -0,0 +1,78 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_INTEGRAL_H_
#define CTL_IS_INTEGRAL_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_integral : ctl::false_type
{};
template<>
struct is_integral<bool> : ctl::true_type
{};
template<>
struct is_integral<char> : ctl::true_type
{};
template<>
struct is_integral<signed char> : ctl::true_type
{};
template<>
struct is_integral<unsigned char> : ctl::true_type
{};
template<>
struct is_integral<short> : ctl::true_type
{};
template<>
struct is_integral<unsigned short> : ctl::true_type
{};
template<>
struct is_integral<int> : ctl::true_type
{};
template<>
struct is_integral<unsigned int> : ctl::true_type
{};
template<>
struct is_integral<long> : ctl::true_type
{};
template<>
struct is_integral<unsigned long> : ctl::true_type
{};
template<>
struct is_integral<long long> : ctl::true_type
{};
template<>
struct is_integral<unsigned long long> : ctl::true_type
{};
template<>
struct is_integral<char16_t> : ctl::true_type
{};
template<>
struct is_integral<char32_t> : ctl::true_type
{};
template<>
struct is_integral<wchar_t> : ctl::true_type
{};
template<typename T>
inline constexpr bool is_integral_v = is_integral<T>::value;
} // namespace ctl
#endif // CTL_IS_INTEGRAL_H_
+18
View File
@@ -0,0 +1,18 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_POLYMORPHIC_H_
#define CTL_IS_POLYMORPHIC_H_
#include "integral_constant.h"
namespace ctl {
template<typename T>
struct is_polymorphic : public ctl::integral_constant<bool, __is_polymorphic(T)>
{};
template<typename T>
inline constexpr bool is_polymorphic_v = __is_polymorphic(T);
} // namespace ctl
#endif // CTL_IS_POLYMORPHIC_H_
+35
View File
@@ -0,0 +1,35 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_REFERENCE_H_
#define CTL_IS_REFERENCE_H_
namespace ctl {
// Primary template
template<class T>
struct is_reference
{
static constexpr bool value = false;
};
// Specialization for lvalue reference
template<class T>
struct is_reference<T&>
{
static constexpr bool value = true;
};
// Specialization for rvalue reference
template<class T>
struct is_reference<T&&>
{
static constexpr bool value = true;
};
// Helper variable template (C++14 and later)
template<class T>
inline constexpr bool is_reference_v = is_reference<T>::value;
} // namespace ctl
#endif // CTL_IS_REFERENCE_H_
+25
View File
@@ -0,0 +1,25 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_SAME_H_
#define CTL_IS_SAME_H_
namespace ctl {
template<typename T, typename U>
struct is_same
{
static constexpr bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static constexpr bool value = true;
};
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;
} // namespace ctl
#endif // CTL_IS_SAME_H_
+16
View File
@@ -0,0 +1,16 @@
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef CTL_IS_SIGNED_H_
#define CTL_IS_SIGNED_H_
namespace ctl {
template<typename T>
struct is_signed
{
static constexpr bool value = T(0) > T(-1);
};
} // namespace ctl
#endif // CTL_IS_SIGNED_H_
Loaded 100 of 5321 files, more files were not shown because too many files have changed in this diff. Show more