mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Remove all array pointer decay.
This commit is contained in:
@@ -237,6 +237,7 @@ static bool voidfail_to_error(Expr *expr, Type *type)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cast int to bool using CAST_INTBOOL
|
||||
* or rewrite 0 => false, any other value => true
|
||||
@@ -466,18 +467,56 @@ static bool array_to_vector(Expr *expr, Type *to_type)
|
||||
/**
|
||||
* We have two cases:
|
||||
* 1. int[] -> Foo[] where Foo is a distinct or typedef OR it is a constant. Then we can just redefine
|
||||
* 2. The second case is something like int*[] -> void*[] for this case we need to make a bitcast.
|
||||
* 2. The second case is something like int*[] -> void*[] for this case we need to make a bitcast using CAST_SASA.
|
||||
*/
|
||||
INLINE bool subarray_to_subarray(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (expr_is_const(expr) || type_flatten(type_flatten(to_type)->array.base) == type_flatten(type_flatten(expr->type)->array.base))
|
||||
{
|
||||
// Here we assume int[] -> float[] can't happen.
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
return insert_cast(expr, CAST_SASA, to_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitstruct casts go from its base type to any integer or char array of the same size.
|
||||
*/
|
||||
static bool bitstruct_cast(Expr *expr, Type *bitstruct_type, Type *to, Type *to_type)
|
||||
{
|
||||
assert(type_size(to) == type_size(bitstruct_type) && "Only casts to the same width expected.");
|
||||
|
||||
// The case where the bitstruct is backed by an integer
|
||||
if (type_is_integer(bitstruct_type))
|
||||
{
|
||||
// The same size integer, this is the simple case.
|
||||
if (type_is_integer(to))
|
||||
{
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
// Now we expect a char array of the same size. This
|
||||
// is runtime only.
|
||||
assert(to->type_kind == TYPE_ARRAY);
|
||||
return insert_cast(expr, CAST_BSARRY, to_type);
|
||||
}
|
||||
|
||||
// Converting from a char array.
|
||||
assert(bitstruct_type->type_kind == TYPE_ARRAY);
|
||||
|
||||
// Converting to a char array is the simple case, just change the type.
|
||||
if (to->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converting to an integer, this is a runtime cast.
|
||||
assert(type_is_integer(to));
|
||||
return insert_cast(expr, CAST_BSINT, to_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast using CAST_VECARR, casting an array to a vector. For the constant, this
|
||||
* is a simple type change, see array_to_vector.
|
||||
@@ -568,6 +607,39 @@ bool cast_promote_vararg(Expr *arg)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given lhs and rhs, promote to the maximum bit size, this will retain
|
||||
* signed/unsigned type of each side.
|
||||
*/
|
||||
void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Type *left_type, Type *right_type)
|
||||
{
|
||||
unsigned bit_size_left = left_type->builtin.bitsize;
|
||||
unsigned bit_size_right = right_type->builtin.bitsize;
|
||||
|
||||
assert(bit_size_left && bit_size_right);
|
||||
|
||||
// Simple case they are the same size, just return.
|
||||
if (bit_size_left == bit_size_right) return;
|
||||
|
||||
// Lhs is smaller than rhs, so widen it using the right type
|
||||
if (bit_size_left < bit_size_right)
|
||||
{
|
||||
Type *to = lhs->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_right)
|
||||
: type_int_unsigned_by_bitsize(bit_size_right);
|
||||
bool success = cast(lhs, to);
|
||||
assert(success);
|
||||
return;
|
||||
}
|
||||
|
||||
// Rhs is smaller, do the same thing as above but with the rhs.
|
||||
Type *to = rhs->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_left)
|
||||
: type_int_unsigned_by_bitsize(bit_size_left);
|
||||
bool success = cast(rhs, to);
|
||||
assert(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* For implicit casts to bool, in a conditional, return the type of cast to
|
||||
* insert.
|
||||
@@ -1931,7 +2003,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_BITSTRUCT:
|
||||
return bitstruct_cast(expr, from_type, to, to_type);
|
||||
return bitstruct_cast(expr, type_flatten(from_type->decl->bitstruct.base_type->type), to, to_type);
|
||||
case TYPE_BOOL:
|
||||
// Bool may convert into integers and floats but only explicitly.
|
||||
if (type_is_integer(to)) return bool_to_int(expr, to, to_type);
|
||||
@@ -2019,28 +2091,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static bool bitstruct_cast(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
{
|
||||
Type *base_type = type_flatten_distinct(from_type->decl->bitstruct.base_type->type);
|
||||
assert(type_size(to) == type_size(base_type));
|
||||
if (type_is_integer(base_type) && type_is_integer(to))
|
||||
{
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
if (base_type->type_kind == TYPE_ARRAY && to->type_kind == TYPE_ARRAY)
|
||||
{
|
||||
expr->type = to_type;
|
||||
return true;
|
||||
}
|
||||
if (type_is_integer(base_type))
|
||||
{
|
||||
assert(to->type_kind == TYPE_ARRAY);
|
||||
return insert_cast(expr, CAST_BSARRY, to_type);
|
||||
}
|
||||
assert(base_type->type_kind == TYPE_ARRAY);
|
||||
return insert_cast(expr, CAST_BSINT, to_type);
|
||||
}
|
||||
|
||||
bool cast(Expr *expr, Type *to_type)
|
||||
{
|
||||
@@ -2173,37 +2223,7 @@ Type *cast_numeric_arithmetic_promotion(Type *type)
|
||||
}
|
||||
}
|
||||
|
||||
bool cast_decay_array_pointers(SemaContext *context, Expr *expr)
|
||||
{
|
||||
CanonicalType *pointer_type = type_pointer_type(type_no_optional(expr->type));
|
||||
if (!pointer_type || !type_is_arraylike(pointer_type)) return true;
|
||||
return cast_expr_inner(context,
|
||||
expr,
|
||||
type_add_optional(type_get_ptr(pointer_type->array.base), IS_OPTIONAL(expr)),
|
||||
true, false, false);
|
||||
}
|
||||
|
||||
void cast_to_max_bit_size(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type)
|
||||
{
|
||||
unsigned bit_size_left = left_type->builtin.bitsize;
|
||||
unsigned bit_size_right = right_type->builtin.bitsize;
|
||||
assert(bit_size_left && bit_size_right);
|
||||
if (bit_size_left == bit_size_right) return;
|
||||
if (bit_size_left < bit_size_right)
|
||||
{
|
||||
Type *to = left->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_right)
|
||||
: type_int_unsigned_by_bitsize(bit_size_right);
|
||||
bool success = cast(left, to);
|
||||
assert(success);
|
||||
return;
|
||||
}
|
||||
Type *to = right->type->type_kind < TYPE_U8
|
||||
? type_int_signed_by_bitsize(bit_size_left)
|
||||
: type_int_unsigned_by_bitsize(bit_size_left);
|
||||
bool success = cast(right, to);
|
||||
assert(success);
|
||||
}
|
||||
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
@@ -4324,7 +4324,6 @@ static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, E
|
||||
if (left_type_canonical->type_kind == TYPE_POINTER)
|
||||
{
|
||||
|
||||
if (!cast_decay_array_pointers(context, left)) return false;
|
||||
expr->type = left->type;
|
||||
|
||||
// 7. Finally, check that the right side is indeed an integer.
|
||||
@@ -4423,13 +4422,11 @@ static bool sema_expr_analyse_sub(SemaContext *context, Expr *expr, Expr *left,
|
||||
// 2. Handle the ptr - x and ptr - other_pointer
|
||||
if (left_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (!cast_decay_array_pointers(context, left)) return false;
|
||||
left_type = type_no_optional(left->type)->canonical;
|
||||
|
||||
// 3. ptr - other pointer
|
||||
if (right_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (!cast_decay_array_pointers(context, right)) return false;
|
||||
right_type = type_no_optional(right->type)->canonical;
|
||||
|
||||
// 3a. Require that both types are the same.
|
||||
@@ -4580,8 +4577,6 @@ static bool sema_expr_analyse_add(SemaContext *context, Expr *expr, Expr *left,
|
||||
// so check if we want to do the normal pointer add special handling.
|
||||
if (left_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (!cast_decay_array_pointers(context, left)) return false;
|
||||
|
||||
// 3a. Check that the other side is an integer of some sort.
|
||||
if (!type_is_integer(right_type))
|
||||
{
|
||||
@@ -5076,7 +5071,7 @@ static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left,
|
||||
|| (type_is_signed(left_type) && type_is_unsigned(right_type)))
|
||||
{
|
||||
// 2a. Resize so that both sides have the same bit width. This will always work.
|
||||
cast_to_max_bit_size(context, left, right, left_type, right_type);
|
||||
cast_to_int_to_max_bit_size(context, left, right, left_type, right_type);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
@@ -5580,8 +5575,6 @@ static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cast_decay_array_pointers(context, inner)) return false;
|
||||
|
||||
// 6. Done, the result is same as the inner type.
|
||||
expr->type = inner->type;
|
||||
return true;
|
||||
|
||||
@@ -83,8 +83,8 @@ Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallAB
|
||||
bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type);
|
||||
bool cast_promote_vararg(Expr *arg);
|
||||
Type *cast_numeric_arithmetic_promotion(Type *type);
|
||||
void cast_to_max_bit_size(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type);
|
||||
bool cast_decay_array_pointers(SemaContext *context, Expr *expr);
|
||||
void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Type *left_type, Type *right_type);
|
||||
|
||||
INLINE bool sema_set_abi_alignment(SemaContext *context, Type *type, AlignSize *result);
|
||||
INLINE bool sema_set_alloca_alignment(SemaContext *context, Type *type, AlignSize *result);
|
||||
void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *decl, SourceSpan use);
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.92"
|
||||
#define COMPILER_VERSION "0.4.93"
|
||||
20
test/test_suite/bitstruct/bitstruct_cast_const_init.c3t
Normal file
20
test/test_suite/bitstruct/bitstruct_cast_const_init.c3t
Normal file
@@ -0,0 +1,20 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
bitstruct Foo : int
|
||||
{
|
||||
int abc : 0..4;
|
||||
int def : 23..26;
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
Foo f;
|
||||
int z = (int) Foo { .abc = 2, .def = 1 };
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
%f = alloca i32, align 4
|
||||
%z = alloca i32, align 4
|
||||
store i32 0, ptr %f, align 4
|
||||
store i32 8388610, ptr %z, align 4
|
||||
@@ -13,7 +13,7 @@ fn void main()
|
||||
int* xx = &x + 1;
|
||||
int[3]* yy = (int[3]*)(xx);
|
||||
int* zz = yy - 1;
|
||||
printf("%p = %p = %p, %p = %p\n", y, z, zz, &(*y)[1], xx);
|
||||
printf("%p = %p = %p, %p != %p\n", y, z, zz, &(*y)[1], xx);
|
||||
x[1] = 123;
|
||||
printf("%d = %d\n", x[1], z[1]);
|
||||
}
|
||||
@@ -52,12 +52,12 @@ entry:
|
||||
%ptroffset1 = getelementptr inbounds i32, ptr %8, i64 1
|
||||
%9 = load i32, ptr %ptroffset1, align 4
|
||||
store i32 %9, ptr %z1, align 4
|
||||
%ptroffset2 = getelementptr i32, ptr %x, i64 1
|
||||
%ptroffset2 = getelementptr [3 x i32], ptr %x, i64 1
|
||||
store ptr %ptroffset2, ptr %xx, align 8
|
||||
%10 = load ptr, ptr %xx, align 8
|
||||
store ptr %10, ptr %yy, align 8
|
||||
%11 = load ptr, ptr %yy, align 8
|
||||
%ptroffset3 = getelementptr i32, ptr %11, i64 -1
|
||||
%ptroffset3 = getelementptr [3 x i32], ptr %11, i64 -1
|
||||
store ptr %ptroffset3, ptr %zz, align 8
|
||||
%12 = load ptr, ptr %y, align 8
|
||||
%13 = load ptr, ptr %z, align 8
|
||||
|
||||
19
test/unit/regression/pointer_non_decay.c3
Normal file
19
test/unit/regression/pointer_non_decay.c3
Normal file
@@ -0,0 +1,19 @@
|
||||
module test @test;
|
||||
|
||||
fn void pointer_non_decay()
|
||||
{
|
||||
int[3] x;
|
||||
int[3]* y = &x;
|
||||
int* z = y;
|
||||
int[] sub = y;
|
||||
int[3] y1 = y[1];
|
||||
int z1 = z[1];
|
||||
int* xx = &x + 1;
|
||||
int[3]* yy = (int[3]*)(xx);
|
||||
int* zz = yy - 1;
|
||||
assert(y == z);
|
||||
assert(z == zz);
|
||||
assert(&(*y)[1] == &xx[-2]);
|
||||
x[1] = 123;
|
||||
assert(x[1] == z[1]);
|
||||
}
|
||||
Reference in New Issue
Block a user