mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Bugfix to split arrays. Correctly generate const initializers on non globals for structs.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user