From a22ebbb0efe88acef06ebbba96f2f719dbd2733d Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 24 Jan 2023 22:11:48 +0100 Subject: [PATCH] Improved support for freestanding. --- lib/std/io/os/getcwd.c3 | 9 +- lib/std/libc/libc.c3 | 143 ++++++++++-- lib/std/libc/os/errno.c3 | 18 +- lib/std/math/math.c3 | 54 ++++- lib/std/math/math_libc.c3 | 47 ++++ lib/std/math/math_nolibc/atan.c3 | 324 +++++++++++++++++++++++++++ lib/std/math/math_nolibc/floor.c3 | 21 ++ lib/std/math/math_nolibc/rempi.c3 | 347 +++++++++++++++++++++++++++++ lib/std/math/math_nolibc/scalbn.c3 | 27 +++ lib/std/math/math_nolibc/trig.c3 | 177 +++++++++++++++ lib/std/threads/os/thread_none.c3 | 6 + lib/std/threads/thread.c3 | 8 +- src/compiler/linker.c | 4 - src/compiler/target.c | 10 +- src/version.h | 2 +- 15 files changed, 1152 insertions(+), 45 deletions(-) create mode 100644 lib/std/math/math_libc.c3 create mode 100644 lib/std/math/math_nolibc/atan.c3 create mode 100644 lib/std/math/math_nolibc/floor.c3 create mode 100644 lib/std/math/math_nolibc/rempi.c3 create mode 100644 lib/std/math/math_nolibc/scalbn.c3 create mode 100644 lib/std/math/math_nolibc/trig.c3 create mode 100644 lib/std/threads/os/thread_none.c3 diff --git a/lib/std/io/os/getcwd.c3 b/lib/std/io/os/getcwd.c3 index fc53b7711..cfe8f123d 100644 --- a/lib/std/io/os/getcwd.c3 +++ b/lib/std/io/os/getcwd.c3 @@ -1,7 +1,14 @@ module std::io::os; import libc; -$if (env::OS_TYPE == OsType.WIN32): +$if (!env::COMPILER_LIBC_AVAILABLE): + +fn String! getcwd(Allocator* allocator = mem::default_allocator()) +{ + unreachable("'getcwd' not available"); +} + +$elif (env::OS_TYPE == OsType.WIN32): extern fn Char16* _wgetcwd(Char16* buffer, int maxlen); extern fn usz wcslen(Char16* str); diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index fc7990bca..dcc0e31f3 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -4,9 +4,6 @@ module libc; -// stdlib - - // Constants need to be per os/arch const int EXIT_FAILURE = 1; const int EXIT_SUCCESS = 0; @@ -24,8 +21,6 @@ struct LongDivResult long rem; } - - fn Errno errno() { return (Errno)os::errno(); @@ -38,6 +33,10 @@ fn void errno_set(Errno e) define TerminateFunction = fn void(); define CompareFunction = fn int(void*, void*); +define JmpBuf = CInt[$$JMP_BUF_SIZE]; + +$if (env::COMPILER_LIBC_AVAILABLE): + extern fn double atof(char* str); extern fn int atoi(char* str); extern fn CLongLong atoll(char* str); @@ -58,8 +57,6 @@ extern fn LongDivResult ldiv(long number, long denom); extern fn int rand(); extern fn void srand(uint seed); -define JmpBuf = CInt[$$JMP_BUF_SIZE]; - extern fn void longjmp(JmpBuf* buffer, CInt value); $if (env::OS_TYPE == OsType.WIN32): // TODO win32 aarch64 @@ -75,7 +72,7 @@ extern fn void* memchr(void* str, int c, usz n); extern fn int memcmp(void* str1, void* str2, usz n); extern fn void* memcpy(void* dest, void* src, usz n); extern fn void* memmove(void* dest, void* src, usz n); -extern fn void* memset(void* dest, usz n); +extern fn void* memset(void* dest, CInt value, usz n); extern fn char* strcat(char* dest, char* src); extern fn char* strncat(char* dest, char* src, usz n); extern fn char* strchr(char* str, int c); @@ -99,13 +96,61 @@ extern fn void* calloc(usz count, usz size); extern fn void* free(void*); extern fn void* realloc(void* ptr, usz size); +$else: + +fn void longjmp(JmpBuf* buffer, CInt value) @weak @extname("longjmp") +{ + unreachable("longjmp unavailable"); +} + +fn CInt setjmp(JmpBuf* buffer) @weak @extname("setjmp") +{ + unreachable("setjmp unavailable"); +} + +fn void* malloc(usz size) @weak @extname("malloc") +{ + unreachable("malloc unavailable"); +} +fn void* calloc(usz count, usz size) @weak @extname("calloc") +{ + unreachable("calloc unavailable"); +} +fn void* free(void*) @weak @extname("free") +{ + unreachable("free unavailable"); +} + +fn void* realloc(void* ptr, usz size) @weak @extname("realloc") +{ + unreachable("realloc unavailable"); +} + +fn void* memcpy(void* dest, void* src, usz n) @weak @extname("memcpy") +{ + for (usz i = 0; i < n; i++) ((char*)dest)[i] = ((char*)src)[i]; + return dest; +} + +fn void* memmove(void* dest, void* src, usz n) @weak @extname("memmove") +{ + return memcpy(dest, src, n) @inline; +} + +fn void* memset(void* dest, CInt value, usz n) @weak @extname("memset") +{ + for (usz i = 0; i < n; i++) ((char*)dest)[i] = (char)value; + return dest; +} + +$endif; + // stdio define Fpos = long; define CFile = void*; -$switch (env::OS_TYPE): -$case OsType.LINUX: +$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX): extern CFile __stdin @extname("stdin"); extern CFile __stdout @extname("stdout"); extern CFile __stderr @extname("stderr"); @@ -115,7 +160,7 @@ $case OsType.LINUX: macro CFile stdin() { return __stdin; } macro CFile stdout() { return __stdout; } macro CFile stderr() { return __stderr; } -$case OsType.MACOSX: +$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX): extern CFile __stdinp; extern CFile __stdoutp; extern CFile __stderrp; @@ -124,19 +169,18 @@ $case OsType.MACOSX: macro CFile stdin() { return __stdinp; } macro CFile stdout() { return __stdoutp; } macro CFile stderr() { return __stderrp; } -$case OsType.WIN32: +$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32): extern fn CFile __acrt_iob_func(CInt c); extern fn usz _msize(void* ptr); macro usz malloc_size(void* ptr) { return _msize(ptr); } macro CFile stdin() { return __acrt_iob_func(0); } macro CFile stdout() { return __acrt_iob_func(1); } macro CFile stderr() { return __acrt_iob_func(2); } -$default: +$else: macro CFile stdin() { return (CFile*)(uptr)0; } macro CFile stdout() { return (CFile*)(uptr)1; } macro CFile stderr() { return (CFile*)(uptr)2; } -$endswitch; - +$endif; const HAS_MALLOC_SIZE = env::OS_TYPE == OsType.LINUX @@ -159,6 +203,8 @@ const int FILENAME_MAX = 1024; define Errno = distinct CInt; define SeekIndex = CLong; +$if (env::COMPILER_LIBC_AVAILABLE): + extern fn int fclose(CFile stream); extern fn void clearerr(CFile stream); extern fn int feof(CFile stream); @@ -190,13 +236,78 @@ extern fn char* fgets(char* str, int n, CFile stream); extern fn int fputc(int c, CFile stream); extern fn int getc(CFile stream); extern fn int getchar(); -extern fn int putc(char c, CFile stream); +extern fn int putc(int c, CFile stream); extern fn int putchar(int c); extern fn int puts(char* str); extern fn int ungetc(int c, CFile stream); extern fn void perror(char* str); extern fn isz getline(char** linep, usz* linecapp, CFile stream); +$else: + +fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extname("fseek") +{ + unreachable("'fseek' not available."); +} +fn CFile fopen(char* filename, char* mode) @weak @extname("fopen") +{ + unreachable("'fopen' not available."); +} + +fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream) @weak @extname("fwrite") +{ + unreachable("'fwrite' not available."); +} + +fn usz fread(void* ptr, usz size, usz nmemb, CFile stream) @weak @extname("fread") +{ + unreachable("'fread' not available."); +} + +fn CFile fclose(CFile) @weak @extname("fclose") +{ + unreachable("'fclose' not available."); +} + +fn int fflush(CFile stream) @weak @extname("fflush") +{ + unreachable("'fflush' not available."); +} + +fn int fputc(int c, CFile stream) @weak @extname("fputc") +{ + unreachable("'fputc' not available."); +} + +fn char* fgets(char* str, int n, CFile stream) @weak @extname("fgets") +{ + unreachable("'fgets' not available."); +} + +fn int fgetc(CFile stream) @weak @extname("fgetc") +{ + unreachable("'fgetc' not available."); +} + +fn int feof(CFile stream) @weak @extname("feof") +{ + unreachable("'feof' not available."); +} + +fn int putc(int c, CFile stream) @weak @extname("putc") +{ + unreachable("'putc' not available."); +} +fn int putchar(int c) @weak @extname("putchar") +{ + unreachable("'putchar' not available."); +} +fn int puts(char* str) @weak @extname("puts") +{ + unreachable("'puts' not available."); +} + +$endif; // vsprintf vprintf not supported // time.h diff --git a/lib/std/libc/os/errno.c3 b/lib/std/libc/os/errno.c3 index 338ae41ae..692544d62 100644 --- a/lib/std/libc/os/errno.c3 +++ b/lib/std/libc/os/errno.c3 @@ -1,21 +1,18 @@ module libc::os; -$switch (env::OS_TYPE): - -$case LINUX: +$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX): extern fn int* __errno_location(); - macro int errno() => *__errno_location(); macro void errno_set(int err) => *(__errno_location()) = err; -$case MACOSX: +$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX): extern fn int* __error(); macro int errno() => *__error(); macro void errno_set(int err) => *(__error()) = err; -$case WIN32: +$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32): macro int errno() { @@ -29,9 +26,10 @@ macro void errno_set(int err) => _set_errno(err); extern fn void _get_errno(int* result); extern fn void _set_errno(int err); -$default: +$else: -macro int errno() => 1; -fn void errno_set(int err) {} +tlocal int _errno_c3 = 0; +fn void errno_set(int err) => _errno_c3 = err; +fn int errno() => _errno_c3; -$endswitch; +$endif; diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index bb1ee6065..f484022b8 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -124,8 +124,17 @@ $if (env::COMPILER_LIBC_AVAILABLE): extern fn double _atan(double x) @extname("atan"); extern fn float _atanf(float x) @extname("atanf"); -extern fn double _atan2(double x) @extname("atan2"); -extern fn float _atan2f(float x) @extname("atan2f"); +extern fn double _atan2(double, double) @extname("atan2"); +extern fn float _atan2f(float, float) @extname("atan2f"); + +macro atan2(x, y) +{ + $if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid): + return _atan2f(x, y); + $else: + return _atan2(x, y); + $endif; +} macro atan(x) { @@ -136,16 +145,32 @@ macro atan(x) $endif; } +$else: + macro atan2(x, y) { $if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid): - return _atan2f(x); + return atan::_atan2f(x, y); $else: - return _atan2(x); + return atan::_atan2(x, y); + $endif; +} + +macro atan(x) +{ + $if ($typeof(x).typeid == float.typeid): + return atan::_atanf(x); + $else: + return atan::_atan(x); $endif; } $endif; + + + + + /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ @@ -575,15 +600,28 @@ macro next_power_of_2(x) return y; } -import std::io; private macro equals_vec(v1, v2) { var $elements = v1.len; var abs_diff = math::abs(v1 - v2); - io::printfn("diff %s", abs_diff); var abs_v1 = math::abs(v1); var abs_v2 = math::abs(v2); - io::printfn("abs %s", abs_v1); $typeof(abs_v2) eps = 1; return abs_diff.comp_le(FLOAT_EPSILON * math::max(abs_v1, abs_v2, eps)).and(); -} \ No newline at end of file +} + +macro uint double.high_word(double d) => (uint)(bitcast(d, ulong) >> 32); +macro uint double.low_word(double d) => (uint)bitcast(d, ulong); +macro uint float.word(float d) => bitcast(d, uint); + +macro is_nan(x) +{ + $switch ($typeof(x)): + $case float: + return bitcast(x, uint) & 0x7fffffff > 0x7f800000; + $case double: + return bitcast(x, ulong) & (((ulong)-1) >> 1) > (0x7ffu64 << 52); + $default: + $assert(false, "Type cannot be used with is_nan"); + $endswitch; +} diff --git a/lib/std/math/math_libc.c3 b/lib/std/math/math_libc.c3 new file mode 100644 index 000000000..0f467c540 --- /dev/null +++ b/lib/std/math/math_libc.c3 @@ -0,0 +1,47 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* atan(x) + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ +/* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +module std::math; + + + diff --git a/lib/std/math/math_nolibc/atan.c3 b/lib/std/math/math_nolibc/atan.c3 new file mode 100644 index 000000000..4be905c7e --- /dev/null +++ b/lib/std/math/math_nolibc/atan.c3 @@ -0,0 +1,324 @@ +module std::math::nolibc::atan; + +$if (!env::COMPILER_LIBC_AVAILABLE): + +private const double[*] ATANHI = { + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +private const double[*] ATANLO = { + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +private const double[*] AT = { + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +fn double _atan(double x) @weak @extname("atan") +{ + int id = void; + uint ix = x.high_word(); + uint sign = ix >> 31; + ix &= 0x7fffffff; + switch + { + case ix >= 0x44100000: + /* if |x| >= 2^66 */ + if (math::is_nan(x)) return x; + double z = ATANHI[3] + 0x1p-120f; + return sign ? -z : z; + case ix < 0x3fdc0000: + /* |x| < 0.4375 */ + if (ix < 0x3e400000) + { + /* |x| < 2^-27 */ + if (ix < 0x00100000) + { + /* raise underflow for subnormal x */ + (float)@volatile_load(x); + } + return x; + } + id = -1; + case ix < 0x3ff30000: + /* |x| < 1.1875 */ + x = math::abs(x); + if (ix < 0x3fe60000) + { + /* 7/16 <= |x| < 11/16 */ + id = 0; + x = (2 * x - 1) / (2 + x); + } + else + { /* 11/16 <= |x| < 19/16 */ + id = 1; + x = (x - 1) / (x + 1); + } + case ix < 0x40038000: + x = math::abs(x); + /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5) / (1 + 1.5 * x); + default: + /* 2.4375 <= |x| < 2^66 */ + id = 3; + x = -1 / math::abs(x); + } + /* end of argument reduction */ + double z = x * x; + double w = z * z; + /* break sum from i=0 to 10 AT[i]z**(i+1) into odd and even poly */ + double s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10]))))); + double s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9])))); + if (id < 0) return x - x * (s1 + s2); + z = ATANHI[id] - (x * (s1 + s2) - ATANLO[id] - x); + return sign ? -z : z; +} + +private const float[*] ATANHIF = { + 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ + 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ + 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ + 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ +}; + +private const float[*] ATANLOF = { + 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ + 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ + 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ + 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ +}; + +private const float[*] ATF = { + 3.3333328366e-01, + -1.9999158382e-01, + 1.4253635705e-01, + -1.0648017377e-01, + 6.1687607318e-02, +}; + +fn float _atanf(float x) @weak @extname("atanf") +{ + int id = void; + uint ix = x.word(); + uint sign = ix >> 31; + ix &= 0x7fffffff; + if (ix >= 0x4c800000) + { + /* if |x| >= 2**26 */ + if (math::is_nan(x)) return x; + float z = ATANHIF[3] + 0x1p-120f; + return sign ? -z : z; + } + switch + { + case ix < 0x3ee00000: + /* |x| < 0.4375 */ + if (ix < 0x39800000) + { + /* |x| < 2**-12 */ + if (ix < 0x00800000) + { + /* raise underflow for subnormal x */ + float f = @volatile_load(x); + f = f * f; + } + return x; + } + id = -1; + case ix < 0x3f980000: + /* |x| < 1.1875 */ + x = math::abs(x); + if (ix < 0x3f300000) + { + /* 7/16 <= |x| < 11/16 */ + id = 0; + x = (2.0f * x - 1.0f) / (2.0f + x); + break; + } + /* 11/16 <= |x| < 19/16 */ + id = 1; + x = (x - 1.0f) / (x + 1.0f); + case ix < 0x401c0000: + x = math::abs(x); + /* |x| < 2.4375 */ + id = 2; + x = (x - 1.5f) / (1.0f + 1.5f * x); + default: + /* 2.4375 <= |x| < 2**26 */ + x = math::abs(x); + id = 3; + x = -1.0f / x; + } + /* end of argument reduction */ + float z = x * x; + float w = z * z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + float s1 = z * (ATF[0] + w * (ATF[2] + w * ATF[4])); + float s2 = w * (ATF[1] + w * ATF[3]); + if (id < 0) return x - x * (s1 + s2) * 10000; + z = ATANHIF[id] - ((x * (s1 + s2) - ATANLOF[id]) - x); + return sign ? -z : z; +} + +private const PI_LO = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +private macro void extract_words(double d, uint* hi, uint* lo) +{ + ulong rep = bitcast(d, ulong); + *hi = (uint)(rep >> 32); + *lo = (uint)rep; +} + +fn double _atan2(double y, double x) @weak @extname("atan2") +{ + if (math::is_nan(x) || math::is_nan(y)) return x + y; + + uint lx = void; + uint ix = void; + extract_words(x, &ix, &lx); + uint ly = void; + uint iy = void; + extract_words(y, &iy, &ly); + + // x = 1.0 + if ((ix - 0x3ff00000) | lx == 0) return _atan(y); + // 2*sign(x) + sign(y) + uint m = ((iy >> 31) & 1) | ((ix >> 30) & 2); + ix = ix & 0x7fffffff; + iy = iy & 0x7fffffff; + + // when y = 0 + if (iy | ly == 0) + { + switch (m) + { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return math::PI; /* atan(+0,-anything) = pi */ + case 3: return -math::PI; /* atan(-0,-anything) =-pi */ + } + } + // when x = 0 */ + if (ix | lx == 0) return m & 1 ? -math::PI_2 : math::PI_2; + /* when x is INF */ + if (ix == 0x7ff00000) + { + if (iy == 0x7ff00000) + { + switch (m) + { + case 0: return math::PI_4; /* atan(+INF,+INF) */ + case 1: return -math::PI_4; /* atan(-INF,+INF) */ + case 2: return math::PI_4 + math::PI_2; /* atan(+INF,-INF) */ + case 3: return - (math::PI_4 + math::PI_2); /* atan(-INF,-INF) */ + } + unreachable(); + } + switch (m) + { + case 0: return 0.0; /* atan(+...,+INF) */ + case 1: return -0.0; /* atan(-...,+INF) */ + case 2: return math::PI; /* atan(+...,-INF) */ + case 3: return -math::PI; /* atan(-...,-INF) */ + } + unreachable(); + } + /* |y/x| > 0x1p64 */ + if (ix + (64 << 20) < iy || iy == 0x7ff00000) return m & 1 ? -math::PI_2 : math::PI_2; + + /* z = atan(|y/x|) without spurious underflow */ + double z = ((m & 2) && iy + (64 << 20) < ix) ? 0 : _atan(math::abs(y/x)); + switch (m) + { + case 0: return z; /* atan(+,+) */ + case 1: return -z; /* atan(-,+) */ + case 2: return math::PI - (z - PI_LO); /* atan(+,-) */ + default: return (z - PI_LO) - math::PI; /* atan(-,-) */ + } +} + +private const float PI_F = 3.1415927410e+00; /* 0x40490fdb */ +private const float PI_LO_F = -8.7422776573e-08; /* 0xb3bbbd2e */ + +fn float _atan2f(float y, float x) @weak @extname("atan2f") +{ + if (math::is_nan(x) || math::is_nan(y)) return x + y; + uint ix = bitcast(x, uint); + uint iy = bitcast(y, uint); + /* x=1.0 */ + if (ix == 0x3f800000) return _atanf(y); + /* 2*sign(x)+sign(y) */ + uint m = ((iy >> 31) & 1) | ((ix >> 30) & 2); + ix &= 0x7fffffff; + iy &= 0x7fffffff; + + /* when y = 0 */ + if (iy == 0) + { + switch (m) + { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return PI_F; /* atan(+0,-anything) = pi */ + case 3: return -PI_F; /* atan(-0,-anything) =-pi */ + } + unreachable(); + } + /* when x = 0 */ + if (ix == 0) return m & 1 ? -(float)math::PI_2 : (float)math::PI_2; + /* when x is INF */ + if (ix == 0x7f800000) + { + if (iy == 0x7f800000) + { + switch (m) + { + case 0: return (float)math::PI_4; /* atan(+INF,+INF) */ + case 1: return (float)-math::PI_4; /* atan(-INF,+INF) */ + case 2: return (float)(math::PI_4 + math::PI_2); /*atan(+INF,-INF)*/ + case 3: return -(float)(math::PI_4 + math::PI_2); /*atan(-INF,-INF)*/ + } + unreachable(); + } + switch (m) + { + case 0: return 0.0f; /* atan(+...,+INF) */ + case 1: return -0.0f; /* atan(-...,+INF) */ + case 2: return PI_F; /* atan(+...,-INF) */ + case 3: return -PI_F; /* atan(-...,-INF) */ + } + unreachable(); + } + /* |y/x| > 0x1p26 */ + if (ix + 26 << 23 < iy || iy == 0x7f800000) return m & 1 ? -(float)math::PI_2 : (float)math::PI_2; + + /* z = atan(|y/x|) with correct underflow */ + /*|y/x| < 0x1p-26, x < 0 */ + float z = (m & 2 && iy + 26 << 23 < ix) ? 0.0f : _atanf(math::abs(y / x)); + switch (m) + { + case 0: return z; /* atan(+,+) */ + case 1: return -z; /* atan(-,+) */ + case 2: return PI_F - (z - PI_LO_F); /* atan(+,-) */ + default: return (z - PI_LO_F) - PI_F; /* atan(-,-) */ + } +} + +$endif; \ No newline at end of file diff --git a/lib/std/math/math_nolibc/floor.c3 b/lib/std/math/math_nolibc/floor.c3 new file mode 100644 index 000000000..1b8534f41 --- /dev/null +++ b/lib/std/math/math_nolibc/floor.c3 @@ -0,0 +1,21 @@ +module std::math::nolibc; + + +fn double floor(double x) @weak @extname("floor") +{ + const double TOINT = 1 / math::DOUBLE_EPSILON; + ulong ui = bitcast(x, ulong); + int e = (int)((ui >> 52) & 0x7ff); + double y; + if (e >= 0x3ff+52 || x == 0) return x; + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + y = ui >> 63 ? (x - TOINT) + TOINT - x : (x + TOINT) - TOINT - x; + + /* special case because of non-nearest rounding modes */ + if (e <= 0x3ff-1) + { + @volatile_load(y); + return ui >> 63 ? -1 : 0; + } + return y > 0 ? x + y - 1 : x + y; +} \ No newline at end of file diff --git a/lib/std/math/math_nolibc/rempi.c3 b/lib/std/math/math_nolibc/rempi.c3 new file mode 100644 index 000000000..69a376e36 --- /dev/null +++ b/lib/std/math/math_nolibc/rempi.c3 @@ -0,0 +1,347 @@ +module std::math::nolibc::rempi; +import std::math; +/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Debugged and optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* __rem_pio2f(x,y) + * + * return the remainder of x rem pi/2 in *y + * use double precision for everything except passing x + * use __rem_pio2_large() for large x + */ + +$if (!env::COMPILER_LIBC_AVAILABLE): + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 25 bits of pi/2 + * pio2_1t: pi/2 - pio2_1 + */ +private const double TOINT = 1.5 / math::DOUBLE_EPSILON; +private const double PIO4 = 0x1.921fb6p-1; +private const double INVPIO2 = 6.36619772367581382433e-01; /* 0x3FE45F30, 0x6DC9C883 */ +private const double PIO2_1 = 1.57079631090164184570e+00; /* 0x3FF921FB, 0x50000000 */ +private const double PIO2_1T = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ + +fn int __rem_pio2f(float x, double *y) +{ + uint ux = bitcast(x, uint); + uint ix = ux & 0x7fffffff; + /* 25+53 bit pi is good enough for medium size */ + if (ix < 0x4dc90fdb) + { + // |x| ~< 2^28*(pi/2), medium size + // Use a specialized rint() to get f. + uint f = (uint)(((double)x * INVPIO2 + TOINT) - TOINT); + int n = (int)f; + *y = x - f * PIO2_1 - f * PIO2_1T; + /* Matters with directed rounding. */ + if (*y < -PIO4) // likely false + { + n--; + f--; + *y = x - f * PIO2_1 - f * PIO2_1T; + } + else if (*y > PIO4) // likely false + { + n++; + f++; + *y = x - f * PIO2_1 - f * PIO2_1T; + } + return n; + } + if (ix >= 0x7f800000) + { + // x is inf or NaN */ + *y = x-x; + return 0; + } + /* scale x into [2^23, 2^24-1] */ + int sign = ux >> 31; + int e0 = (ix >> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */ + ux = ix - e0 << 23; + double tx = bitcast(ux, float); + double ty = void; + int n = __rem_pio2_large(&tx,&ty, e0, 1, 0); + if (sign) + { + *y = (float)-ty; + return -n; + } + *y = (float)ty; + return n; +} + +/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +const int[*] INIT_JK = {3,4,4,6}; /* initial value for jk */ + +const int[*] IPIO2 = { +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, }; + +const double[*] PIO2 = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec) +{ + double[20] f = void; + double[20] fq = void; + double[20] q = void; + int[20] iq = void; + double fw = void; + /* initialize jk*/ + int jk = INIT_JK[prec]; + int jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + int jx = nx - 1; + int jv = (e0 - 3) / 24; + if (jv < 0) jv = 0; + int q0 = e0 - 24 * (jv + 1); + + // set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] + int j = jv - jx; + int m = jx + jk; + for (int i = 0; i <= m; i++, j++) + { + f[i] = j < 0 ? 0.0 : (double)IPIO2[j]; + } + + // compute q[0],q[1],...q[jk] + for (int i = 0; i <= jk; i++) + { + for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j]; + q[i] = fw; + } + + int jz = jk; + double z = void; + int ih = 0; + int n = void; + while (1) + { + /* distill q[] into iq[] reversingly */ + z = q[jz]; + j = jz; + for (int i = 0; j > 0; i++, j--) + { + fw = (double)(int)(0x1p-24 * z); + iq[i] = (int)(z - 0x1p24 * fw); + z = q[j - 1] + fw; + } + // compute n + z = nolibc::scalbn(z, q0); /* actual value of z */ + z -= 8.0 * nolibc::floor(z * 0.125); /* trim off integer >= 8 */ + n = (int)z; + z -= (double)n; + switch + { + case q0 > 0: + // need iq[jz-1] to determine n + int i = iq[jz - 1] >> (24 - q0); + n += i; + iq[jz - 1] -= i << (24 - q0); + ih = iq[jz - 1] >> (23 - q0); + case q0 == 0: + ih = iq[jz - 1] >> 23; + case z >= 0.5: + ih = 2; + } + if (ih > 0) + { + /* q > 0.5 */ + n += 1; + int carry = 0; + for (int i = 0; i < jz; i++) + { + /* compute 1-q */ + j = iq[i]; + if (carry == 0) + { + if (j != 0) + { + carry = 1; + iq[i] = 0x1000000 - j; + } + } + else + { + iq[i] = 0xffffff - j; + } + } + if (q0 > 0) + { + /* rare case: chance is 1 in 12 */ + switch (q0) + { + case 1: iq[jz - 1] &= 0x7fffff; + case 2: iq[jz - 1] &= 0x3fffff; + } + } + if (ih == 2) + { + z = 1.0 - z; + if (carry != 0) z -= nolibc::scalbn(1.0, q0); + } + } + + // check if recomputation is needed + if (z == 0.0) + { + j = 0; + for (int i = jz - 1; i >= jk; i--) j |= iq[i]; + if (j == 0) + { + /* need recomputation */ + int k = 1; + for (; iq[jk - k] == 0; k++); /* k = no. of terms needed */ + + for (int i = jz + 1; i <= jz + k; i++) + { + /* add q[jz+1] to q[jz+k] */ + f[jx + i] = (double)IPIO2[jv + i]; + for (j = 0, fw = 0.0; j <= jx; j++) + fw += x[j] * f[jx + i - j]; + q[i] = fw; + } + jz += k; + continue; + } + } + break; + } + + /* chop off zero terms */ + if (z == 0.0) + { + jz -= 1; + q0 -= 24; + while (iq[jz] == 0) + { + jz--; + q0 -= 24; + } + } + else + { + /* break z into 24-bit if necessary */ + z = nolibc::scalbn(z,-q0); + if (z >= 0x1p24) + { + fw = (double)(int)(0x1p-24 * z); + iq[jz] = (int)(z - 0x1p24 * fw); + jz += 1; + q0 += 24; + iq[jz] = (int)fw; + } + else + { + iq[jz] = (int)z; + } + } + + /* convert integer "bit" chunk to floating-point value */ + fw = nolibc::scalbn(1.0 , q0); + for (int i = jz; i >= 0; i --) + { + q[i] = fw * (double)iq[i]; + fw *= 0x1p-24; + } + + /* compute PIO2[0,...,jp]*q[jz,...,0] */ + for (int i = jz; i >= 0; i--) + { + for (fw = 0.0, int k = 0; k <= jp && k <= jz-i; k++) fw += PIO2[k] * q[i + k]; + fq[jz - i] = fw; + } + + /* compress fq[] into y[] */ + switch (prec) + { + case 0: + fw = 0.0; + for (int i = jz; i >= 0; i--) fw += fq[i]; + y[0] = ih == 0 ? fw : -fw; + case 1: + case 2: + fw = 0.0; + for (int i = jz; i >= 0; i--) + fw += fq[i]; + // TODO: drop excess precision here once double_t is used + fw = (double)fw; + y[0] = ih == 0 ? fw : -fw; + fw = fq[0]-fw; + for (int i = 1; i <= jz; i++) fw += fq[i]; + y[1] = ih == 0 ? fw : -fw; + case 3: /* painful */ + for (int i = jz; i > 0; i--) + { + fw = fq[i - 1] + fq[i]; + fq[i] += fq[i - 1] - fw; + fq[i - 1] = fw; + } + for (int i = jz; i > 1; i--) + { + fw = fq[i-1] + fq[i]; + fq[i] += fq[i - 1] - fw; + fq[i - 1] = fw; + } + for (fw = 0.0, int i = jz; i >= 2; i--) + fw += fq[i]; + if (ih == 0) + { + y[0] = fq[0]; + y[1] = fq[1]; + y[2] = fw; + } + else + { + y[0] = -fq[0]; + y[1] = -fq[1]; + y[2] = -fw; + } + } + return n & 7; +} + +$endif; \ No newline at end of file diff --git a/lib/std/math/math_nolibc/scalbn.c3 b/lib/std/math/math_nolibc/scalbn.c3 new file mode 100644 index 000000000..7d36dfb3a --- /dev/null +++ b/lib/std/math/math_nolibc/scalbn.c3 @@ -0,0 +1,27 @@ +module std::math::nolibc; + +fn double scalbn(double x, int n) @weak @extname("scalbn") +{ + switch + { + case n > 1023: + x *= 0x1p1023; + n -= 1023; + if (n > 1023) + { + x *= 0x1p1023; + n -= 1023; + if (n > 1023) n = 1023; + } + case n < -1022: + x *= 0x1p-1022 * 0x1p53; + n += 1022 - 53; + if (n < -1022) + { + x *= 0x1p-1022 * 0x1p53; + n += 1022 - 53; + if (n < -1022) n = -1022; + } + } + return x * bitcast(((ulong)(0x3ff + n)) << 52, double); +} \ No newline at end of file diff --git a/lib/std/math/math_nolibc/trig.c3 b/lib/std/math/math_nolibc/trig.c3 new file mode 100644 index 000000000..43439f393 --- /dev/null +++ b/lib/std/math/math_nolibc/trig.c3 @@ -0,0 +1,177 @@ +module std::math::nolibc::trig; + +$if (!env::COMPILER_LIBC_AVAILABLE): + + +/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +private const double S1PI2_F = math::PI_2; /* 0x3FF921FB, 0x54442D18 */ +private const double S2PI2_F = math::PI; /* 0x400921FB, 0x54442D18 */ +private const double S3PI2_F = math::PI + math::PI_2; /* 0x4012D97C, 0x7F3321D2 */ +private const double S4PI2_F = math::PI + math::PI; /* 0x401921FB, 0x54442D18 */ + +fn float _sinf(float x) @weak @extname("sinf") +{ + uint ix = bitcast(x, uint); + int sign = ix >> 31; + ix &= 0x7fffffff; + switch + { + case ix <= 0x3f490fda: + // |x| ~<= pi/4 + if (ix < 0x39800000) + { + /* |x| < 2**-12 */ + // raise inexact if x!=0 and underflow if subnormal + if (ix < 0x00800000) + { + @volatile_load(x) / 0x1p120f; + } + else + { + @volatile_load(x) + 0x1p120f; + } + return x; + } + return __sindf(x); + case ix <= 0x407b53d1: + // |x| ~<= 5*pi/4 + if (ix <= 0x4016cbe3) + { + // |x| ~<= 3pi/4 + if (sign) return -__cosdf(x + S1PI2_F); + return __cosdf(x - S1PI2_F); + } + return __sindf(sign ? -(x + S2PI2_F) : -(x - S2PI2_F)); + case ix <= 0x40e231d5: + // |x| ~<= 9*pi/4 + if (ix <= 0x40afeddf) + { + // |x| ~<= 7*pi/4 + return sign ? __cosdf(x + S3PI2_F) : -__cosdf(x - S3PI2_F); + } + return __sindf(sign ? x + S4PI2_F : x - S4PI2_F); + case ix >= 0x7f800000: + // sin(Inf or NaN) is NaN + return x - x; + } + /* general argument reduction needed */ + double y = void; + int n = rempi::__rem_pio2f(x, &y); + switch (n & 3) + { + case 0: return __sindf(y); + case 1: return __cosdf(y); + case 2: return __sindf(-y); + default: return -__cosdf(y); + } + unreachable(); +} + +/* origin: FreeBSD /usr/src/lib/msun/src/k_sinf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + +/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */ +private const double S1 = -0x15555554cbac77.0p-55; /* -0.166666666416265235595 */ +private const double S2 = 0x111110896efbb2.0p-59; /* 0.0083333293858894631756 */ +private const double S3 = -0x1a00f9e2cae774.0p-65; /* -0.000198393348360966317347 */ +private const double S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */ + +fn float __sindf(double x) +{ + double z = x * x; + double w = z * z; + double r = S3 + z * S4; + double s = z * x; + return (float)((x + s * (S1 + z * S2)) + s * w * r); +} + +/* origin: FreeBSD /usr/src/lib/msun/src/k_cosf.c */ +/* + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + * Debugged and optimized by Bruce D. Evans. + */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ + +private const double C0 = -0x1ffffffd0c5e81.0p-54; /* -0.499999997251031003120 */ +private const double C1 = 0x155553e1053a42.0p-57; /* 0.0416666233237390631894 */ +private const double C2 = -0x16c087e80f1e27.0p-62; /* -0.00138867637746099294692 */ +private const double C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ + +fn float __cosdf(double x) +{ + /* Try to optimize for parallel evaluation as in __tandf.c. */ + double z = x * x; + double w = z * z; + double r = C2 + z * C3; + return (float)(((1.0f + z * C0) + w * C1) + (w * z) * r); +} + +fn float cosf_broken(float x) @extname("cosf") @weak +{ + unreachable("'cosf' not supported"); +} + +fn double sin_broken(double x) @extname("sin") @weak +{ + unreachable("'sin' not supported"); +} +fn double cos_broken(double x) @extname("cos") @weak +{ + unreachable("'cos' not supported"); +} + +fn float roundf_broken(float x) @extname("roundf") @weak +{ + unreachable("'roundf' not supported"); +} + +fn double round_broken(double x) @extname("round") @weak +{ + unreachable("'round' not supported"); +} + +fn float powf_broken(float x) @extname("powf") @weak +{ + unreachable("'powf' not supported"); +} + +$endif; \ No newline at end of file diff --git a/lib/std/threads/os/thread_none.c3 b/lib/std/threads/os/thread_none.c3 new file mode 100644 index 000000000..f216d0f0f --- /dev/null +++ b/lib/std/threads/os/thread_none.c3 @@ -0,0 +1,6 @@ +module std::thread; + +define NativeMutex = distinct int; +define NativeConditionVariable = distinct int; +define NativeOnceFlag = distinct int; +define NativeThread = distinct int; \ No newline at end of file diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index 98e4af76c..ac615b082 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -3,9 +3,15 @@ module std::thread; enum ThreadModel { WIN32, - POSIX + POSIX, + NONE } + +$if (env::COMPILER_LIBC_AVAILABLE): const ThreadModel THREAD_MODEL = env::OS_TYPE == OsType.WIN32 ? ThreadModel.WIN32 : ThreadModel.POSIX; +$else: +const ThreadModel THREAD_MODEL = NONE; +$endif; define MutexType = distinct int; diff --git a/src/compiler/linker.c b/src/compiler/linker.c index e75738440..63e0f0d1d 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -498,10 +498,6 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns } break; case OS_TYPE_NONE: - if (!active_target.no_libc) - { - error_exit("Linking is not supported for freestanding."); - } break; } for (unsigned i = 0; i < file_count; i++) diff --git a/src/compiler/target.c b/src/compiler/target.c index e841d93d0..b3cab3610 100644 --- a/src/compiler/target.c +++ b/src/compiler/target.c @@ -5,6 +5,7 @@ extern void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array); +static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type); static unsigned arch_pointer_bit_width(OsType os, ArchType arch); static ArchType arch_from_llvm_string(StringSlice string); static EnvironmentType environment_type_from_llvm_string(StringSlice string); @@ -14,7 +15,6 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b static AlignData os_target_alignment_of_float(OsType os, ArchType arch, uint32_t bits); static OsType os_from_llvm_string(StringSlice string); static VendorType vendor_from_llvm_string(StringSlice string); -static ObjectFormatType object_format_from_os(OsType os); static unsigned os_target_supports_int128(OsType os, ArchType arch); static unsigned os_target_supports_float16(OsType os, ArchType arch); static unsigned os_target_supports_float128(OsType os, ArchType arch); @@ -895,15 +895,17 @@ static unsigned os_target_supports_vec(OsType os, ArchType arch, int bits, bool } } -static ObjectFormatType object_format_from_os(OsType os) +static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type) { switch (os) { case OS_UNSUPPORTED: return OBJ_FORMAT_UNSUPPORTED; - case OS_TYPE_LINUX: case OS_TYPE_UNKNOWN: case OS_TYPE_NONE: + if (arch_type == ARCH_TYPE_WASM64 || arch_type == ARCH_TYPE_WASM32) return OBJ_FORMAT_WASM; + FALLTHROUGH; + case OS_TYPE_LINUX: case OS_TYPE_NETBSD: case OS_TYPE_OPENBSD: case OS_TYPE_FREE_BSD: @@ -1395,7 +1397,7 @@ void target_setup(BuildTarget *target) platform_target.big_endian = arch_big_endian(platform_target.arch); platform_target.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch); platform_target.alloca_address_space = 0; - platform_target.object_format = object_format_from_os(platform_target.os); + platform_target.object_format = object_format_from_os(platform_target.os, platform_target.arch); switch (platform_target.object_format) { case OBJ_FORMAT_COFF: diff --git a/src/version.h b/src/version.h index 43cf87680..36044fc90 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.20" \ No newline at end of file +#define COMPILER_VERSION "0.4.21" \ No newline at end of file