mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- Miscompilation: global struct with vector could generate an incorrect initializer.
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
- Assert when encountering a test function with raw vaarg parameters.
|
||||
- `foo.x` was not always handled correctly when `foo` was optional.
|
||||
- `x'1234' +++ (ichar[1]) { 'A' }` would fail due to missing const folding.
|
||||
- Miscompilation: global struct with vector could generate an incorrect initializer.
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
@@ -230,22 +230,22 @@ static LLVMValueRef llvm_emit_const_array_padding(LLVMTypeRef element_type, Inde
|
||||
LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_init, bool in_aggregate)
|
||||
{
|
||||
ASSERT(const_init->type == type_flatten(const_init->type));
|
||||
Type *type = in_aggregate && const_init->type->type_kind == TYPE_VECTOR ? type_array_from_vector(const_init->type) : const_init->type;
|
||||
switch (const_init->kind)
|
||||
{
|
||||
case CONST_INIT_ZERO:
|
||||
return llvm_get_zero(c, const_init->type);
|
||||
return llvm_get_zero(c, type);
|
||||
case CONST_INIT_ARRAY_VALUE:
|
||||
UNREACHABLE
|
||||
case CONST_INIT_ARRAY_FULL:
|
||||
{
|
||||
ASSERT(const_init->type->type_kind != TYPE_SLICE);
|
||||
ASSERT(type->type_kind != TYPE_SLICE);
|
||||
bool was_modified = false;
|
||||
Type *array_type = const_init->type;
|
||||
Type *element_type = array_type->array.base;
|
||||
Type *element_type = type->array.base;
|
||||
LLVMTypeRef element_type_llvm = llvm_get_type(c, element_type);
|
||||
ConstInitializer **elements = const_init->init_array_full;
|
||||
ASSERT(type_is_arraylike(array_type));
|
||||
ArraySize size = array_type->array.len;
|
||||
ASSERT(type_is_arraylike(type));
|
||||
ArraySize size = type->array.len;
|
||||
ASSERT(size > 0);
|
||||
LLVMValueRef *parts = VECNEW(LLVMValueRef, size);
|
||||
for (ArrayIndex i = 0; i < (ArrayIndex)size; i++)
|
||||
@@ -254,7 +254,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
|
||||
if (element_type_llvm != LLVMTypeOf(element)) was_modified = true;
|
||||
vec_add(parts, element);
|
||||
}
|
||||
if ((!in_aggregate && array_type->type_kind == TYPE_VECTOR) || array_type->type_kind == TYPE_SIMD_VECTOR)
|
||||
if (type->type_kind == TYPE_VECTOR || type->type_kind == TYPE_SIMD_VECTOR)
|
||||
{
|
||||
return LLVMConstVector(parts, vec_size(parts));
|
||||
}
|
||||
@@ -267,20 +267,19 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
|
||||
|
||||
case CONST_INIT_ARRAY:
|
||||
{
|
||||
ASSERT(const_init->type->type_kind != TYPE_SLICE);
|
||||
ASSERT(type->type_kind != TYPE_SLICE);
|
||||
bool was_modified = false;
|
||||
Type *array_type = const_init->type;
|
||||
Type *element_type = array_type->array.base;
|
||||
Type *element_type = type->array.base;
|
||||
LLVMTypeRef element_type_llvm = llvm_get_type(c, element_type);
|
||||
AlignSize expected_align = llvm_abi_alignment(c, element_type_llvm);
|
||||
ConstInitializer **elements = const_init->init_array.elements;
|
||||
ASSERT(vec_size(elements) > 0 && "Array should always have gotten at least one element.");
|
||||
if (elements > 0 && array_type->type_kind == TYPE_FLEXIBLE_ARRAY) was_modified = true;
|
||||
if (elements > 0 && type->type_kind == TYPE_FLEXIBLE_ARRAY) was_modified = true;
|
||||
ArrayIndex current_index = 0;
|
||||
unsigned alignment = 0;
|
||||
LLVMValueRef *parts = NULL;
|
||||
bool pack = false;
|
||||
bool is_vec = array_type->type_kind == TYPE_SIMD_VECTOR || (!in_aggregate && array_type->type_kind == TYPE_VECTOR);
|
||||
bool is_vec = type->type_kind == TYPE_SIMD_VECTOR || type->type_kind == TYPE_VECTOR;
|
||||
FOREACH(ConstInitializer *, element, elements)
|
||||
{
|
||||
ASSERT(element->kind == CONST_INIT_ARRAY_VALUE);
|
||||
@@ -312,7 +311,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
|
||||
current_index = element_index + 1;
|
||||
}
|
||||
|
||||
IndexDiff end_diff = (ArrayIndex)array_type->array.len - current_index;
|
||||
IndexDiff end_diff = (ArrayIndex)type->array.len - current_index;
|
||||
if (end_diff > 0)
|
||||
{
|
||||
vec_add(parts, llvm_emit_const_array_padding(element_type_llvm, end_diff, &was_modified));
|
||||
@@ -321,7 +320,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_
|
||||
{
|
||||
return llvm_get_unnamed_struct(c, parts, pack);
|
||||
}
|
||||
if (type_flat_is_vector(array_type))
|
||||
if (type_flat_is_vector(type))
|
||||
{
|
||||
return LLVMConstVector(parts, vec_size(parts));
|
||||
}
|
||||
|
||||
22
test/test_suite/vector/const_init_struct_with_vector.c3t
Normal file
22
test/test_suite/vector/const_init_struct_with_vector.c3t
Normal file
@@ -0,0 +1,22 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
struct Struct
|
||||
{
|
||||
float[<3>] foo;
|
||||
int bar;
|
||||
}
|
||||
|
||||
Struct my_struct1 = { .foo[1] = 1.0, .bar = 10 };
|
||||
Struct my_struct2 = { .bar = 10 };
|
||||
|
||||
fn int main()
|
||||
{
|
||||
return my_struct1.bar + my_struct2.bar;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
|
||||
|
||||
@test.my_struct1 = local_unnamed_addr global { [3 x float], i32 } { [3 x float] [float 0.000000e+00, float 1.000000e+00, float 0.000000e+00], i32 10 }, align 4
|
||||
@test.my_struct2 = local_unnamed_addr global { [3 x float], i32 } { [3 x float] zeroinitializer, i32 10 }, align 4
|
||||
Reference in New Issue
Block a user