From 781638d207843350423aa4a9d77b77ba29e75123 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 27 Dec 2020 22:13:45 +0100 Subject: [PATCH] Bugfix to split arrays. Correctly generate const initializers on non globals for structs. --- src/compiler/llvm_codegen.c | 5 ++-- src/compiler/llvm_codegen_expr.c | 39 ++++++---------------------- src/compiler/llvm_codegen_internal.h | 1 + src/compiler/sema_expr.c | 21 ++++++++++++--- 4 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index c647b21ab..d86d85f52 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -87,10 +87,11 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ pieces[count++] = llvm_emit_const_initializer(c, const_init->split_const.low, modified); } pieces[count++] = llvm_emit_const_initializer(c, const_init->split_const.mid, modified); - if (const_init->split_const.low) + if (const_init->split_const.hi) { - pieces[count++] = llvm_emit_const_initializer(c, const_init->split_const.low, modified); + pieces[count++] = llvm_emit_const_initializer(c, const_init->split_const.hi, modified); } + if (count == 1) return pieces[0]; return LLVMConstStructInContext(c->context, pieces, count, true); } case CONST_INIT_ARRAY_VALUE_FRAGMENT: diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 75f65231a..27868dc97 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -524,33 +524,8 @@ static inline void gencontext_emit_cast_expr(GenContext *context, BEValue *be_va expr->cast_expr.expr->type->canonical); } -static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *expr); +static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *expr, bool *modified); -static void gencontext_construct_const_value(GenContext *context, BEValue *be_value, Expr *expr) -{ - if (expr->expr_kind == EXPR_INITIALIZER_LIST) - { - llvm_emit_initializer_list_expr_const(context, expr); - return; - } - llvm_emit_expr(context, be_value, expr); -} - -static void gencontext_construct_const_union_struct(GenContext *context, BEValue *be_value, Type *canonical, Expr *value) -{ - LLVMValueRef values[2]; - gencontext_construct_const_value(context, be_value, value); - values[0] = llvm_value_rvalue_store(context, be_value); - unsigned size_diff = type_size(canonical) - type_size(value->type); - if (size_diff > 0) - { - LLVMTypeRef size = LLVMArrayType(llvm_get_type(context, type_char), size_diff); - values[1] = LLVMConstNull(size); - } - llvm_value_set(be_value, - LLVMConstStructInContext(context->context, values, size_diff > 0 ? 2 : 1, false), - canonical); -} static LLVMValueRef llvm_recursive_set_value(GenContext *c, DesignatorElement **current_element_ptr, LLVMValueRef parent, DesignatorElement **last_element_ptr, Expr *value) { @@ -613,16 +588,17 @@ static LLVMValueRef llvm_recursive_set_const_value(GenContext *context, Designat } -static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *expr) +static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *expr, bool *modified) { Type *canonical = expr->type->canonical; LLVMTypeRef type = llvm_get_type(c, canonical); if (expr->initializer_expr.init_type == INITIALIZER_CONST) { - return LLVMConstNull(type); + return llvm_emit_const_aggregate(c, expr, modified); } + bool is_error = expr->type->canonical->type_kind == TYPE_ERRTYPE; if (is_error) @@ -650,7 +626,7 @@ static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *e Expr *element = elements[i]; if (element->expr_kind == EXPR_INITIALIZER_LIST) { - value = LLVMConstInsertValue(value, llvm_emit_initializer_list_expr_const(c, element), &i, 1); + value = LLVMConstInsertValue(value, llvm_emit_initializer_list_expr_const(c, element, modified), &i, 1); continue; } BEValue be_value; @@ -676,11 +652,12 @@ static LLVMValueRef llvm_emit_initializer_list_expr_const(GenContext *c, Expr *e static inline void llvm_emit_initialize_reference_small_const(GenContext *c, BEValue *ref, Expr *expr) { + bool modified = false; // First create the constant value. - LLVMValueRef value = llvm_emit_initializer_list_expr_const(c, expr); + LLVMValueRef value = llvm_emit_initializer_list_expr_const(c, expr, &modified); // Create a global const. - LLVMTypeRef type = llvm_get_type(c, expr->type); + LLVMTypeRef type = modified ? LLVMTypeOf(value) : llvm_get_type(c, expr->type); LLVMValueRef global_copy = LLVMAddGlobal(c->module, type, ""); // Set a nice alignment diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 2994bd437..af9b4ae4a 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -222,6 +222,7 @@ void llvm_emit_debug_local_var(GenContext *c, Decl *var); void llvm_emit_debug_global_var(GenContext *c, Decl *global); void llvm_emit_defer(GenContext *c, AstId defer_start, AstId defer_end); void llvm_emit_extern_decl(GenContext *context, Decl *decl); +LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified); LLVMValueRef llvm_emit_is_no_error(GenContext *c, LLVMValueRef error); LLVMValueRef llvm_emit_load_aligned(GenContext *c, LLVMTypeRef type, LLVMValueRef pointer, unsigned alignment, const char *name); void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 7fa5d5f0c..ca7817598 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2031,12 +2031,19 @@ static Type *sema_find_type_of_element(Context *context, Type *type, DesignatorE { return NULL; } - int64_t index = sema_analyse_designator_index(context, element->index_expr); + ByteSize len = type_lowered->array.len; + ArrayIndex index = sema_analyse_designator_index(context, element->index_expr); if (index < 0) { *did_report_error = true; return NULL; } + if (index >= (ArrayIndex)len) + { + SEMA_ERROR(element->index_expr, "The index may must be less than the array length (which was %llu).", (unsigned long long)len); + *did_report_error = true; + return NULL; + } element->index = index; if (element->index_expr->expr_kind != EXPR_CONST) *is_constant = false; @@ -2053,8 +2060,16 @@ static Type *sema_find_type_of_element(Context *context, Type *type, DesignatorE && index > end_index) { SEMA_ERROR(element->index_end_expr, "End index must be greater than start index."); - return false; + *did_report_error = true; + return NULL; } + if (end_index > (ArrayIndex)len) + { + *did_report_error = true; + SEMA_ERROR(element->index_expr, "The index may must be less than the array length (which was %llu).", (unsigned long long)len); + return NULL; + } + element->index_end = end_index; } return type_lowered->array.base; @@ -2442,8 +2457,6 @@ static bool sema_expr_analyse_designated_initializer(Context *context, Type *ass { ConstInitializer *const_init = MALLOC(sizeof(ConstInitializer)); sema_create_const_initializer(const_init, initializer); - printf("---------------------------------\n"); - debug_dump_const_initializer(const_init, "TOP", 0); initializer->initializer_expr.init_type = INITIALIZER_CONST; initializer->initializer_expr.initializer = const_init; return true;