fix nested arrays
parent
826c7f06a3
commit
f0a43cfda9
|
@ -235,17 +235,53 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui
|
|||
}
|
||||
}
|
||||
|
||||
static void unknown_size_array_type_common_init(CodeGen *g, TypeTableEntry *child_type,
|
||||
bool is_const, TypeTableEntry *entry)
|
||||
{
|
||||
TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
|
||||
|
||||
unsigned element_count = 2;
|
||||
entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->data.structure.is_packed = false;
|
||||
entry->data.structure.is_unknown_size_array = true;
|
||||
entry->data.structure.field_count = element_count;
|
||||
entry->data.structure.fields = allocate<TypeStructField>(element_count);
|
||||
entry->data.structure.fields[0].name = buf_create_from_str("ptr");
|
||||
entry->data.structure.fields[0].type_entry = pointer_type;
|
||||
entry->data.structure.fields[0].src_index = 0;
|
||||
entry->data.structure.fields[0].gen_index = 0;
|
||||
entry->data.structure.fields[1].name = buf_create_from_str("len");
|
||||
entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
|
||||
entry->data.structure.fields[1].src_index = 1;
|
||||
entry->data.structure.fields[1].gen_index = 1;
|
||||
}
|
||||
|
||||
static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
|
||||
assert(child_type->id != TypeTableEntryIdInvalid);
|
||||
TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
|
||||
|
||||
if (*parent_pointer) {
|
||||
return *parent_pointer;
|
||||
} else if (is_const) {
|
||||
TypeTableEntry *var_peer = get_unknown_size_array_type(g, child_type, false);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
|
||||
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name));
|
||||
|
||||
unknown_size_array_type_common_init(g, child_type, is_const, entry);
|
||||
|
||||
entry->type_ref = var_peer->type_ref;
|
||||
entry->di_type = var_peer->di_type;
|
||||
|
||||
*parent_pointer = entry;
|
||||
return entry;
|
||||
} else {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
|
||||
|
||||
const char *const_str = is_const ? "const " : "";
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "[]%s%s", const_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
|
||||
entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
|
||||
|
||||
TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
|
||||
|
@ -257,20 +293,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
|
|||
};
|
||||
LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
|
||||
|
||||
entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
|
||||
entry->align_in_bits = g->pointer_size_bytes * 8;
|
||||
entry->data.structure.is_packed = false;
|
||||
entry->data.structure.is_unknown_size_array = true;
|
||||
entry->data.structure.field_count = element_count;
|
||||
entry->data.structure.fields = allocate<TypeStructField>(element_count);
|
||||
entry->data.structure.fields[0].name = buf_create_from_str("ptr");
|
||||
entry->data.structure.fields[0].type_entry = pointer_type;
|
||||
entry->data.structure.fields[0].src_index = 0;
|
||||
entry->data.structure.fields[0].gen_index = 0;
|
||||
entry->data.structure.fields[1].name = buf_create_from_str("len");
|
||||
entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
|
||||
entry->data.structure.fields[1].src_index = 1;
|
||||
entry->data.structure.fields[1].gen_index = 1;
|
||||
unknown_size_array_type_common_init(g, child_type, is_const, entry);
|
||||
|
||||
LLVMZigDIType *di_element_types[] = {
|
||||
pointer_type->di_type,
|
||||
|
|
|
@ -150,6 +150,13 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
|
|||
return expr->type_entry;
|
||||
}
|
||||
|
||||
static bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
return type_entry->id == TypeTableEntryIdStruct ||
|
||||
(type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
|
||||
type_entry->id == TypeTableEntryIdMaybe ||
|
||||
type_entry->id == TypeTableEntryIdArray;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
|
||||
NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
|
||||
{
|
||||
|
@ -681,12 +688,27 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
|
||||
assert(node->type == NodeTypeArrayAccessExpr);
|
||||
|
||||
LLVMValueRef ptr = gen_array_ptr(g, node);
|
||||
TypeTableEntry *child_type;
|
||||
TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
child_type = array_type->data.pointer.child_type;
|
||||
} else if (array_type->id == TypeTableEntryIdStruct) {
|
||||
assert(array_type->data.structure.is_unknown_size_array);
|
||||
TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
|
||||
assert(child_ptr_type->id == TypeTableEntryIdPointer);
|
||||
child_type = child_ptr_type->data.pointer.child_type;
|
||||
} else if (array_type->id == TypeTableEntryIdArray) {
|
||||
child_type = array_type->data.array.child_type;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
if (is_lvalue || !ptr) {
|
||||
if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
|
||||
return ptr;
|
||||
} else {
|
||||
add_debug_source_node(g, node);
|
||||
|
@ -1142,10 +1164,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
|
|||
static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,
|
||||
TypeTableEntry *type_entry)
|
||||
{
|
||||
assert(type_entry->id == TypeTableEntryIdStruct ||
|
||||
type_entry->id == TypeTableEntryIdMaybe ||
|
||||
(type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
|
||||
type_entry->id == TypeTableEntryIdArray);
|
||||
assert(handle_is_ptr(type_entry));
|
||||
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
|
||||
|
@ -1168,11 +1187,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
|
|||
LLVMValueRef target_ref, LLVMValueRef value,
|
||||
TypeTableEntry *op1_type, TypeTableEntry *op2_type)
|
||||
{
|
||||
if (op1_type->id == TypeTableEntryIdStruct ||
|
||||
(op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) ||
|
||||
op1_type->id == TypeTableEntryIdMaybe ||
|
||||
op1_type->id == TypeTableEntryIdArray)
|
||||
{
|
||||
if (handle_is_ptr(op1_type)) {
|
||||
assert(op1_type == op2_type);
|
||||
assert(bin_op == BinOpTypeAssign);
|
||||
|
||||
|
@ -1632,8 +1647,10 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
|
|||
|
||||
add_debug_source_node(g, field_node);
|
||||
LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
|
||||
LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);
|
||||
LLVMBuildStore(g->builder, value, field_ptr);
|
||||
AstNode *expr_node = field_node->data.struct_val_field.expr;
|
||||
LLVMValueRef value = gen_expr(g, expr_node);
|
||||
gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value,
|
||||
type_struct_field->type_entry, get_expr_type(expr_node));
|
||||
}
|
||||
|
||||
return tmp_struct_ptr;
|
||||
|
@ -1651,6 +1668,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
|
|||
int field_count = type_entry->data.array.len;
|
||||
assert(field_count == node->data.container_init_expr.entries.length);
|
||||
|
||||
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
||||
|
||||
for (int i = 0; i < field_count; i += 1) {
|
||||
AstNode *field_node = node->data.container_init_expr.entries.at(i);
|
||||
LLVMValueRef elem_val = gen_expr(g, field_node);
|
||||
|
@ -1661,7 +1680,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
|
|||
};
|
||||
add_debug_source_node(g, field_node);
|
||||
LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
|
||||
LLVMBuildStore(g->builder, elem_val, elem_ptr);
|
||||
gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
|
||||
child_type, get_expr_type(field_node));
|
||||
}
|
||||
|
||||
return tmp_array_ptr;
|
||||
|
|
|
@ -1121,6 +1121,21 @@ pub fn main(args: [][]u8) i32 => {
|
|||
return 0;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
add_simple_case("nested arrays", R"SOURCE(
|
||||
import "std.zig";
|
||||
|
||||
pub fn main(args: [][]u8) i32 => {
|
||||
const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
|
||||
var i: @typeof(array_of_strings.len) = 0;
|
||||
while (i < array_of_strings.len) {
|
||||
print_str(array_of_strings[i]);
|
||||
print_str("\n");
|
||||
i += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "hello\nthis\nis\nmy\nthing\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue