Added clz, ctz, popcount, bswap, bitreverse.

This commit is contained in:
Christoffer Lerno
2022-08-16 21:18:14 +02:00
parent 15586b3076
commit ae51214c47
9 changed files with 114 additions and 2 deletions

41
lib/std/bits.c3 Normal file
View 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);
}

View File

@@ -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)):

View File

@@ -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);

View File

@@ -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,

View File

@@ -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:

View File

@@ -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:

View File

@@ -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");

View File

@@ -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)
{

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.18"
#define COMPILER_VERSION "0.3.19"