mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Added vector dot functions. Comparison now yields bool vector. Cast between vector types.
This commit is contained in:
committed by
Christoffer Lerno
parent
8008fb2c18
commit
c339261d1e
@@ -2308,6 +2308,7 @@ 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_flat_is_boolintlike(Type *type);
|
||||
bool type_flat_is_numlike(Type *type);
|
||||
bool type_may_have_sub_elements(Type *type);
|
||||
bool type_may_have_method(Type *type);
|
||||
@@ -2327,6 +2328,7 @@ INLINE bool type_is_substruct(Type *type);
|
||||
INLINE Type *type_flatten_for_bitstruct(Type *type);
|
||||
INLINE const char *type_invalid_storage_type_name(Type *type);
|
||||
INLINE bool type_is_float(Type *type);
|
||||
INLINE bool type_is_floatlike(Type *type);
|
||||
INLINE bool type_is_optional(Type *type);
|
||||
INLINE bool type_is_optional_type(Type *type);
|
||||
INLINE bool type_is_optional_any(Type *type);
|
||||
@@ -2577,6 +2579,14 @@ INLINE bool type_is_float(Type *type)
|
||||
return kind >= TYPE_FLOAT_FIRST && kind <= TYPE_FLOAT_LAST;
|
||||
}
|
||||
|
||||
INLINE bool type_is_floatlike(Type *type)
|
||||
{
|
||||
type = type->canonical;
|
||||
TypeKind kind = type->type_kind;
|
||||
if (kind == TYPE_VECTOR && type_is_float(type->array.base)) return true;
|
||||
return kind >= TYPE_FLOAT_FIRST && kind <= TYPE_FLOAT_LAST;
|
||||
}
|
||||
|
||||
INLINE const char *type_invalid_storage_type_name(Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
@@ -2638,9 +2648,9 @@ INLINE Type *type_new(TypeKind kind, const char *name)
|
||||
|
||||
INLINE bool type_convert_will_trunc(Type *destination, Type *source)
|
||||
{
|
||||
assert(type_is_builtin(destination->canonical->type_kind));
|
||||
assert(type_is_builtin(source->canonical->type_kind));
|
||||
return (unsigned)destination->canonical->builtin.bitsize < (unsigned)source->canonical->builtin.bitsize;
|
||||
assert(type_flat_is_vector(destination) || type_is_builtin(destination->canonical->type_kind));
|
||||
assert(type_flat_is_vector(destination) || type_is_builtin(source->canonical->type_kind));
|
||||
return type_size(destination) < type_size(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -2786,6 +2796,17 @@ INLINE bool type_flat_is_vector(Type *type)
|
||||
return type_flatten(type)->type_kind == TYPE_VECTOR;
|
||||
}
|
||||
|
||||
INLINE bool type_kind_is_any_vector(TypeKind kind)
|
||||
{
|
||||
return kind == TYPE_VECTOR || kind == TYPE_INFERRED_VECTOR || kind == TYPE_SCALED_VECTOR;
|
||||
}
|
||||
|
||||
INLINE bool type_flat_is_bool_vector(Type *type)
|
||||
{
|
||||
Type *flat = type_flatten(type);
|
||||
return flat->type_kind == TYPE_VECTOR && type_flatten(flat->array.base) == type_bool;
|
||||
}
|
||||
|
||||
INLINE bool type_is_union_or_strukt(Type *type)
|
||||
{
|
||||
DECL_TYPE_KIND_REAL(kind, type);
|
||||
|
||||
@@ -95,6 +95,7 @@ typedef enum
|
||||
CAST_PTRBOOL,
|
||||
CAST_BOOLINT,
|
||||
CAST_BOOLFP,
|
||||
CAST_BOOLVECINT,
|
||||
CAST_BOOLBOOL,
|
||||
CAST_FPBOOL,
|
||||
CAST_INTBOOL,
|
||||
|
||||
@@ -369,6 +369,7 @@ static inline bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_
|
||||
case CAST_STST:
|
||||
case CAST_VECARR:
|
||||
case CAST_ARRVEC:
|
||||
case CAST_BOOLVECINT:
|
||||
if (eval_kind != CONSTANT_EVAL_NO_SIDE_EFFECTS) return false;
|
||||
return exprid_is_constant_eval(expr->cast_expr.expr, eval_kind);
|
||||
case CAST_XIPTR:
|
||||
|
||||
@@ -771,15 +771,9 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
||||
LLVMSetLinkage(value, LLVMLinkerPrivateLinkage);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value)
|
||||
{
|
||||
value->value = llvm_value;
|
||||
@@ -788,6 +782,14 @@ void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value)
|
||||
value->type = type_bool;
|
||||
}
|
||||
|
||||
void llvm_value_set_bool_vector(BEValue *value, LLVMValueRef llvm_value, Type *type)
|
||||
{
|
||||
value->value = llvm_value;
|
||||
value->alignment = type_abi_alignment(type);
|
||||
value->kind = BE_BOOLVECTOR;
|
||||
value->type = type;
|
||||
}
|
||||
|
||||
void llvm_value_set_int(GenContext *c, BEValue *value, Type *type, uint64_t i)
|
||||
{
|
||||
llvm_value_set(value, llvm_const_int(c, type, i), type);
|
||||
|
||||
@@ -481,7 +481,7 @@ static void llvm_emit_veccomp(GenContext *c, BEValue *value, Expr *expr, Builtin
|
||||
}
|
||||
else
|
||||
{
|
||||
bool is_signed = type_is_signed(value->type);
|
||||
bool is_signed = type_is_signed(args[0]->type);
|
||||
switch (fn)
|
||||
{
|
||||
case BUILTIN_VECCOMPEQ:
|
||||
@@ -508,9 +508,7 @@ static void llvm_emit_veccomp(GenContext *c, BEValue *value, Expr *expr, Builtin
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
Type *result_type = type_get_vector_bool(value->type);
|
||||
res = LLVMBuildSExt(c->builder, res, llvm_get_type(c, result_type), "");
|
||||
llvm_value_set(value, res, result_type);
|
||||
llvm_value_set_bool_vector(value, res, expr->type);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@@ -1164,6 +1164,15 @@ void llvm_emit_array_to_vector_cast(GenContext *c, BEValue *value, Type *to_type
|
||||
llvm_value_set(value, vector, to_type);
|
||||
}
|
||||
|
||||
void llvm_emit_bool_to_intvec_cast(GenContext *c, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
llvm_value_rvalue(c, value);
|
||||
LLVMTypeRef type = llvm_get_type(c, to_type);
|
||||
LLVMValueRef res = LLVMBuildSExt(c->builder, value->value, type, "");
|
||||
llvm_value_set(value, res, to_type);
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
Type *to_type_original = to_type;
|
||||
@@ -1172,6 +1181,9 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
|
||||
|
||||
switch (cast_kind)
|
||||
{
|
||||
case CAST_BOOLVECINT:
|
||||
llvm_emit_bool_to_intvec_cast(c, value, to_type, from_type);
|
||||
return;
|
||||
case CAST_ARRVEC:
|
||||
llvm_emit_array_to_vector_cast(c, value, to_type, from_type);
|
||||
return;
|
||||
@@ -1304,7 +1316,7 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
|
||||
case CAST_INTBOOL:
|
||||
llvm_value_rvalue(c, value);
|
||||
value->value = LLVMBuildICmp(c->builder, LLVMIntNE, value->value, llvm_get_zero(c, from_type), "intbool");
|
||||
value->kind = BE_BOOLEAN;
|
||||
value->kind = type_kind_is_any_vector(value->type->type_kind) ? BE_BOOLVECTOR : BE_BOOLEAN;
|
||||
break;
|
||||
case CAST_FPFP:
|
||||
llvm_value_rvalue(c, value);
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef enum
|
||||
BE_ADDRESS,
|
||||
BE_ADDRESS_FAILABLE,
|
||||
BE_BOOLEAN,
|
||||
BE_BOOLVECTOR,
|
||||
} BackendValueKind;
|
||||
|
||||
typedef struct
|
||||
@@ -258,6 +259,7 @@ static inline bool llvm_value_is_bool(BEValue *value) { return value->kind == BE
|
||||
bool llvm_value_is_const(BEValue *value);
|
||||
void llvm_value_rvalue(GenContext *context, BEValue *value);
|
||||
void llvm_value_set_bool(BEValue *value, LLVMValueRef llvm_value);
|
||||
void llvm_value_set_bool_vector(BEValue *value, LLVMValueRef llvm_value, Type *type);
|
||||
void llvm_value_set(BEValue *value, LLVMValueRef llvm_value, Type *type);
|
||||
void llvm_value_set_int(GenContext *c, BEValue *value, Type *type, uint64_t i);
|
||||
void llvm_value_set_address(BEValue *value, LLVMValueRef llvm_value, Type *type, AlignSize alignment);
|
||||
|
||||
@@ -102,6 +102,11 @@ INLINE LLVMValueRef llvm_emit_lshr(GenContext *c, LLVMValueRef value, LLVMValueR
|
||||
|
||||
INLINE LLVMValueRef llvm_emit_trunc_bool(GenContext *c, LLVMValueRef value)
|
||||
{
|
||||
LLVMTypeRef type = LLVMTypeOf(value);
|
||||
if (LLVMGetTypeKind(type) == LLVMVectorTypeKind)
|
||||
{
|
||||
return LLVMBuildTrunc(c->builder, value, LLVMVectorType(c->bool_type, LLVMGetVectorSize(type)), "");
|
||||
}
|
||||
return LLVMBuildTrunc(c->builder, value, c->bool_type, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ LLVMValueRef llvm_store_to_ptr_aligned(GenContext *c, LLVMValueRef destination,
|
||||
}
|
||||
switch (value->kind)
|
||||
{
|
||||
case BE_BOOLVECTOR:
|
||||
value->value = LLVMBuildSExt(c->builder, value->value, llvm_get_type(c, value->type), "");
|
||||
value->kind = BE_VALUE;
|
||||
return llvm_store_to_ptr_raw_aligned(c, destination, value->value, alignment);
|
||||
case BE_BOOLEAN:
|
||||
value->value = LLVMBuildZExt(c->builder, value->value, c->byte_type, "");
|
||||
value->kind = BE_VALUE;
|
||||
@@ -85,6 +89,7 @@ LLVMValueRef llvm_load_value(GenContext *c, BEValue *value)
|
||||
llvm_value_fold_optional(c, value);
|
||||
switch (value->kind)
|
||||
{
|
||||
case BE_BOOLVECTOR:
|
||||
case BE_BOOLEAN:
|
||||
case BE_VALUE:
|
||||
return value->value;
|
||||
@@ -99,6 +104,10 @@ LLVMValueRef llvm_load_value(GenContext *c, BEValue *value)
|
||||
LLVMValueRef llvm_load_value_store(GenContext *c, BEValue *value)
|
||||
{
|
||||
LLVMValueRef val = llvm_load_value(c, value);
|
||||
if (value->kind == BE_BOOLVECTOR)
|
||||
{
|
||||
return LLVMBuildSExt(c->builder, val, llvm_get_type(c, type_get_vector_bool(value->type)), "");
|
||||
}
|
||||
if (value->kind != BE_BOOLEAN) return val;
|
||||
return LLVMBuildZExt(c->builder, val, c->byte_type, "");
|
||||
}
|
||||
|
||||
@@ -50,9 +50,14 @@ void llvm_value_rvalue(GenContext *c, BEValue *value)
|
||||
{
|
||||
if (value->type->type_kind == TYPE_BOOL && value->kind != BE_BOOLEAN)
|
||||
{
|
||||
value->value = LLVMBuildTrunc(c->builder, value->value, c->bool_type, "");
|
||||
value->value = llvm_emit_trunc_bool(c, value->value);
|
||||
value->kind = BE_BOOLEAN;
|
||||
}
|
||||
if (type_flat_is_bool_vector(value->type) && value->kind != BE_BOOLVECTOR)
|
||||
{
|
||||
value->value = llvm_emit_trunc_bool(c, value->value);
|
||||
value->kind = BE_BOOLVECTOR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
llvm_value_fold_optional(c, value);
|
||||
@@ -67,6 +72,12 @@ void llvm_value_rvalue(GenContext *c, BEValue *value)
|
||||
value->kind = BE_BOOLEAN;
|
||||
return;
|
||||
}
|
||||
if (type_flat_is_bool_vector(value->type))
|
||||
{
|
||||
value->value = llvm_emit_trunc_bool(c, value->value);
|
||||
value->kind = BE_BOOLVECTOR;
|
||||
return;
|
||||
}
|
||||
value->kind = BE_VALUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef enum
|
||||
BA_FLOAT,
|
||||
BA_INTLIKE,
|
||||
BA_NUMLIKE,
|
||||
BA_BOOLINTVEC,
|
||||
BA_INTVEC,
|
||||
BA_FLOATVEC,
|
||||
BA_VEC,
|
||||
@@ -109,12 +110,21 @@ static bool sema_check_builtin_args(Expr **args, BuiltinArg *arg_type, size_t ar
|
||||
}
|
||||
break;
|
||||
case BA_INTVEC:
|
||||
|
||||
if (type->type_kind != TYPE_VECTOR || !type_flat_is_intlike(type->array.base))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected an integer vector.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BA_BOOLINTVEC:
|
||||
|
||||
if (type->type_kind != TYPE_VECTOR || !type_flat_is_boolintlike(type->array.base))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected a boolean or integer vector.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BA_FLOATVEC:
|
||||
if (type->type_kind != TYPE_VECTOR || !type_flat_is_floatlike(type->array.base))
|
||||
{
|
||||
@@ -326,7 +336,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
(BuiltinArg[]) { BA_VEC, BA_VEC },
|
||||
arg_count)) return false;
|
||||
if (!sema_check_builtin_args_match(args, 2)) return false;
|
||||
rtype = type_get_vector_bool(args[0]->type);
|
||||
rtype = type_get_vector(type_bool, type_flatten(args[0]->type)->array.len);
|
||||
break;
|
||||
case BUILTIN_OVERFLOW_ADD:
|
||||
case BUILTIN_OVERFLOW_MUL:
|
||||
@@ -492,7 +502,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
case BUILTIN_REDUCE_XOR:
|
||||
case BUILTIN_REDUCE_MUL:
|
||||
if (!sema_check_builtin_args(args,
|
||||
(BuiltinArg[]) { BA_INTVEC },
|
||||
(BuiltinArg[]) { BA_BOOLINTVEC },
|
||||
arg_count)) return false;
|
||||
rtype = args[0]->type->canonical->array.base;
|
||||
break;
|
||||
|
||||
@@ -14,6 +14,7 @@ static Expr *recursive_may_narrow_int(Expr *expr, Type *type);
|
||||
static void recursively_rewrite_untyped_list(Expr *expr, Expr **list);
|
||||
static inline bool cast_may_implicit_ptr(Type *from_pointee, Type *to_pointee);
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit);
|
||||
static inline bool cast_may_vector(Type *from, Type *to, bool is_explicit, bool is_const, CastOption option);
|
||||
|
||||
static inline bool insert_cast(Expr *expr, CastKind kind, Type *type)
|
||||
{
|
||||
@@ -468,6 +469,10 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
|
||||
// 2. Same underlying type, always ok
|
||||
if (from_type == to_type) return true;
|
||||
|
||||
if (type_kind_is_any_vector(to_type->type_kind) && type_kind_is_any_vector(from_type->type_kind))
|
||||
{
|
||||
return cast_may_vector(from_type, to_type, true, is_const, CAST_OPTION_NONE);
|
||||
}
|
||||
if (type_is_any_arraylike(to_type) && type_is_any_arraylike(from_type))
|
||||
{
|
||||
return cast_may_array(from_type, to_type, true);
|
||||
@@ -568,6 +573,24 @@ bool type_may_convert_to_anyerr(Type *type)
|
||||
return type->failable->canonical == type_void;
|
||||
}
|
||||
|
||||
static inline bool cast_may_vector(Type *from, Type *to, bool is_explicit, bool is_const, CastOption option)
|
||||
{
|
||||
if (to->array.len != from->array.len) return false;
|
||||
Type *to_inner = to->array.base;
|
||||
Type *from_inner = from->array.base;
|
||||
if (is_explicit)
|
||||
{
|
||||
to_inner = type_flatten(to_inner);
|
||||
from_inner = type_flatten(from_inner);
|
||||
}
|
||||
if (to_inner == from_inner) return true;
|
||||
if (from_inner == type_bool && type_is_integer(to_inner)) return true;
|
||||
if (is_explicit)
|
||||
{
|
||||
return cast_may_explicit(from_inner, to_inner, true, is_const);
|
||||
}
|
||||
return cast_may_implicit(from_inner, to_inner, option);
|
||||
}
|
||||
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit)
|
||||
{
|
||||
@@ -807,6 +830,11 @@ bool cast_may_implicit(Type *from_type, Type *to_type, CastOption option)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type_kind_is_any_vector(to->type_kind) && to->type_kind == from->type_kind)
|
||||
{
|
||||
return cast_may_vector(from, to, false, false, option);
|
||||
}
|
||||
|
||||
if (type_is_any_arraylike(to) && type_is_any_arraylike(from))
|
||||
{
|
||||
return cast_may_array(from, to, false);
|
||||
@@ -1439,6 +1467,101 @@ static bool vec_to_arr(Expr *expr, Type *to_type)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vec_const_init_to_type(ConstInitializer *initializer, Type *to_type)
|
||||
{
|
||||
switch (initializer->kind)
|
||||
{
|
||||
case CONST_INIT_ARRAY:
|
||||
{
|
||||
Type *element_type = type_flatten(to_type)->array.base;
|
||||
FOREACH_BEGIN(ConstInitializer *element, initializer->init_array.elements)
|
||||
vec_const_init_to_type(element, element_type);
|
||||
FOREACH_END();
|
||||
break;
|
||||
}
|
||||
case CONST_INIT_ARRAY_FULL:
|
||||
{
|
||||
Type *element_type = type_flatten(to_type)->array.base;
|
||||
FOREACH_BEGIN(ConstInitializer *element, initializer->init_array_full)
|
||||
vec_const_init_to_type(element, element_type);
|
||||
FOREACH_END();
|
||||
break;
|
||||
}
|
||||
case CONST_INIT_VALUE:
|
||||
{
|
||||
Type *to_flat = type_flatten(to_type);
|
||||
bool is_neg_conversion = to_flat && type_flatten(initializer->type) == type_bool;
|
||||
if (is_neg_conversion)
|
||||
{
|
||||
bool is_true = initializer->init_value->const_expr.b;
|
||||
initializer->init_value->const_expr.ixx = (Int)
|
||||
{ .i = is_true ? (Int128) { UINT64_MAX, UINT64_MAX } : (Int128) { 0, 0 },
|
||||
.type = to_flat->type_kind };
|
||||
initializer->init_value->type = to_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
cast(initializer->init_value, to_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONST_INIT_ZERO:
|
||||
break;
|
||||
case CONST_INIT_UNION:
|
||||
case CONST_INIT_STRUCT:
|
||||
UNREACHABLE
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
vec_const_init_to_type(initializer->init_array_value.element, to_type);
|
||||
break;
|
||||
}
|
||||
initializer->type = to_type;
|
||||
}
|
||||
static bool vec_to_vec(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (expr->expr_kind != EXPR_CONST)
|
||||
{
|
||||
Type *from_type = type_flatten(expr->type);
|
||||
Type *from_element = from_type->array.base;
|
||||
to_type = type_flatten(to_type);
|
||||
Type *to_element = to_type->array.base;
|
||||
if (type_is_float(from_element))
|
||||
{
|
||||
if (to_element == type_bool) return insert_cast(expr, CAST_FPBOOL, to_type);
|
||||
if (type_is_unsigned(to_element)) return insert_cast(expr, CAST_FPUI, to_type);
|
||||
if (type_is_signed(to_element)) return insert_cast(expr, CAST_FPSI, to_type);
|
||||
if (type_is_float(to_element)) return insert_cast(expr, CAST_FPFP, to_type);
|
||||
UNREACHABLE;
|
||||
}
|
||||
if (from_element == type_bool)
|
||||
{
|
||||
if (type_is_integer(to_element)) return insert_cast(expr, CAST_BOOLVECINT, to_type);
|
||||
if (type_is_float(to_element)) return insert_cast(expr, CAST_FPFP, to_type);
|
||||
UNREACHABLE;
|
||||
}
|
||||
if (type_is_signed(from_element))
|
||||
{
|
||||
if (to_element == type_bool) return insert_cast(expr, CAST_INTBOOL, to_type);
|
||||
if (type_is_unsigned(to_element)) return insert_cast(expr, CAST_SIUI, to_type);
|
||||
if (type_is_signed(to_element)) return insert_cast(expr, CAST_SISI, to_type);
|
||||
if (type_is_float(to_element)) return insert_cast(expr, CAST_SIFP, to_type);
|
||||
UNREACHABLE
|
||||
}
|
||||
assert(type_is_unsigned(from_element));
|
||||
if (to_element == type_bool) return insert_cast(expr, CAST_INTBOOL, to_type);
|
||||
if (type_is_unsigned(to_element)) return insert_cast(expr, CAST_UIUI, to_type);
|
||||
if (type_is_signed(to_element)) return insert_cast(expr, CAST_UISI, to_type);
|
||||
if (type_is_float(to_element)) return insert_cast(expr, CAST_UIFP, to_type);
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
assert(expr->const_expr.const_kind == CONST_INITIALIZER);
|
||||
|
||||
ConstInitializer *list = expr->const_expr.initializer;
|
||||
vec_const_init_to_type(list, to_type);
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool err_to_anyerr(Expr *expr, Type *to_type)
|
||||
{
|
||||
expr->type = to_type;
|
||||
@@ -1587,6 +1710,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
break;
|
||||
case TYPE_VECTOR:
|
||||
if (to->type_kind == TYPE_ARRAY) return vec_to_arr(expr, to_type);
|
||||
if (to->type_kind == TYPE_VECTOR) return vec_to_vec(expr, to_type);
|
||||
break;
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
@@ -351,6 +351,14 @@ bool type_flat_is_intlike(Type *type)
|
||||
return kind >= TYPE_INTEGER_FIRST && kind <= TYPE_INTEGER_LAST;
|
||||
}
|
||||
|
||||
bool type_flat_is_boolintlike(Type *type)
|
||||
{
|
||||
type = type_flatten(type);
|
||||
if (type->type_kind == TYPE_VECTOR) type = type->array.base;
|
||||
TypeKind kind = type->type_kind;
|
||||
return kind == TYPE_BOOL || (kind >= TYPE_INTEGER_FIRST && kind <= TYPE_INTEGER_LAST);
|
||||
}
|
||||
|
||||
|
||||
bool type_is_int128(Type *type)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user