mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
- Regression vector ABI: npot vectors would load incorrectly from pointers and other things. #2576
240 lines
6.4 KiB
C
240 lines
6.4 KiB
C
#include "compiler_internal.h"
|
|
|
|
typedef enum IntrospectIndex
|
|
{
|
|
INTROSPECT_INDEX_KIND = 0,
|
|
INTROSPECT_INDEX_PARENTOF = 1,
|
|
INTROSPECT_INDEX_DTABLE = 2,
|
|
INTROSPECT_INDEX_SIZEOF = 3,
|
|
INTROSPECT_INDEX_INNER = 4,
|
|
INTROSPECT_INDEX_LEN = 5,
|
|
INTROSPECT_INDEX_ADDITIONAL = 6,
|
|
INTROSPECT_INDEX_TOTAL,
|
|
} IntrospectIndex;
|
|
|
|
bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements);
|
|
static inline bool abi_type_is_type(AbiType type);
|
|
|
|
static inline bool abi_type_is_valid(AbiType type);
|
|
|
|
|
|
static inline LoweredType *type_lowering(Type *type)
|
|
{
|
|
while (1)
|
|
{
|
|
type = type->canonical;
|
|
switch (type->type_kind)
|
|
{
|
|
case TYPE_ALIAS:
|
|
UNREACHABLE
|
|
case TYPE_OPTIONAL:
|
|
type = type->optional;
|
|
continue;
|
|
case TYPE_TYPEDEF:
|
|
type = type->decl->distinct->type;
|
|
continue;
|
|
case TYPE_CONST_ENUM:
|
|
case TYPE_ENUM:
|
|
type = enum_inner_type(type);
|
|
continue;
|
|
case TYPE_FUNC_PTR:
|
|
{
|
|
Type *raw_func = type->pointer;
|
|
if (raw_func->function.prototype && raw_func->function.prototype->raw_type == raw_func) return type;
|
|
FunctionPrototype *proto = type_get_resolved_prototype(raw_func);
|
|
return type_get_func_ptr(proto->raw_type);
|
|
}
|
|
case TYPE_INTERFACE:
|
|
return type_any;
|
|
case TYPE_ANYFAULT:
|
|
case TYPE_TYPEID:
|
|
return type_iptr->canonical;
|
|
case TYPE_BITSTRUCT:
|
|
type = type->decl->strukt.container_type->type;
|
|
continue;
|
|
case TYPE_WILDCARD:
|
|
type = type_void;
|
|
break;
|
|
case TYPE_POINTER:
|
|
{
|
|
Type *pointer = type->pointer;
|
|
Type *flat = type_lowering(pointer);
|
|
if (flat == pointer) return type;
|
|
return type_get_ptr(flat);
|
|
}
|
|
case TYPE_SLICE:
|
|
case TYPE_ARRAY:
|
|
case TYPE_VECTOR:
|
|
case TYPE_SIMD_VECTOR:
|
|
case TYPE_FLEXIBLE_ARRAY:
|
|
{
|
|
Type *arr_type = type->array.base;
|
|
Type *flat = type_lowering(arr_type);
|
|
if (flat == arr_type) return type;
|
|
switch (type->type_kind)
|
|
{
|
|
case TYPE_SLICE:
|
|
return type_get_slice(flat);
|
|
case TYPE_ARRAY:
|
|
return type_get_array(flat, type->array.len);
|
|
case VECTORS:
|
|
return type_get_vector_from_vector(flat, type);
|
|
case TYPE_FLEXIBLE_ARRAY:
|
|
return type_get_flexible_array(flat);
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
}
|
|
default:
|
|
return type;
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline LoweredType *type_lowering_abi(Type *type)
|
|
{
|
|
while (1)
|
|
{
|
|
type = type->canonical;
|
|
switch (type->type_kind)
|
|
{
|
|
case TYPE_ALIAS:
|
|
UNREACHABLE
|
|
case TYPE_OPTIONAL:
|
|
type = type->optional;
|
|
continue;
|
|
case TYPE_TYPEDEF:
|
|
type = type->decl->distinct->type;
|
|
continue;
|
|
case TYPE_CONST_ENUM:
|
|
case TYPE_ENUM:
|
|
type = enum_inner_type(type);
|
|
continue;
|
|
case TYPE_FUNC_PTR:
|
|
{
|
|
Type *raw_func = type->pointer;
|
|
if (raw_func->function.prototype && raw_func->function.prototype->raw_type == raw_func) return type;
|
|
FunctionPrototype *proto = type_get_resolved_prototype(raw_func);
|
|
return type_get_func_ptr(proto->raw_type);
|
|
}
|
|
case TYPE_INTERFACE:
|
|
return type_any;
|
|
case TYPE_ANYFAULT:
|
|
case TYPE_TYPEID:
|
|
return type_iptr->canonical;
|
|
case TYPE_BITSTRUCT:
|
|
type = type->decl->strukt.container_type->type;
|
|
continue;
|
|
case TYPE_WILDCARD:
|
|
type = type_void;
|
|
break;
|
|
case TYPE_POINTER:
|
|
{
|
|
Type *pointer = type->pointer;
|
|
Type *flat = type_lowering_abi(pointer);
|
|
if (flat == pointer) return type;
|
|
return type_get_ptr(flat);
|
|
}
|
|
case TYPE_SLICE:
|
|
case TYPE_ARRAY:
|
|
case TYPE_VECTOR:
|
|
case TYPE_FLEXIBLE_ARRAY:
|
|
case TYPE_SIMD_VECTOR:
|
|
{
|
|
Type *flat = type_lowering_abi(type->array.base);
|
|
switch (type->type_kind)
|
|
{
|
|
case TYPE_SLICE:
|
|
return type_get_slice(flat);
|
|
case TYPE_SIMD_VECTOR:
|
|
return type_get_vector(flat, TYPE_SIMD_VECTOR, type->array.len);
|
|
case TYPE_ARRAY:
|
|
case TYPE_VECTOR:
|
|
return type_get_array(flat, type->array.len);
|
|
case TYPE_FLEXIBLE_ARRAY:
|
|
return type_get_flexible_array(flat);
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
}
|
|
default:
|
|
return type;
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline bool abi_type_match(AbiType type, Type *other_type)
|
|
{
|
|
other_type = other_type->canonical;
|
|
if (type.abi_type & 0x01)
|
|
{
|
|
switch (type.abi_type)
|
|
{
|
|
case ABI_TYPE_INT_24:
|
|
case ABI_TYPE_INT_40:
|
|
case ABI_TYPE_INT_48:
|
|
case ABI_TYPE_INT_56:
|
|
return false;
|
|
case ABI_TYPE_INT_VEC_2:
|
|
return other_type == type_get_vector(type_uint, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_INT_VEC_4:
|
|
return other_type == type_get_vector(type_uint, TYPE_SIMD_VECTOR, 4);
|
|
case ABI_TYPE_FLOAT_VEC_2:
|
|
return other_type == type_get_vector(type_float, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_FLOAT_VEC_4:
|
|
return other_type == type_get_vector(type_float, TYPE_SIMD_VECTOR, 4);
|
|
case ABI_TYPE_FLOAT16_VEC_2:
|
|
return other_type == type_get_vector(type_float16, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_FLOAT16_VEC_4:
|
|
return other_type == type_get_vector(type_float16, TYPE_SIMD_VECTOR, 4);
|
|
case ABI_TYPE_BFLOAT16_VEC_2:
|
|
return other_type == type_get_vector(type_bfloat, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_BFLOAT16_VEC_4:
|
|
return other_type == type_get_vector(type_bfloat, TYPE_SIMD_VECTOR, 4);
|
|
case ABI_TYPE_LONG_VEC_2:
|
|
return other_type == type_get_vector(type_ulong, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_DOUBLE_VEC_2:
|
|
return other_type == type_get_vector(type_double, TYPE_SIMD_VECTOR, 2);
|
|
case ABI_TYPE_DOUBLE_VEC_4:
|
|
return other_type == type_get_vector(type_double, TYPE_SIMD_VECTOR, 4);
|
|
case ABI_TYPE_DOUBLE_VEC_8:
|
|
return other_type == type_get_vector(type_double, TYPE_SIMD_VECTOR, 8);
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
return type.type == other_type->canonical;
|
|
}
|
|
static inline bool abi_type_is_type(AbiType type)
|
|
{
|
|
return !(type.abi_type & 0x01);
|
|
}
|
|
|
|
static inline bool abi_type_is_valid(AbiType type)
|
|
{
|
|
return type.abi_type != 0;
|
|
}
|
|
|
|
|
|
static inline bool expr_is_vector_index_or_swizzle(Expr *expr)
|
|
{
|
|
return (expr->expr_kind == EXPR_SUBSCRIPT && type_kind_is_real_vector(type_lowering(exprtype(expr->subscript_expr.expr))->type_kind))
|
|
|| (expr->expr_kind == EXPR_SWIZZLE && type_kind_is_real_vector(type_lowering(exprtype(expr->swizzle_expr.parent))->type_kind));
|
|
}
|
|
|
|
const char *codegen_create_asm(Ast *ast);
|
|
|
|
extern const char * const benchmark_fns_var_name;
|
|
extern const char * const benchmark_names_var_name;
|
|
extern const char * const test_fns_var_name;
|
|
extern const char * const test_names_var_name;
|
|
|
|
INLINE Type *lowered_member_type(Decl *member)
|
|
{
|
|
return type_lowering_abi(member->type);
|
|
}
|
|
|
|
INLINE Type *lowered_array_element_type(Type *array_type)
|
|
{
|
|
return type_lowering_abi(array_type->array.base);
|
|
}
|