mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Improved support for freestanding.
This commit is contained in:
committed by
Christoffer Lerno
parent
a22ebbb0ef
commit
39801a304d
@@ -10,7 +10,7 @@ macro @volatile_load(&x) @builtin
|
||||
|
||||
macro @volatile_store(&x, y) @builtin
|
||||
{
|
||||
return $$volatile_store(&x, y);
|
||||
return $$volatile_store(&x, ($typeof(x))y);
|
||||
}
|
||||
|
||||
enum AtomicOrdering : int
|
||||
|
||||
@@ -120,13 +120,11 @@ macro sign(x)
|
||||
return ($typeof(x))(x < 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
$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, double) @extname("atan2");
|
||||
extern fn float _atan2f(float, float) @extname("atan2f");
|
||||
|
||||
/**
|
||||
* @require values::@is_int(x) || values::@is_float(x) "Expected an integer or floating point value"
|
||||
* @checked x + y
|
||||
**/
|
||||
macro atan2(x, y)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid):
|
||||
@@ -136,6 +134,10 @@ macro atan2(x, y)
|
||||
$endif;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require values::@is_int(x) || values::@is_float(x) "Expected an integer or floating point value"
|
||||
* @checked x + y
|
||||
**/
|
||||
macro atan(x)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid):
|
||||
@@ -145,32 +147,6 @@ macro atan(x)
|
||||
$endif;
|
||||
}
|
||||
|
||||
$else:
|
||||
|
||||
macro atan2(x, y)
|
||||
{
|
||||
$if ($typeof(x).typeid == float.typeid && $typeof(y).typeid == float.typeid):
|
||||
return atan::_atan2f(x, y);
|
||||
$else:
|
||||
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`
|
||||
**/
|
||||
@@ -625,3 +601,9 @@ macro is_nan(x)
|
||||
$assert(false, "Type cannot be used with is_nan");
|
||||
$endswitch;
|
||||
}
|
||||
|
||||
|
||||
extern fn double _atan(double x) @extname("atan");
|
||||
extern fn float _atanf(float x) @extname("atanf");
|
||||
extern fn double _atan2(double, double) @extname("atan2");
|
||||
extern fn float _atan2f(float, float) @extname("atan2f");
|
||||
|
||||
45
lib/std/math/math_nolibc/ceil.c3
Normal file
45
lib/std/math/math_nolibc/ceil.c3
Normal file
@@ -0,0 +1,45 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn double _ceil(double x) @weak @extname("ceil")
|
||||
{
|
||||
ulong ui = bitcast(x, ulong);
|
||||
int e = (int)((ui >> 52) & 0x7ff);
|
||||
if (e >= 0x3ff + 52 || x == 0) return x;
|
||||
// y = int(x) - x, where int(x) is an integer neighbor of x
|
||||
double y = ui >> 63 ? (x - TOINT) + TOINT - x : (x + TOINT) - TOINT - x;
|
||||
// special case because of non-nearest rounding modes
|
||||
if (e <= 0x3ff - 1)
|
||||
{
|
||||
@force_eval_add(y, 0);
|
||||
return ui >> 63 ? -0.0 : 1;
|
||||
}
|
||||
return y < 0 ? x + y + 1 : x + y;
|
||||
}
|
||||
|
||||
|
||||
fn float _ceilf(float x) @weak @extname("ceilf")
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (int)((u >> 23) & 0xff) - 0x7f;
|
||||
switch
|
||||
{
|
||||
case e >= 23:
|
||||
return x;
|
||||
case e >= 0:
|
||||
uint m = 0x007fffff >> e;
|
||||
if (u & m == 0) return x;
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
if (u >> 31 == 0) u += m;
|
||||
u &= ~m;
|
||||
case u >> 31 != 0:
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
return -0.0f;
|
||||
case u << 1 != 0:
|
||||
return 1;
|
||||
}
|
||||
return bitcast(u, float);
|
||||
}
|
||||
|
||||
$endif;
|
||||
15
lib/std/math/math_nolibc/exp2.c3
Normal file
15
lib/std/math/math_nolibc/exp2.c3
Normal file
@@ -0,0 +1,15 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn float exp2f_broken(float x) @extname("exp2f") @weak
|
||||
{
|
||||
unreachable("'exp2f' not supported");
|
||||
}
|
||||
|
||||
fn float exp2_broken(float x) @extname("exp2") @weak
|
||||
{
|
||||
unreachable("'exp2' not supported");
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -1,21 +1,45 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn double floor(double x) @weak @extname("floor")
|
||||
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)
|
||||
if (e >= 0x3ff + 52 || x == 0) return x;
|
||||
// y = int(x) - x, where int(x) is an integer neighbor of x
|
||||
double 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);
|
||||
@force_eval_add(y, 0);
|
||||
return ui >> 63 ? -1 : 0;
|
||||
}
|
||||
return y > 0 ? x + y - 1 : x + y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn float _floorf(float x) @weak @extname("floorf")
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (int)((u >> 23) & 0xff) - 0x7f;
|
||||
switch
|
||||
{
|
||||
case e >= 23:
|
||||
return x;
|
||||
case e >= 0:
|
||||
uint m = 0x007fffff >> e;
|
||||
if (u & m == 0) return x;
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
if (u >> 31) u += m;
|
||||
u &= ~m;
|
||||
case u >> 31 == 0:
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
u = 0;
|
||||
case (u << 1 != 0):
|
||||
return -1;
|
||||
}
|
||||
return bitcast(u, float);
|
||||
}
|
||||
|
||||
$endif;
|
||||
9
lib/std/math/math_nolibc/math_nolibc.c3
Normal file
9
lib/std/math/math_nolibc/math_nolibc.c3
Normal file
@@ -0,0 +1,9 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
const double TOINT = 1 / math::DOUBLE_EPSILON;
|
||||
const float TOINTF = (float)(1 / math::FLOAT_EPSILON);
|
||||
|
||||
macro @force_eval_add(&x, v)
|
||||
{
|
||||
@volatile_store(x, @volatile_load(x) + v);
|
||||
}
|
||||
15
lib/std/math/math_nolibc/pow.c3
Normal file
15
lib/std/math/math_nolibc/pow.c3
Normal file
@@ -0,0 +1,15 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn float powf_broken(float x) @extname("powf") @weak
|
||||
{
|
||||
unreachable("'powf' not supported");
|
||||
}
|
||||
|
||||
fn float pow_broken(float x) @extname("pow") @weak
|
||||
{
|
||||
unreachable("'pow' not supported");
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -170,8 +170,8 @@ fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec)
|
||||
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 */
|
||||
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
|
||||
@@ -221,7 +221,7 @@ fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec)
|
||||
if (ih == 2)
|
||||
{
|
||||
z = 1.0 - z;
|
||||
if (carry != 0) z -= nolibc::scalbn(1.0, q0);
|
||||
if (carry != 0) z -= nolibc::_scalbn(1.0, q0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec)
|
||||
else
|
||||
{
|
||||
/* break z into 24-bit if necessary */
|
||||
z = nolibc::scalbn(z,-q0);
|
||||
z = nolibc::_scalbn(z,-q0);
|
||||
if (z >= 0x1p24)
|
||||
{
|
||||
fw = (double)(int)(0x1p-24 * z);
|
||||
@@ -281,7 +281,7 @@ fn int __rem_pio2_large(double* x, double* y, int e0, int nx, int prec)
|
||||
}
|
||||
|
||||
/* convert integer "bit" chunk to floating-point value */
|
||||
fw = nolibc::scalbn(1.0 , q0);
|
||||
fw = nolibc::_scalbn(1.0 , q0);
|
||||
for (int i = jz; i >= 0; i --)
|
||||
{
|
||||
q[i] = fw * (double)iq[i];
|
||||
|
||||
56
lib/std/math/math_nolibc/round.c3
Normal file
56
lib/std/math/math_nolibc/round.c3
Normal file
@@ -0,0 +1,56 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn double _round(double x) @extname("round") @weak
|
||||
{
|
||||
ulong u = bitcast(x, ulong);
|
||||
int e = (int)((u >> 52) & 0x7ff);
|
||||
if (e >= 0x3ff + 52) return x;
|
||||
if (u >> 63) x = -x;
|
||||
if (e < 0x3ff - 1)
|
||||
{
|
||||
/* raise inexact if x!=0 */
|
||||
@force_eval_add(x, TOINT);
|
||||
return 0 * x;
|
||||
}
|
||||
double y = (x + TOINT) - TOINT - x;
|
||||
switch
|
||||
{
|
||||
case y > 0.5:
|
||||
y = y + x - 1;
|
||||
case y <= -0.5:
|
||||
y = y + x + 1;
|
||||
default:
|
||||
y = y + x;
|
||||
}
|
||||
if (u >> 63) y = -y;
|
||||
return y;
|
||||
}
|
||||
|
||||
fn float roundf(float x) @extname("roundf") @weak
|
||||
{
|
||||
uint u = bitcast(x, uint);
|
||||
int e = (u >> 23) & 0xff;
|
||||
if (e >= 0x7f + 23) return x;
|
||||
if (u >> 31) x = -x;
|
||||
if (e < 0x7f - 1)
|
||||
{
|
||||
@force_eval_add(x, TOINTF);
|
||||
return 0 * x;
|
||||
}
|
||||
float y = (x + TOINTF) - TOINTF - x;
|
||||
switch
|
||||
{
|
||||
case y > 0.5f:
|
||||
y = y + x - 1;
|
||||
case y <= -0.5f:
|
||||
y = y + x + 1;
|
||||
default:
|
||||
y = y + x;
|
||||
}
|
||||
if (u >> 31) y = -y;
|
||||
return y;
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -1,6 +1,8 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
fn double scalbn(double x, int n) @weak @extname("scalbn")
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn double _scalbn(double x, int n) @weak @extname("scalbn")
|
||||
{
|
||||
switch
|
||||
{
|
||||
@@ -24,4 +26,6 @@ fn double scalbn(double x, int n) @weak @extname("scalbn")
|
||||
}
|
||||
}
|
||||
return x * bitcast(((ulong)(0x3ff + n)) << 52, double);
|
||||
}
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -149,6 +149,10 @@ fn float cosf_broken(float x) @extname("cosf") @weak
|
||||
{
|
||||
unreachable("'cosf' not supported");
|
||||
}
|
||||
fn float sincosf_broken(float x) @extname("sincosf") @weak
|
||||
{
|
||||
unreachable("'sincosf' not supported");
|
||||
}
|
||||
|
||||
fn double sin_broken(double x) @extname("sin") @weak
|
||||
{
|
||||
@@ -158,20 +162,10 @@ fn double cos_broken(double x) @extname("cos") @weak
|
||||
{
|
||||
unreachable("'cos' not supported");
|
||||
}
|
||||
|
||||
fn float roundf_broken(float x) @extname("roundf") @weak
|
||||
fn double sincos_broken(double x) @extname("sincos") @weak
|
||||
{
|
||||
unreachable("'roundf' not supported");
|
||||
unreachable("'sinccos' 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;
|
||||
31
lib/std/math/math_nolibc/trunc.c3
Normal file
31
lib/std/math/math_nolibc/trunc.c3
Normal file
@@ -0,0 +1,31 @@
|
||||
module std::math::nolibc;
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn double _trunc(double x) @weak @extname("trunc")
|
||||
{
|
||||
ulong i = bitcast(x, ulong);
|
||||
int e = (int)((i >> 52) & 0x7ff) - 0x3ff + 12;
|
||||
if (e >= 52 + 12) return x;
|
||||
if (e < 12) e = 1;
|
||||
ulong m = ((ulong)-1) >> e;
|
||||
if (i & m == 0) return x;
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
i &= ~m;
|
||||
return bitcast(i, double);
|
||||
}
|
||||
|
||||
fn float _truncf(float x) @weak @extname("truncf")
|
||||
{
|
||||
uint i = bitcast(x, uint);
|
||||
int e = (int)((i >> 23) & 0xff) - 0x7f + 9;
|
||||
if (e >= 23 + 9) return x;
|
||||
if (e < 9) e = 1;
|
||||
uint m = ((uint)-1) >> e;
|
||||
if (i & m == 0) return x;
|
||||
@force_eval_add(x, 0x1p120f);
|
||||
i &= ~m;
|
||||
return bitcast(i, float);
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -1,4 +1,3 @@
|
||||
// #target: macos-x64
|
||||
module brainfk;
|
||||
import std::io;
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type)
|
||||
|
||||
add_arg("kernel32.lib");
|
||||
add_arg("ntdll.lib");
|
||||
add_arg("user32.lib");
|
||||
add_arg("legacy_stdio_definitions.lib");
|
||||
|
||||
if (active_target.win.crt_linking == WIN_CRT_STATIC)
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.21"
|
||||
#define COMPILER_VERSION "0.4.22"
|
||||
Reference in New Issue
Block a user