Bugfix to split arrays. Correctly generate const initializers on non globals for structs.

This commit is contained in:
Christoffer Lerno
2020-12-27 22:13:45 +01:00
parent 9a0b8aab0b
commit 781638d207
4 changed files with 29 additions and 37 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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);

View File

@@ -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;