From 2676ec55de9a31a5d3568f317d529b54f591fd7e Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 10 Jun 2023 15:50:01 -0700 Subject: [PATCH] Make improvements to cosmocc toolchain --- examples/date.c | 65 ++++++++++++++++++++--- libc/assert.h | 16 +++--- libc/calls/write-nt.c | 5 +- libc/intrin/assertfail.greg.c | 44 ++-------------- libc/runtime/runtime.h | 2 +- libc/x/x.h | 2 +- tool/scripts/cosmoc++ | 98 ++++++++++++++++++++++++----------- tool/scripts/cosmocc | 90 +++++++++++++++++++++----------- 8 files changed, 205 insertions(+), 117 deletions(-) diff --git a/examples/date.c b/examples/date.c index 53a8d8351..70b1f60d4 100644 --- a/examples/date.c +++ b/examples/date.c @@ -7,15 +7,66 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif -#include "libc/mem/gc.h" -#include "libc/stdio/stdio.h" -#include "libc/x/xiso8601.h" +#include "libc/calls/calls.h" +#include "libc/calls/struct/timespec.h" +#include "libc/str/str.h" +#include "libc/time/struct/tm.h" /** - * @fileoverview ISO-8601 international high-precision timestamp printer. + * @fileoverview High performance ISO-8601 timestamp formatter. */ -int main(int argc, char *argv[]) { - puts(_gc(xiso8601ts(NULL))); - return 0; +char *GetTimestamp(void) { + int x; + struct timespec ts; + _Thread_local static long last; + _Thread_local static char s[27]; + _Thread_local static struct tm tm; + clock_gettime(0, &ts); + if (ts.tv_sec != last) { + localtime_r(&ts.tv_sec, &tm); + x = tm.tm_year + 1900; + s[0] = '0' + x / 1000; + s[1] = '0' + x / 100 % 10; + s[2] = '0' + x / 10 % 10; + s[3] = '0' + x % 10; + s[4] = '-'; + x = tm.tm_mon + 1; + s[5] = '0' + x / 10; + s[6] = '0' + x % 10; + s[7] = '-'; + x = tm.tm_mday; + s[8] = '0' + x / 10; + s[9] = '0' + x % 10; + s[10] = 'T'; + x = tm.tm_hour; + s[11] = '0' + x / 10; + s[12] = '0' + x % 10; + s[13] = ':'; + x = tm.tm_min; + s[14] = '0' + x / 10; + s[15] = '0' + x % 10; + s[16] = ':'; + x = tm.tm_sec; + s[17] = '0' + x / 10; + s[18] = '0' + x % 10; + s[19] = '.'; + s[26] = 0; + last = ts.tv_sec; + } + x = ts.tv_nsec; + s[20] = '0' + x / 100000000; + s[21] = '0' + x / 10000000 % 10; + s[22] = '0' + x / 1000000 % 10; + s[23] = '0' + x / 100000 % 10; + s[24] = '0' + x / 10000 % 10; + s[25] = '0' + x / 1000 % 10; + return s; +} + +int main(int argc, char *argv[]) { + char buf[128], *p = buf; + p = stpcpy(p, GetTimestamp()); + p = stpcpy(p, "\n"); + write(1, buf, p - buf); } diff --git a/libc/assert.h b/libc/assert.h index e73d1b030..26a915306 100644 --- a/libc/assert.h +++ b/libc/assert.h @@ -23,11 +23,18 @@ void __assert_fail(const char *, const char *, int) _Hide relegated; ({ \ if (__builtin_expect(!(x), 0)) { \ __assert_fail(s, __FILE__, __LINE__); \ - notpossible; \ + __builtin_trap(); \ } \ (void)0; \ }) #else +#define _npassert(x) \ + ({ \ + if (__builtin_expect(!(x), 0)) { \ + __builtin_trap(); \ + } \ + (void)0; \ + }) #define _unassert(x) \ ({ \ if (__builtin_expect(!(x), 0)) { \ @@ -35,13 +42,6 @@ void __assert_fail(const char *, const char *, int) _Hide relegated; } \ (void)0; \ }) -#define _npassert(x) \ - ({ \ - if (__builtin_expect(!(x), 0)) { \ - notpossible; \ - } \ - (void)0; \ - }) #endif COSMOPOLITAN_C_END_ diff --git a/libc/calls/write-nt.c b/libc/calls/write-nt.c index cf536e330..f1454bbdc 100644 --- a/libc/calls/write-nt.c +++ b/libc/calls/write-nt.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" @@ -47,7 +46,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size, if (offset != -1) { // windows changes the file pointer even if overlapped is passed - _npassert(SetFilePointerEx(h, 0, &p, SEEK_CUR)); + SetFilePointerEx(h, 0, &p, SEEK_CUR); } ok = WriteFile(h, data, _clampio(size), &sent, @@ -55,7 +54,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size, if (offset != -1) { // windows clobbers file pointer even on error - _npassert(SetFilePointerEx(h, p, 0, SEEK_SET)); + SetFilePointerEx(h, p, 0, SEEK_SET); } if (ok) { diff --git a/libc/intrin/assertfail.greg.c b/libc/intrin/assertfail.greg.c index a6f196437..788f0df17 100644 --- a/libc/intrin/assertfail.greg.c +++ b/libc/intrin/assertfail.greg.c @@ -18,49 +18,15 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/atomic.h" -#include "libc/calls/state.internal.h" -#include "libc/calls/syscall-sysv.internal.h" -#include "libc/errno.h" #include "libc/intrin/atomic.h" #include "libc/intrin/kprintf.h" -#include "libc/intrin/weaken.h" -#include "libc/log/backtrace.internal.h" -#include "libc/log/internal.h" -#include "libc/runtime/internal.h" -#include "libc/runtime/runtime.h" -#include "libc/runtime/symbols.internal.h" -#include "libc/thread/thread.h" -#include "libc/thread/tls.h" -relegated void __assert_fail(const char *expr, const char *file, int line) { - int me, owner; - static atomic_int once; +privileged void __assert_fail(const char *expr, const char *file, int line) { + static atomic_bool once; if (!__assert_disable) { - strace_enabled(-1); - ftrace_enabled(-1); - owner = 0; - me = __tls_enabled ? __get_tls()->tib_tid : __pid; - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); - kprintf("%s:%d: assert(%s) failed (tid %d) %m\n", file, line, expr, me); - if (__vforked || - atomic_compare_exchange_strong_explicit( - &once, &owner, me, memory_order_relaxed, memory_order_relaxed)) { - __restore_tty(); - if (_weaken(ShowBacktrace)) { - _weaken(ShowBacktrace)(2, __builtin_frame_address(0)); - } else if (_weaken(PrintBacktraceUsingSymbols) && - _weaken(GetSymbolTable)) { - _weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0), - _weaken(GetSymbolTable)()); - } else { - kprintf("can't backtrace b/c `ShowCrashReports` not linked\n"); - } - _Exitr(23); - } else if (owner == me) { - kprintf("assert failed while failing\n"); - _Exitr(24); - } else { - _Exit1(25); + if (!atomic_exchange(&once, true)) { + kprintf("%s:%d: assert(%s) failed (tid %P) %m\n", file, line, expr); } + __builtin_trap(); } } diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index deab3f780..68a06e209 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -120,7 +120,7 @@ long _missingno(); void _weakfree(void *); void *_mapanon(size_t) attributeallocsize((1)) mallocesque; void *_mapshared(size_t) attributeallocsize((1)) mallocesque; -void *_mapstack(void) returnsaligned((FRAMESIZE)) mallocesque; +void *_mapstack(void) returnsaligned((APE_PAGESIZE)) mallocesque; int _freestack(void *); void __oom_hook(size_t); void _peekall(void); diff --git a/libc/x/x.h b/libc/x/x.h index 0c5e4ed03..0b33edf2d 100644 --- a/libc/x/x.h +++ b/libc/x/x.h @@ -55,7 +55,7 @@ void *xrealloc(void *, size_t) attributeallocsize((2)) dontthrow nocallback dontdiscard; void *xcalloc(size_t, size_t) attributeallocsize((1, 2)) returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull; -void *xvalloc(size_t) attributeallocsize((1)) returnsaligned((FRAMESIZE)) +void *xvalloc(size_t) attributeallocsize((1)) returnsaligned((APE_PAGESIZE)) returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull; void *xmemalign(size_t, size_t) attributeallocalign((1)) attributeallocsize((2)) returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull; diff --git a/tool/scripts/cosmoc++ b/tool/scripts/cosmoc++ index 9187837af..f1f2dc8db 100755 --- a/tool/scripts/cosmoc++ +++ b/tool/scripts/cosmoc++ @@ -2,23 +2,50 @@ # # cosmopolitan c++ compiler # -# we assume you run the following beforehand +# getting started # # sudo chmod 1777 /opt -# cd /opt -# git clone https://github.com/jart/cosmopolitan cosmo -# cd cosmo -# make -j +# git clone https://github.com/jart/cosmopolitan /opt/cosmo +# (cd /opt/cosmo; make -j8 toolchain) +# sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /usr/local/bin/cosmocc +# sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /usr/local/bin/cosmoc++ +# cosmoc++ -o hello.com hello.cc +# ./foo.com +# ./foo.com.dbg # -# you can then use it to build open source projects, e.g. +# building open source projects # # export CC=cosmocc # export CXX=cosmoc++ -# export LD=cosmoc++ # ./configure --prefix=/opt/cosmos # make -j # make install # +# cosmopolitan runtime flags +# +# ./hello.com --strace +# ./hello.com --ftrace +# +# cosmpolitan runtime libraries +# +# #include +# int main() { +# ShowCrashReports(); +# __builtin_trap(); +# } +# +# building programs in tiny mode +# +# export MODE=tiny +# (cd /opt/cosmo; make -j8 toolchain) +# cosmoc++ -Os -o foo.com foo.cc +# +# hardening programs with memory safety +# +# export MODE=asan +# (cd /opt/cosmo; make -j8 toolchain) +# cosmoc++ -o foo.com foo.cc +# MODE=${MODE:-$m} COSMO=${COSMO:-/opt/cosmo} @@ -36,14 +63,14 @@ fi PLATFORM="-D__COSMOPOLITAN__" PREDEF="-include libc/integral/normalize.inc" -CCFLAGS="-g -fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" +CCFLAGS="-fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" CXXFLAGS="-fno-exceptions -fuse-cxa-atexit -fno-threadsafe-statics" CPPFLAGS="-DNDEBUG -nostdinc -iquote /opt/cosmo -isystem $COSMOS/include -isystem $COSMO/libc/isystem" LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd -Wl,-melf_x86_64 -Wl,--gc-sections -L$COSMOS/lib -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape-no-modify-self.o $COSMO/o/$MODE/libc/crt/crt.o" LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $COSMO/o/$MODE/cosmopolitan.a" -CXX="$COSMO/o/$MODE/third_party/gcc/bin/x86_64-linux-musl-g++" -OBJCOPY="$COSMO/o/$MODE/third_party/gcc/bin/x86_64-linux-musl-objcopy" +CXX="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-g++" +OBJCOPY="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" FIXUPOBJ="$COSMO/o/$MODE/tool/build/fixupobj.com" ZIPCOPY="$COSMO/o/$MODE/tool/build/zipcopy.com" @@ -57,6 +84,16 @@ if [ ! -d "$COSMOS" ]; then exit 1 fi +if [ ! -f "$CXX" ] || + [ ! -f "$OBJCOPY" ] || + [ ! -f "$FIXUPOBJ" ] || + [ ! -f "$ZIPCOPY" ]; then + echo "error: cosmopolitan artifacts missing; please run" >&2 + echo " cd $COSMOS" >&2 + echo " make -j8 m=$MODE toolchain" >&2 + exit 1 +fi + # auto-install some shell libraries if [ ! -d "$COSMOS/lib" ]; then mkdir "$COSMOS/lib" @@ -128,24 +165,27 @@ set -- "$CXX" "$@" printf '(cd %s; %s)\n' "$PWD" "$*" >>/tmp/build.log "$@" || exit -if [ $INTENT = cc ] && [ -n "$OUTPUT" ]; then - "$FIXUPOBJ" "$OUTPUT" || exit -elif [ $INTENT = ld ] && [ -n "$OUTPUT" ]; then - if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || - [ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then - # cosmocc -o foo.com ... - # -> foo.com (ape) - # -> foo.com.dbg (elf) - mv -f "$OUTPUT" "$OUTPUT.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit - "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit - else - # cosmocc -o foo ... - # -> foo (elf) - # -> foo.com (ape) - # -> foo.com.dbg (elf) - cp -f "$OUTPUT" "$OUTPUT.com.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT" "$OUTPUT.com" || exit - "$ZIPCOPY" "$OUTPUT" "$OUTPUT.com" || exit +if [ -n "$OUTPUT" ]; then + if [ $INTENT = cc ] || [ $INTENT = ld ]; then + "$FIXUPOBJ" "$OUTPUT" || exit + fi + if [ $INTENT = ld ]; then + if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || + [ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then + # cosmocc -o foo.com ... + # -> foo.com (ape) + # -> foo.com.dbg (elf) + mv -f "$OUTPUT" "$OUTPUT.dbg" || exit + "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit + "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit + else + # cosmocc -o foo ... + # -> foo (elf) + # -> foo.com (ape) + # -> foo.com.dbg (elf) + cp -f "$OUTPUT" "$OUTPUT.com.dbg" || exit + "$OBJCOPY" -S -O binary "$OUTPUT" "$OUTPUT.com" || exit + "$ZIPCOPY" "$OUTPUT" "$OUTPUT.com" || exit + fi fi fi diff --git a/tool/scripts/cosmocc b/tool/scripts/cosmocc index 893608903..c9b8422c8 100755 --- a/tool/scripts/cosmocc +++ b/tool/scripts/cosmocc @@ -2,23 +2,50 @@ # # cosmopolitan c compiler # -# we assume you run the following beforehand +# getting started # # sudo chmod 1777 /opt -# cd /opt -# git clone https://github.com/jart/cosmopolitan cosmo -# cd cosmo -# make -j +# git clone https://github.com/jart/cosmopolitan /opt/cosmo +# (cd /opt/cosmo; make -j8 toolchain) +# sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /usr/local/bin/cosmocc +# sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /usr/local/bin/cosmoc++ +# cosmocc -o hello.com hello.c +# ./foo.com +# ./foo.com.dbg # -# you can then use it to build open source projects, e.g. +# building open source projects # # export CC=cosmocc # export CXX=cosmoc++ -# export LD=cosmoc++ # ./configure --prefix=/opt/cosmos # make -j # make install # +# cosmopolitan runtime flags +# +# ./hello.com --strace +# ./hello.com --ftrace +# +# cosmpolitan runtime libraries +# +# #include +# int main() { +# ShowCrashReports(); +# __builtin_trap(); +# } +# +# building programs in tiny mode +# +# export MODE=tiny +# (cd /opt/cosmo; make -j8 toolchain) +# cosmocc -Os -o foo.com foo.c +# +# hardening programs with memory safety +# +# export MODE=asan +# (cd /opt/cosmo; make -j8 toolchain) +# cosmocc -o foo.com foo.c +# MODE=${MODE:-$m} COSMO=${COSMO:-/opt/cosmo} @@ -36,14 +63,14 @@ fi PLATFORM="-D__COSMOPOLITAN__" PREDEF="-include libc/integral/normalize.inc" -CCFLAGS="-g -fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" +CCFLAGS="-fdata-sections -ffunction-sections -fno-pie -mno-tls-direct-seg-refs -mno-red-zone -fportcosmo" CFLAGS= CPPFLAGS="-DNDEBUG -nostdinc -iquote /opt/cosmo -isystem $COSMOS/include -isystem $COSMO/libc/isystem" LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd -Wl,-melf_x86_64 -Wl,--gc-sections -L$COSMOS/lib -Wl,-T,$COSMO/o/$MODE/ape/public/ape.lds $COSMO/o/$MODE/ape/ape-no-modify-self.o $COSMO/o/$MODE/libc/crt/crt.o" LDLIBS="$COSMO/o/$MODE/cosmopolitan.a" -CC="$COSMO/o/$MODE/third_party/gcc/bin/x86_64-linux-musl-gcc" -OBJCOPY="$COSMO/o/$MODE/third_party/gcc/bin/x86_64-linux-musl-objcopy" +CC="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" +OBJCOPY="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy" FIXUPOBJ="$COSMO/o/$MODE/tool/build/fixupobj.com" ZIPCOPY="$COSMO/o/$MODE/tool/build/zipcopy.com" @@ -57,6 +84,16 @@ if [ ! -d "$COSMOS" ]; then exit 1 fi +if [ ! -f "$CC" ] || + [ ! -f "$OBJCOPY" ] || + [ ! -f "$FIXUPOBJ" ] || + [ ! -f "$ZIPCOPY" ]; then + echo "error: cosmopolitan artifacts missing; please run" >&2 + echo " cd $COSMOS" >&2 + echo " make -j8 m=$MODE toolchain" >&2 + exit 1 +fi + # auto-install some shell libraries if [ ! -d "$COSMOS/lib" ]; then mkdir "$COSMOS/lib" @@ -128,24 +165,19 @@ set -- "$CC" "$@" printf '(cd %s; %s)\n' "$PWD" "$*" >>/tmp/build.log "$@" || exit -if [ $INTENT = cc ] && [ -n "$OUTPUT" ]; then - "$FIXUPOBJ" "$OUTPUT" || exit -elif [ $INTENT = ld ] && [ -n "$OUTPUT" ]; then - if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || - [ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then - # cosmocc -o foo.com ... - # -> foo.com (ape) - # -> foo.com.dbg (elf) - mv -f "$OUTPUT" "$OUTPUT.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit - "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit - else - # cosmocc -o foo ... - # -> foo (elf) - # -> foo.com (ape) - # -> foo.com.dbg (elf) - cp -f "$OUTPUT" "$OUTPUT.com.dbg" || exit - "$OBJCOPY" -S -O binary "$OUTPUT" "$OUTPUT.com" || exit - "$ZIPCOPY" "$OUTPUT" "$OUTPUT.com" || exit +if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then + if [ $INTENT = cc ] || [ $INTENT = ld ]; then + "$FIXUPOBJ" "$OUTPUT" || exit + fi + if [ $INTENT = ld ]; then + if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] || + [ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then + # cosmocc -o foo.com ... + # -> foo.com (ape) + # -> foo.com.dbg (elf) + mv -f "$OUTPUT" "$OUTPUT.dbg" || exit + "$OBJCOPY" -S -O binary "$OUTPUT.dbg" "$OUTPUT" || exit + "$ZIPCOPY" "$OUTPUT.dbg" "$OUTPUT" || exit + fi fi fi