mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Added clz, ctz, popcount, bswap, bitreverse.
This commit is contained in:
41
lib/std/bits.c3
Normal file
41
lib/std/bits.c3
Normal file
@@ -0,0 +1,41 @@
|
||||
module std::bits;
|
||||
|
||||
/**
|
||||
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
|
||||
**/
|
||||
macro popcount(i)
|
||||
{
|
||||
return $$popcount(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
|
||||
**/
|
||||
macro reverse(i)
|
||||
{
|
||||
return $$bitreverse(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
|
||||
**/
|
||||
macro bswap(i) @builtin
|
||||
{
|
||||
return $$bswap(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
|
||||
**/
|
||||
macro ctz(i) @builtin
|
||||
{
|
||||
return $$ctz(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
|
||||
**/
|
||||
macro clz(i) @builtin
|
||||
{
|
||||
return $$clz(i);
|
||||
}
|
||||
@@ -121,6 +121,19 @@ macro bool is_subarray_convertable($Type)
|
||||
$endswitch;
|
||||
}
|
||||
|
||||
macro bool is_intlike($Type)
|
||||
{
|
||||
$switch ($Type.kind):
|
||||
$case SIGNED_INT:
|
||||
$case UNSIGNED_INT:
|
||||
return true;
|
||||
$case VECTOR:
|
||||
return is_intlike($Type.inner);
|
||||
$default:
|
||||
return false;
|
||||
$endswitch;
|
||||
}
|
||||
|
||||
macro bool is_equatable_value(value)
|
||||
{
|
||||
$if ($defined(value.less) || $defined(value.compare_to) || $defined(value.equals)):
|
||||
|
||||
@@ -2101,6 +2101,7 @@ Type *type_from_token(TokenType type);
|
||||
bool type_is_user_defined(Type *type);
|
||||
bool type_is_structurally_equivalent(Type *type1, Type *type);
|
||||
bool type_flat_is_floatlike(Type *type);
|
||||
bool type_flat_is_intlike(Type *type);
|
||||
bool type_may_have_sub_elements(Type *type);
|
||||
const char *type_to_error_string(Type *type);
|
||||
const char *type_quoted_error_string(Type *type);
|
||||
|
||||
@@ -758,6 +758,11 @@ typedef enum
|
||||
BUILTIN_EXP,
|
||||
BUILTIN_FABS,
|
||||
BUILTIN_FMA,
|
||||
BUILTIN_CTPOP,
|
||||
BUILTIN_CTLZ,
|
||||
BUILTIN_CTTZ,
|
||||
BUILTIN_BITREVERSE,
|
||||
BUILTIN_BSWAP,
|
||||
BUILTIN_VOLATILE_LOAD,
|
||||
BUILTIN_VOLATILE_STORE,
|
||||
BUILTIN_MEMCOPY,
|
||||
|
||||
@@ -4099,6 +4099,11 @@ static void llvm_emit_intrinsic_expr(GenContext *c, unsigned intrinsic, BEValue
|
||||
llvm_value_rvalue(c, be_value);
|
||||
arg_results[i] = be_value->value;
|
||||
}
|
||||
if (intrinsic == intrinsic_id.ctlz || intrinsic == intrinsic_id.cttz)
|
||||
{
|
||||
arg_results[1] = llvm_get_zero_raw(c->bool_type);
|
||||
arguments++;
|
||||
}
|
||||
LLVMTypeRef call_type[3];
|
||||
int call_args = 0;
|
||||
if (expr->type != type_void)
|
||||
@@ -4321,6 +4326,16 @@ unsigned llvm_get_intrinsic(BuiltinFunction func)
|
||||
return intrinsic_id.fabs;
|
||||
case BUILTIN_FMA:
|
||||
return intrinsic_id.fma;
|
||||
case BUILTIN_BITREVERSE:
|
||||
return intrinsic_id.bitreverse;
|
||||
case BUILTIN_BSWAP:
|
||||
return intrinsic_id.bswap;
|
||||
case BUILTIN_CTLZ:
|
||||
return intrinsic_id.ctlz;
|
||||
case BUILTIN_CTTZ:
|
||||
return intrinsic_id.cttz;
|
||||
case BUILTIN_CTPOP:
|
||||
return intrinsic_id.ctpop;
|
||||
case BUILTIN_LOG2:
|
||||
return intrinsic_id.log2;
|
||||
case BUILTIN_POW:
|
||||
|
||||
@@ -2486,6 +2486,11 @@ static inline unsigned builtin_expected_args(BuiltinFunction func)
|
||||
case BUILTIN_LOG10:
|
||||
case BUILTIN_FABS:
|
||||
case BUILTIN_VOLATILE_LOAD:
|
||||
case BUILTIN_CTPOP:
|
||||
case BUILTIN_CTTZ:
|
||||
case BUILTIN_CTLZ:
|
||||
case BUILTIN_BSWAP:
|
||||
case BUILTIN_BITREVERSE:
|
||||
return 1;
|
||||
case BUILTIN_POW:
|
||||
case BUILTIN_MAX:
|
||||
@@ -2511,6 +2516,7 @@ typedef enum
|
||||
BA_BOOL,
|
||||
BA_CHAR,
|
||||
BA_FLOATLIKE,
|
||||
BA_INTLIKE,
|
||||
} BuiltinArg;
|
||||
|
||||
static bool sema_check_builtin_args_match(Expr **args, size_t arg_len)
|
||||
@@ -2577,7 +2583,14 @@ static bool sema_check_builtin_args(Expr **args, BuiltinArg *arg_type, size_t ar
|
||||
case BA_FLOATLIKE:
|
||||
if (!type_flat_is_floatlike(type))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected a floating point or floating point array.");
|
||||
SEMA_ERROR(args[i], "Expected a floating point or floating point vector.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BA_INTLIKE:
|
||||
if (!type_flat_is_intlike(type))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected an int or int vector.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -2676,6 +2689,16 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex
|
||||
case BUILTIN_STACKTRACE:
|
||||
rtype = type_voidptr;
|
||||
break;
|
||||
case BUILTIN_CTPOP:
|
||||
case BUILTIN_CTTZ:
|
||||
case BUILTIN_CTLZ:
|
||||
case BUILTIN_BITREVERSE:
|
||||
case BUILTIN_BSWAP:
|
||||
if (!sema_check_builtin_args(args,
|
||||
(BuiltinArg[]) { BA_INTLIKE },
|
||||
arg_count)) return false;
|
||||
rtype = args[0]->type;
|
||||
break;
|
||||
case BUILTIN_CEIL:
|
||||
case BUILTIN_TRUNC:
|
||||
case BUILTIN_SQRT:
|
||||
@@ -2691,6 +2714,7 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex
|
||||
arg_count)) return false;
|
||||
rtype = args[0]->type;
|
||||
break;
|
||||
|
||||
case BUILTIN_POW:
|
||||
case BUILTIN_MAX:
|
||||
case BUILTIN_MIN:
|
||||
|
||||
@@ -180,6 +180,11 @@ void symtab_init(uint32_t capacity)
|
||||
builtin_list[BUILTIN_SYSCLOCK] = KW_DEF("sysclock");
|
||||
builtin_list[BUILTIN_UNREACHABLE] = KW_DEF("unreachable");
|
||||
builtin_list[BUILTIN_STACKTRACE] = KW_DEF("stacktrace");
|
||||
builtin_list[BUILTIN_BSWAP] = KW_DEF("bswap");
|
||||
builtin_list[BUILTIN_BITREVERSE] = KW_DEF("bitreverse");
|
||||
builtin_list[BUILTIN_CTLZ] = KW_DEF("clz");
|
||||
builtin_list[BUILTIN_CTTZ] = KW_DEF("ctz");
|
||||
builtin_list[BUILTIN_CTPOP] = KW_DEF("popcount");
|
||||
builtin_list[BUILTIN_CEIL] = KW_DEF("ceil");
|
||||
builtin_list[BUILTIN_TRUNC] = KW_DEF("trunc");
|
||||
builtin_list[BUILTIN_SIN] = KW_DEF("sin");
|
||||
|
||||
@@ -328,6 +328,14 @@ bool type_flat_is_floatlike(Type *type)
|
||||
return kind >= TYPE_FLOAT_FIRST && kind <= TYPE_FLOAT_LAST;
|
||||
}
|
||||
|
||||
bool type_flat_is_intlike(Type *type)
|
||||
{
|
||||
type = type_flatten(type);
|
||||
if (type->type_kind == TYPE_VECTOR) type = type->array.base;
|
||||
TypeKind kind = type->type_kind;
|
||||
return kind >= TYPE_INTEGER_FIRST && kind <= TYPE_INTEGER_LAST;
|
||||
}
|
||||
|
||||
|
||||
bool type_is_int128(Type *type)
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.18"
|
||||
#define COMPILER_VERSION "0.3.19"
|
||||
Reference in New Issue
Block a user