Fix of nested union/struct initialization. Fixes #886.

This commit is contained in:
Christoffer Lerno
2023-07-26 21:12:04 +02:00
parent 499c82b089
commit c18526f10a
5 changed files with 57 additions and 64 deletions

View File

@@ -1682,16 +1682,15 @@ static LLVMValueRef llvm_recursive_set_value(GenContext *c, DesignatorElement **
}
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr)
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, ConstInitializer *initializer)
{
bool modified = false;
// First create the constant value.
assert(expr_is_const_initializer(expr));
LLVMValueRef value = llvm_emit_const_initializer(c, expr->const_expr.initializer);
LLVMValueRef value = llvm_emit_const_initializer(c, initializer);
// Create a global const.
AlignSize alignment = type_alloca_alignment(expr->type);
AlignSize alignment = type_alloca_alignment(initializer->type);
LLVMTypeRef type = LLVMTypeOf(value);
LLVMValueRef global_copy = llvm_add_global_raw(c, ".__const", type, alignment);
llvm_set_private_linkage(global_copy);
@@ -1705,11 +1704,49 @@ void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref,
llvm_value_addr(c, ref);
// Perform the memcpy.
llvm_emit_memcpy(c, ref->value, ref->alignment, global_copy, alignment, type_size(expr->type));
llvm_emit_memcpy(c, ref->value, ref->alignment, global_copy, alignment, type_size(initializer->type));
}
static inline void llvm_emit_const_initialize_bitstruct_ref(GenContext *c, BEValue *ref, ConstInitializer *initializer)
{
if (initializer->kind == CONST_INIT_ZERO)
{
llvm_store_zero(c, ref);
return;
}
assert(initializer->kind == CONST_INIT_STRUCT);
llvm_store_raw(c, ref, llvm_emit_const_bitstruct(c, initializer));
}
static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializer *const_init)
{
if (const_init->type->type_kind == TYPE_VECTOR)
{
LLVMValueRef val = llvm_emit_const_initializer(c, const_init);
llvm_store_raw(c, ref, val);
return;
}
if (const_init->type->type_kind == TYPE_BITSTRUCT)
{
llvm_emit_const_initialize_bitstruct_ref(c, ref, const_init);
return;
}
if (const_init->kind == CONST_INIT_ZERO)
{
// In case of a zero, optimize.
llvm_store_zero(c, ref);
return;
}
// In case of small const initializers, or full arrays - use copy.
if (const_init->kind == CONST_INIT_ARRAY_FULL || type_size(const_init->type) <= 32)
{
llvm_emit_initialize_reference_temporary_const(c, ref, const_init);
return;
}
// Make sure we have an address.
llvm_value_addr(c, ref);
switch (const_init->kind)
{
case CONST_INIT_ZERO:
@@ -1800,16 +1837,6 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ
UNREACHABLE
}
static inline void llvm_emit_const_initialize_struct_union_array(GenContext *c, BEValue *ref, Expr *expr)
{
assert(expr_is_const_initializer(expr));
ConstInitializer *initializer = expr->const_expr.initializer;
// Make sure we have an address.
llvm_value_addr(c, ref);
llvm_emit_const_init_ref(c, ref, initializer);
}
static inline void llvm_emit_initialize_reference_vector(GenContext *c, BEValue *ref, Type *real_type, Expr **elements)
{
llvm_value_addr(c, ref);
@@ -2244,16 +2271,6 @@ LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initiali
return result;
}
static inline void llvm_emit_const_initialize_bitstruct_ref(GenContext *c, BEValue *ref, ConstInitializer *initializer)
{
if (initializer->kind == CONST_INIT_ZERO)
{
llvm_store_zero(c, ref);
return;
}
assert(initializer->kind == CONST_INIT_STRUCT);
llvm_store_raw(c, ref, llvm_emit_const_bitstruct(c, initializer));
}
/**
* Initialize a constant aggregate type.
@@ -2261,31 +2278,7 @@ static inline void llvm_emit_const_initialize_bitstruct_ref(GenContext *c, BEVal
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr)
{
assert(expr_is_const_initializer(expr));
ConstInitializer *initializer = expr->const_expr.initializer;
if (initializer->type->type_kind == TYPE_VECTOR)
{
LLVMValueRef val = llvm_emit_const_initializer(c, initializer);
llvm_store_raw(c, ref, val);
return;
}
if (initializer->type->type_kind == TYPE_BITSTRUCT)
{
llvm_emit_const_initialize_bitstruct_ref(c, ref, initializer);
return;
}
if (initializer->kind == CONST_INIT_ZERO)
{
// In case of a zero, optimize.
llvm_store_zero(c, ref);
return;
}
// In case of small const initializers, or full arrays - use copy.
if (initializer->kind == CONST_INIT_ARRAY_FULL || type_size(expr->type) <= 32)
{
llvm_emit_initialize_reference_temporary_const(c, ref, expr);
return;
}
llvm_emit_const_initialize_struct_union_array(c, ref, expr);
llvm_emit_const_init_ref(c, ref, expr->const_expr.initializer);
return;
}

View File

@@ -483,7 +483,7 @@ void llvm_emit_dynamic_functions(GenContext *context, Decl **funcs);
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional);
INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr);
INLINE void llvm_emit_statement_chain(GenContext *c, AstId current);
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr);
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, ConstInitializer *initializer);
void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len);
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.581"
#define COMPILER_VERSION "0.4.582"

View File

@@ -65,7 +65,7 @@ entry:
%6 = getelementptr inbounds %c, ptr %2, i32 0, i32 3
store double 0.000000e+00, ptr %6, align 8
%7 = getelementptr inbounds %c, ptr %2, i32 0, i32 4
store double 3.300000e+00, ptr %7, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %7, ptr align 8 @.__const, i32 8, i1 false)
%8 = getelementptr inbounds %ExtraSimple, ptr %a, i32 0, i32 3
%9 = getelementptr inbounds %.anon, ptr %8, i32 0, i32 0
store i32 0, ptr %9, align 8

View File

@@ -69,25 +69,25 @@ entry:
%m2 = alloca %Matrix2x2_b, align 4
%0 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0
%1 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 0
store float 1.000000e+00, ptr %1, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %1, ptr align 4 @.__const, i32 4, i1 false)
%2 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 1
store float 2.000000e+00, ptr %2, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %2, ptr align 4 @.__const.16, i32 4, i1 false)
%3 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 2
store float 3.000000e+00, ptr %3, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %3, ptr align 4 @.__const.17, i32 4, i1 false)
%4 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 3
store float 4.000000e+00, ptr %4, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %4, ptr align 4 @.__const.18, i32 4, i1 false)
%5 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 4
store float 5.000000e+00, ptr %5, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %5, ptr align 4 @.__const.19, i32 4, i1 false)
%6 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 5
store float 6.000000e+00, ptr %6, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %6, ptr align 4 @.__const.20, i32 4, i1 false)
%7 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 6
store float 7.000000e+00, ptr %7, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %7, ptr align 4 @.__const.21, i32 4, i1 false)
%8 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 7
store float 8.000000e+00, ptr %8, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %8, ptr align 4 @.__const.22, i32 4, i1 false)
%9 = getelementptr inbounds %.anon.0, ptr %0, i32 0, i32 8
store float 9.000000e+00, ptr %9, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const, i32 16, i1 false)
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.16, i32 16, i1 false)
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %9, ptr align 4 @.__const.23, i32 4, i1 false)
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const.24, i32 16, i1 false)
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.25, i32 16, i1 false)
%10 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0
%11 = getelementptr inbounds %.anon.0, ptr %10, i32 0, i32 0
%12 = load float, ptr %11, align 4