authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-15 14:07:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-15 14:09:08-04:00
logb738cbdc768796b59b19a07a29a95892937d6f11
treee3e1088d9a45786655aa5c6e9938d458a5f0faa8
parent3f05fdc8e8fdc25faec2ca51547404411b314ce1

fix compiler crash involving slice with const slice child

also fix compiler crash for multiple errors in main fn prototype closes #191

4 files changed, 163 insertions(+), 84 deletions(-)

src/analyze.cpp+110-84
......@@ -558,100 +558,125 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
558558 } else {
559559 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
560560
561 // If the child type is []const T then we need to make sure the type ref
562 // and debug info is the same as if the child type were []T.
563 if (is_slice(child_type)) {
564 TypeTableEntry *ptr_type = child_type->data.structure.fields[0].type_entry;
565 assert(ptr_type->id == TypeTableEntryIdPointer);
566 if (ptr_type->data.pointer.is_const) {
567 TypeTableEntry *non_const_child_type = get_slice_type(g,
568 ptr_type->data.pointer.child_type, false);
569 TypeTableEntry *var_peer = get_slice_type(g, non_const_child_type, false);
570
571 entry->type_ref = var_peer->type_ref;
572 entry->di_type = var_peer->di_type;
573 }
574 }
575
561576 buf_resize(&entry->name, 0);
562577 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
563 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
564
565 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
566 ZigLLVMDIFile *di_file = nullptr;
567 unsigned line = 0;
568 entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
569 ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
570 compile_unit_scope, di_file, line);
571578
579 slice_type_common_init(g, child_type, is_const, entry);
572580 if (child_type->zero_bits) {
573 LLVMTypeRef element_types[] = {
574 g->builtin_types.entry_usize->type_ref,
575 };
576 LLVMStructSetBody(entry->type_ref, element_types, 1, false);
577
578 slice_type_common_init(g, child_type, is_const, entry);
579
580581 entry->data.structure.gen_field_count = 1;
581582 entry->data.structure.fields[0].gen_index = -1;
582583 entry->data.structure.fields[1].gen_index = 0;
584 }
583585
584 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
585 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
586 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
587 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
588
589 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
590 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
591
592 ZigLLVMDIType *di_element_types[] = {
593 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
594 "len", di_file, line,
595 len_debug_size_in_bits,
596 len_debug_align_in_bits,
597 len_offset_in_bits,
598 0, usize_type->di_type),
599 };
600 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
601 compile_unit_scope,
602 buf_ptr(&entry->name),
603 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
604 nullptr, di_element_types, 1, 0, nullptr, "");
605
606 ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
607 entry->di_type = replacement_di_type;
608 } else {
609 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
610
611 unsigned element_count = 2;
612 LLVMTypeRef element_types[] = {
613 pointer_type->type_ref,
614 g->builtin_types.entry_usize->type_ref,
615 };
616 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
617
618 slice_type_common_init(g, child_type, is_const, entry);
619
620
621 uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);
622 uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);
623 uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
624
625 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
626 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
627 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
628 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
629
630 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
631 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
586 if (!entry->type_ref) {
587 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
632588
633 ZigLLVMDIType *di_element_types[] = {
634 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
635 "ptr", di_file, line,
636 ptr_debug_size_in_bits,
637 ptr_debug_align_in_bits,
638 ptr_offset_in_bits,
639 0, pointer_type->di_type),
640 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
641 "len", di_file, line,
642 len_debug_size_in_bits,
643 len_debug_align_in_bits,
644 len_offset_in_bits,
645 0, usize_type->di_type),
646 };
647 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
648 compile_unit_scope,
649 buf_ptr(&entry->name),
650 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
651 nullptr, di_element_types, 2, 0, nullptr, "");
589 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
590 ZigLLVMDIFile *di_file = nullptr;
591 unsigned line = 0;
592 entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
593 ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
594 compile_unit_scope, di_file, line);
652595
653 ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
654 entry->di_type = replacement_di_type;
596 if (child_type->zero_bits) {
597 LLVMTypeRef element_types[] = {
598 g->builtin_types.entry_usize->type_ref,
599 };
600 LLVMStructSetBody(entry->type_ref, element_types, 1, false);
601
602 slice_type_common_init(g, child_type, is_const, entry);
603
604 entry->data.structure.gen_field_count = 1;
605 entry->data.structure.fields[0].gen_index = -1;
606 entry->data.structure.fields[1].gen_index = 0;
607
608 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
609 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
610 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
611 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
612
613 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
614 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
615
616 ZigLLVMDIType *di_element_types[] = {
617 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
618 "len", di_file, line,
619 len_debug_size_in_bits,
620 len_debug_align_in_bits,
621 len_offset_in_bits,
622 0, usize_type->di_type),
623 };
624 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
625 compile_unit_scope,
626 buf_ptr(&entry->name),
627 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
628 nullptr, di_element_types, 1, 0, nullptr, "");
629
630 ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
631 entry->di_type = replacement_di_type;
632 } else {
633 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
634
635 unsigned element_count = 2;
636 LLVMTypeRef element_types[] = {
637 pointer_type->type_ref,
638 g->builtin_types.entry_usize->type_ref,
639 };
640 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
641
642 slice_type_common_init(g, child_type, is_const, entry);
643
644
645 uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);
646 uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);
647 uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
648
649 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
650 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref);
651 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref);
652 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
653
654 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
655 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
656
657 ZigLLVMDIType *di_element_types[] = {
658 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
659 "ptr", di_file, line,
660 ptr_debug_size_in_bits,
661 ptr_debug_align_in_bits,
662 ptr_offset_in_bits,
663 0, pointer_type->di_type),
664 ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type),
665 "len", di_file, line,
666 len_debug_size_in_bits,
667 len_debug_align_in_bits,
668 len_offset_in_bits,
669 0, usize_type->di_type),
670 };
671 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
672 compile_unit_scope,
673 buf_ptr(&entry->name),
674 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
675 nullptr, di_element_types, 2, 0, nullptr, "");
676
677 ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
678 entry->di_type = replacement_di_type;
679 }
655680 }
656681
657682
......@@ -1695,6 +1720,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
16951720
16961721 bool is_main_fn = !is_generic_instance &&
16971722 !parent_decl && (import == g->root_import) &&
1723 !proto_node->data.fn_proto.skip &&
16981724 buf_eql_str(proto_name, "main");
16991725 if (is_main_fn) {
17001726 g->main_fn = fn_table_entry;
test/cases/const_slice_child.zig created+48
......@@ -0,0 +1,48 @@
1const assert = @import("std").debug.assert;
2
3var argv: &&const u8 = undefined;
4
5#attribute("test")
6fn constSliceChild() {
7 const strs = ([]&const u8) {
8 c"one",
9 c"two",
10 c"three",
11 };
12 argv = &strs[0];
13 bar(strs.len);
14}
15
16#static_eval_enable(false)
17fn foo(args: [][]const u8) {
18 assert(args.len == 3);
19 assert(streql(args[0], "one"));
20 assert(streql(args[1], "two"));
21 assert(streql(args[2], "three"));
22}
23
24#static_eval_enable(false)
25fn bar(argc: usize) {
26 var args: [argc][]u8 = undefined;
27 for (args) |_, i| {
28 const ptr = argv[i];
29 args[i] = ptr[0...strlen(ptr)];
30 }
31 foo(args);
32}
33
34#static_eval_enable(false)
35fn strlen(ptr: &const u8) -> usize {
36 var count: usize = 0;
37 while (ptr[count] != 0; count += 1) {}
38 return count;
39}
40
41#static_eval_enable(false)
42fn streql(a: []const u8, b: []const u8) -> bool {
43 if (a.len != b.len) return false;
44 for (a) |item, index| {
45 if (b[index] != item) return false;
46 }
47 return true;
48}
test/run_tests.cpp+4
......@@ -1491,6 +1491,10 @@ pub fn f() {
14911491 cstr[0] = 'W';
14921492}
14931493 )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant");
1494
1495 add_compile_fail_case("main function with bogus args type", R"SOURCE(
1496pub fn main(args: [][]bogus) -> %void {}
1497 )SOURCE", 1, ".tmp_source.zig:2:23: error: use of undeclared identifier 'bogus'");
14941498}
14951499
14961500//////////////////////////////////////////////////////////////////////////////
test/self_hosted.zig+1
......@@ -10,6 +10,7 @@ const test_sizeof_and_typeof = @import("cases/sizeof_and_typeof.zig");
1010const test_maybe_return = @import("cases/maybe_return.zig");
1111const test_max_value_type = @import("cases/max_value_type.zig");
1212const test_var_params = @import("cases/var_params.zig");
13const test_const_slice_child = @import("cases/const_slice_child.zig");
1314
1415// normal comment
1516/// this is a documentation comment