aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-01-07 05:29:11 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-01-07 05:29:11 -0700
commit9aea99a999997e223307d8559e0ff9fa613839a3 (patch)
tree241d9f8fc2b8225a4941bbf8b748170eb49411e7 /src/codegen.cpp
parentea69d6ecda8412cf47b85853c8645d453c826427 (diff)
downloadzig-9aea99a999997e223307d8559e0ff9fa613839a3.tar.gz
zig-9aea99a999997e223307d8559e0ff9fa613839a3.zip
implement array slicing syntax
closes #52
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp68
1 files changed, 60 insertions, 8 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 0f4499c48d..850afd71a4 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -215,26 +215,34 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
}
}
-static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
- assert(node->type == NodeTypeArrayAccessExpr);
-
- AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
- TypeTableEntry *type_entry = get_expr_type(array_expr_node);
+static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
+ TypeTableEntry *type_entry = get_expr_type(node);
LLVMValueRef array_ptr;
- if (array_expr_node->type == NodeTypeFieldAccessExpr) {
- array_ptr = gen_field_access_expr(g, array_expr_node, true);
+ if (node->type == NodeTypeFieldAccessExpr) {
+ array_ptr = gen_field_access_expr(g, node, true);
if (type_entry->id == TypeTableEntryIdPointer) {
// we have a double pointer so we must dereference it once
add_debug_source_node(g, node);
array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
}
} else {
- array_ptr = gen_expr(g, array_expr_node);
+ array_ptr = gen_expr(g, node);
}
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
+ return array_ptr;
+}
+
+static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
+ assert(node->type == NodeTypeArrayAccessExpr);
+
+ AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
+ TypeTableEntry *type_entry = get_expr_type(array_expr_node);
+
+ LLVMValueRef array_ptr = gen_array_base_ptr(g, array_expr_node);
+
LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);
assert(subscript_value);
@@ -299,6 +307,48 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, "");
}
+static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
+ assert(node->type == NodeTypeSliceExpr);
+
+ AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
+ TypeTableEntry *array_type = get_expr_type(array_ref_node);
+
+ LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr;
+
+ if (array_type->id == TypeTableEntryIdArray) {
+ LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
+ LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
+ LLVMValueRef end_val;
+ if (node->data.slice_expr.end) {
+ end_val = gen_expr(g, node->data.slice_expr.end);
+ } else {
+ end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false);
+ }
+
+ add_debug_source_node(g, node);
+ LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
+ LLVMValueRef indices[] = {
+ LLVMConstNull(g->builtin_types.entry_usize->type_ref),
+ start_val,
+ };
+ LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
+ LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
+
+ LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
+ LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
+ LLVMBuildStore(g->builder, len_value, len_field_ptr);
+
+ return tmp_struct_ptr;
+ } else if (array_type->id == TypeTableEntryIdPointer) {
+ zig_panic("TODO gen_slice_expr pointer");
+ } else if (array_type->id == TypeTableEntryIdStruct) {
+ assert(array_type->data.structure.is_unknown_size_array);
+ zig_panic("TODO gen_slice_expr unknown size array");
+ } else {
+ zig_unreachable();
+ }
+}
+
static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
assert(node->type == NodeTypeArrayAccessExpr);
@@ -1443,6 +1493,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
return gen_fn_call_expr(g, node);
case NodeTypeArrayAccessExpr:
return gen_array_access_expr(g, node, false);
+ case NodeTypeSliceExpr:
+ return gen_slice_expr(g, node);
case NodeTypeFieldAccessExpr:
return gen_field_access_expr(g, node, false);
case NodeTypeUnreachable: