From 6e0c3dc173507b92fc04515659454044f918efbb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 8 Dec 2015 14:47:17 -0700 Subject: [PATCH] array access support --- example/arrays/arrays.zig | 5 +++-- src/analyze.cpp | 16 ++++++++++++---- src/analyze.hpp | 5 +++++ src/codegen.cpp | 21 ++++++++++++++++++--- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/example/arrays/arrays.zig b/example/arrays/arrays.zig index 04f3d3b5f8..88ec8e411b 100644 --- a/example/arrays/arrays.zig +++ b/example/arrays/arrays.zig @@ -9,8 +9,9 @@ extern { export fn _start() -> unreachable { let mut array : [i32; 10]; - array[4] = array[1] + 5; + exit(array[1]); + + //array[4] = array[1] + 5; - exit(0); } diff --git a/src/analyze.cpp b/src/analyze.cpp index 3351041db9..c6f50ff5d3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -124,6 +124,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, in entry->align_in_bits = child_type->align_in_bits; entry->di_type = LLVMZigCreateDebugArrayType(g->dbuilder, entry->size_in_bits, entry->align_in_bits, child_type->di_type, array_size); + entry->data.array.child_type = child_type; g->type_table.put(&entry->name, entry); child_type->arrays_by_size.put(array_size, entry); @@ -185,7 +186,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { size = parse_int(&size_node->data.number); } - type_node->entry = get_array_type(g, child_type, size); // TODO + type_node->entry = get_array_type(g, child_type, size); return type_node->entry; } } @@ -737,12 +738,19 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, case NodeTypeArrayAccessExpr: { // here we are always reading the array - TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, + TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, node->data.array_access_expr.array_ref_expr); - if (lhs_type->id == TypeTableEntryIdArray) { - zig_panic("TODO"); + if (array_type->id == TypeTableEntryIdArray) { + TypeTableEntry *subscript_type = analyze_expression(g, import, context, + nullptr, node->data.array_access_expr.subscript); + if (subscript_type->id != TypeTableEntryIdInt) { + add_node_error(g, node, + buf_sprintf("array subscripts must be integers")); + } + return_type = array_type->data.array.child_type; } else { add_node_error(g, node, buf_sprintf("array access of non-array")); + return_type = g->builtin_types.entry_invalid; } break; diff --git a/src/analyze.hpp b/src/analyze.hpp index c79f2d0f85..dca9f37cbf 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -26,6 +26,10 @@ struct TypeTableEntryInt { bool is_signed; }; +struct TypeTableEntryArray { + TypeTableEntry *child_type; +}; + enum TypeTableEntryId { TypeTableEntryIdInvalid, TypeTableEntryIdVoid, @@ -50,6 +54,7 @@ struct TypeTableEntry { union { TypeTableEntryPointer pointer; TypeTableEntryInt integral; + TypeTableEntryArray array; } data; // use these fields to make sure we don't duplicate type table entries for the same type diff --git a/src/codegen.cpp b/src/codegen.cpp index 6c7a84774d..366873c721 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -170,7 +170,18 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeArrayAccessExpr); - zig_panic("TODO gen arary access"); + LLVMValueRef array_ref_value = gen_expr(g, node->data.array_access_expr.array_ref_expr); + LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript); + + assert(array_ref_value); + assert(subscript_value); + + LLVMValueRef indices[] = { + LLVMConstInt(LLVMInt32Type(), 0, false), + subscript_value + }; + LLVMValueRef result_ptr = LLVMBuildInBoundsGEP(g->builder, array_ref_value, indices, 2, ""); + return LLVMBuildLoad(g->builder, result_ptr, ""); } static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { @@ -651,8 +662,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { if (variable->type == g->builtin_types.entry_void) { return nullptr; } else if (variable->is_ptr) { - add_debug_source_node(g, node); - return LLVMBuildLoad(g->builder, variable->value_ref, ""); + if (variable->type->id == TypeTableEntryIdArray) { + return variable->value_ref; + } else { + add_debug_source_node(g, node); + return LLVMBuildLoad(g->builder, variable->value_ref, ""); + } } else { return variable->value_ref; }