mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add saturated math and expect macros.
This commit is contained in:
@@ -120,6 +120,17 @@ macro enum_by_name($Type, String enum_name) @builtin
|
||||
return SearchResult.MISSING!;
|
||||
}
|
||||
|
||||
macro bool @expect_true(bool value) @builtin => $$expect(value, true);
|
||||
macro bool @expect_false(bool value) @builtin => $$expect(value, false);
|
||||
|
||||
/**
|
||||
* @require values.is_int(value)
|
||||
* @checked $typeof(value) a = expected
|
||||
**/
|
||||
macro @expect(value, expected) @builtin
|
||||
{
|
||||
return $$expect(value, ($typeof(value))expected);
|
||||
}
|
||||
/**
|
||||
* Locality for prefetch, levels 0 - 3, corresponding
|
||||
* to "extremely local" to "no locality"
|
||||
|
||||
@@ -593,6 +593,56 @@ macro uint128 uint128[<*>].xor(uint128[<*>] x) => $$reduce_xor(x);
|
||||
macro uint128 uint128[<*>].max(uint128[<*>] x) => $$reduce_max(x);
|
||||
macro uint128 uint128[<*>].min(uint128[<*>] x) => $$reduce_min(x);
|
||||
|
||||
macro char char.sat_add(char x, char y) => $$sat_add(x, y);
|
||||
macro char char.sat_sub(char x, char y) => $$sat_sub(x, y);
|
||||
macro char char.sat_mul(char x, char y) => $$sat_mul(x, y);
|
||||
macro char char.sat_shl(char x, char y) => $$sat_shl(x, y);
|
||||
|
||||
macro ichar ichar.sat_add(ichar x, ichar y) => $$sat_add(x, y);
|
||||
macro ichar ichar.sat_sub(ichar x, ichar y) => $$sat_sub(x, y);
|
||||
macro ichar ichar.sat_mul(ichar x, ichar y) => $$sat_mul(x, y);
|
||||
macro ichar ichar.sat_shl(ichar x, ichar y) => $$sat_shl(x, y);
|
||||
|
||||
macro ushort ushort.sat_add(ushort x, ushort y) => $$sat_add(x, y);
|
||||
macro ushort ushort.sat_sub(ushort x, ushort y) => $$sat_sub(x, y);
|
||||
macro ushort ushort.sat_mul(ushort x, ushort y) => $$sat_mul(x, y);
|
||||
macro ushort ushort.sat_shl(ushort x, ushort y) => $$sat_shl(x, y);
|
||||
|
||||
macro short short.sat_add(short x, short y) => $$sat_add(x, y);
|
||||
macro short short.sat_sub(short x, short y) => $$sat_sub(x, y);
|
||||
macro short short.sat_mul(short x, short y) => $$sat_mul(x, y);
|
||||
macro short short.sat_shl(short x, short y) => $$sat_shl(x, y);
|
||||
|
||||
macro uint uint.sat_add(uint x, uint y) => $$sat_add(x, y);
|
||||
macro uint uint.sat_sub(uint x, uint y) => $$sat_sub(x, y);
|
||||
macro uint uint.sat_mul(uint x, uint y) => $$sat_mul(x, y);
|
||||
macro uint uint.sat_shl(uint x, uint y) => $$sat_shl(x, y);
|
||||
|
||||
macro int int.sat_add(int x, int y) => $$sat_add(x, y);
|
||||
macro int int.sat_sub(int x, int y) => $$sat_sub(x, y);
|
||||
macro int int.sat_mul(int x, int y) => $$sat_mul(x, y);
|
||||
macro int int.sat_shl(int x, int y) => $$sat_shl(x, y);
|
||||
|
||||
macro ulong ulong.sat_add(ulong x, ulong y) => $$sat_add(x, y);
|
||||
macro ulong ulong.sat_sub(ulong x, ulong y) => $$sat_sub(x, y);
|
||||
macro ulong ulong.sat_mul(ulong x, ulong y) => $$sat_mul(x, y);
|
||||
macro ulong ulong.sat_shl(ulong x, ulong y) => $$sat_shl(x, y);
|
||||
|
||||
macro long long.sat_add(long x, long y) => $$sat_add(x, y);
|
||||
macro long long.sat_sub(long x, long y) => $$sat_sub(x, y);
|
||||
macro long long.sat_mul(long x, long y) => $$sat_mul(x, y);
|
||||
macro long long.sat_shl(long x, long y) => $$sat_shl(x, y);
|
||||
|
||||
macro uint128 uint128.sat_add(uint128 x, uint128 y) => $$sat_add(x, y);
|
||||
macro uint128 uint128.sat_sub(uint128 x, uint128 y) => $$sat_sub(x, y);
|
||||
macro uint128 uint128.sat_mul(uint128 x, uint128 y) => $$sat_mul(x, y);
|
||||
macro uint128 uint128.sat_shl(uint128 x, uint128 y) => $$sat_shl(x, y);
|
||||
|
||||
macro int128 int128.sat_add(int128 x, int128 y) => $$sat_add(x, y);
|
||||
macro int128 int128.sat_sub(int128 x, int128 y) => $$sat_sub(x, y);
|
||||
macro int128 int128.sat_mul(int128 x, int128 y) => $$sat_mul(x, y);
|
||||
macro int128 int128.sat_shl(int128 x, int128 y) => $$sat_shl(x, y);
|
||||
|
||||
/**
|
||||
* @checked x & 1
|
||||
*/
|
||||
|
||||
@@ -833,6 +833,8 @@ typedef enum
|
||||
BUILTIN_EXACT_SUB,
|
||||
BUILTIN_EXP,
|
||||
BUILTIN_EXP2,
|
||||
BUILTIN_EXPECT,
|
||||
BUILTIN_EXPECT_WITH_PROBABILITY,
|
||||
BUILTIN_FLOOR,
|
||||
BUILTIN_FMA,
|
||||
BUILTIN_FMULADD,
|
||||
@@ -895,7 +897,6 @@ typedef enum
|
||||
BUILTIN_VOLATILE_STORE,
|
||||
BUILTIN_WASM_MEMORY_SIZE,
|
||||
BUILTIN_WASM_MEMORY_GROW,
|
||||
|
||||
BUILTIN_NONE,
|
||||
NUMBER_OF_BUILTINS = BUILTIN_NONE,
|
||||
|
||||
|
||||
@@ -633,6 +633,8 @@ static void llvm_codegen_setup()
|
||||
intrinsic_id.cttz = lookup_intrinsic("llvm.cttz");
|
||||
intrinsic_id.exp = lookup_intrinsic("llvm.exp");
|
||||
intrinsic_id.exp2 = lookup_intrinsic("llvm.exp2");
|
||||
intrinsic_id.expect = lookup_intrinsic("llvm.expect");
|
||||
intrinsic_id.expect_with_probability = lookup_intrinsic("llvm.expect.with.probability");
|
||||
intrinsic_id.fabs = lookup_intrinsic("llvm.fabs");
|
||||
intrinsic_id.floor = lookup_intrinsic("llvm.floor");
|
||||
intrinsic_id.fma = lookup_intrinsic("llvm.fma");
|
||||
|
||||
@@ -424,6 +424,7 @@ void llvm_emit_simple_builtin(GenContext *c, BEValue *be_value, Expr *expr, unsi
|
||||
llvm_value_set(be_value, result, expr->type);
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_builtin_args_types3(GenContext *c, BEValue *be_value, Expr *expr, unsigned intrinsic, Type *type1, Type *type2, Type *type3)
|
||||
{
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
@@ -710,6 +711,20 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
case BUILTIN_CTLZ:
|
||||
llvm_emit_int_with_bool_builtin(c, intrinsic_id.ctlz, result_value, expr, false);
|
||||
return;
|
||||
case BUILTIN_EXPECT:
|
||||
llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.expect);
|
||||
return;
|
||||
case BUILTIN_EXPECT_WITH_PROBABILITY:
|
||||
if (active_target.optimization_level == OPTIMIZATION_NONE)
|
||||
{
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
llvm_emit_expr(c, result_value, args[0]);
|
||||
BEValue dummy;
|
||||
llvm_emit_expr(c, &dummy, args[1]);
|
||||
return;
|
||||
}
|
||||
llvm_emit_simple_builtin(c, result_value, expr, intrinsic_id.expect_with_probability);
|
||||
return;
|
||||
case BUILTIN_MAX:
|
||||
llvm_emit_3_variant_builtin(c, result_value, expr, intrinsic_id.smax, intrinsic_id.umax, intrinsic_id.maxnum);
|
||||
return;
|
||||
|
||||
@@ -131,6 +131,8 @@ typedef struct
|
||||
unsigned cttz;
|
||||
unsigned exp;
|
||||
unsigned exp2;
|
||||
unsigned expect;
|
||||
unsigned expect_with_probability;
|
||||
unsigned fabs;
|
||||
unsigned floor;
|
||||
unsigned fma;
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef enum
|
||||
BA_INTLIKE,
|
||||
BA_NUMLIKE,
|
||||
BA_BOOLINTVEC,
|
||||
BA_BOOLINT,
|
||||
BA_INTVEC,
|
||||
BA_FLOATVEC,
|
||||
BA_VEC,
|
||||
@@ -118,6 +119,13 @@ static bool sema_check_builtin_args(Expr **args, BuiltinArg *arg_type, size_t ar
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BA_BOOLINT:
|
||||
if (!type_is_integer_or_bool_kind(type))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected a boolean or integer value.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BA_BOOLINTVEC:
|
||||
|
||||
if (type->type_kind != TYPE_VECTOR || !type_flat_is_boolintlike(type->array.base))
|
||||
@@ -464,6 +472,35 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_VEC }, arg_count)) return false;
|
||||
rtype = args[0]->type;
|
||||
break;
|
||||
case BUILTIN_EXPECT:
|
||||
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_BOOLINT, BA_BOOLINT }, arg_count)) return false;
|
||||
if (!sema_check_builtin_args_match(args, arg_count)) return false;
|
||||
rtype = args[0]->type;
|
||||
break;
|
||||
case BUILTIN_EXPECT_WITH_PROBABILITY:
|
||||
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_BOOLINT, BA_BOOLINT }, 2)) return false;
|
||||
if (!cast_implicit(context, args[2], type_double))
|
||||
{
|
||||
SEMA_ERROR(args[2], "Expected a 'double', but was %s.", type_quoted_error_string(args[2]->type));
|
||||
return false;
|
||||
}
|
||||
if (!expr_is_const(args[2]))
|
||||
{
|
||||
SEMA_ERROR(args[2], "This value must be a constant.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Real r = args[2]->const_expr.fxx.f;
|
||||
if (r < 0 || r > 1)
|
||||
{
|
||||
SEMA_ERROR(args[2], "The probability must be between 0 and 1.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!sema_check_builtin_args_match(args, 2)) return false;
|
||||
rtype = args[0]->type;
|
||||
break;
|
||||
case BUILTIN_CEIL:
|
||||
case BUILTIN_COPYSIGN:
|
||||
case BUILTIN_COS:
|
||||
@@ -699,6 +736,7 @@ static inline int builtin_expected_args(BuiltinFunction func)
|
||||
case BUILTIN_EXACT_MOD:
|
||||
case BUILTIN_EXACT_MUL:
|
||||
case BUILTIN_EXACT_SUB:
|
||||
case BUILTIN_EXPECT:
|
||||
case BUILTIN_MAX:
|
||||
case BUILTIN_MIN:
|
||||
case BUILTIN_POW:
|
||||
@@ -717,6 +755,7 @@ static inline int builtin_expected_args(BuiltinFunction func)
|
||||
case BUILTIN_VECCOMPEQ:
|
||||
case BUILTIN_WASM_MEMORY_GROW:
|
||||
return 2;
|
||||
case BUILTIN_EXPECT_WITH_PROBABILITY:
|
||||
case BUILTIN_FMA:
|
||||
case BUILTIN_FSHL:
|
||||
case BUILTIN_FSHR:
|
||||
|
||||
@@ -200,6 +200,8 @@ void symtab_init(uint32_t capacity)
|
||||
builtin_list[BUILTIN_EXACT_SUB] = KW_DEF("sub");
|
||||
builtin_list[BUILTIN_EXP] = KW_DEF("exp");
|
||||
builtin_list[BUILTIN_EXP2] = KW_DEF("exp2");
|
||||
builtin_list[BUILTIN_EXPECT] = KW_DEF("expect");
|
||||
builtin_list[BUILTIN_EXPECT_WITH_PROBABILITY] = KW_DEF("expect_with_probability");
|
||||
builtin_list[BUILTIN_FLOOR] = KW_DEF("floor");
|
||||
builtin_list[BUILTIN_FMA] = KW_DEF("fma");
|
||||
builtin_list[BUILTIN_FMULADD] = KW_DEF("fmuladd");
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.40"
|
||||
#define COMPILER_VERSION "0.4.41"
|
||||
Reference in New Issue
Block a user