authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-23 13:58:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-23 13:58:30-07:00
log899fb14c30f34cea811bbf361124b15dc41eea71
tree78e32bfb606dd9bae9fba0865837a0bbc7eaa11f
parent55b28ab0301237b8c9e39db4160036a42544f836

fix handling of slice of zero bits type

closes #143

3 files changed, 125 insertions(+), 59 deletions(-)

src/analyze.cpp+84-46
...@@ -494,18 +494,6 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c...@@ -494,18 +494,6 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
494 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));494 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
495 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));495 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
496496
497 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
498
499 unsigned element_count = 2;
500 LLVMTypeRef element_types[] = {
501 pointer_type->type_ref,
502 g->builtin_types.entry_isize->type_ref,
503 };
504 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
505
506 slice_type_common_init(g, child_type, is_const, entry);
507
508
509 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);497 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
510 LLVMZigDIFile *di_file = nullptr;498 LLVMZigDIFile *di_file = nullptr;
511 unsigned line = 0;499 unsigned line = 0;
...@@ -513,40 +501,90 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c...@@ -513,40 +501,90 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
513 LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),501 LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),
514 compile_unit_scope, di_file, line);502 compile_unit_scope, di_file, line);
515503
516 uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);504 if (child_type->zero_bits) {
517 uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);505 LLVMTypeRef element_types[] = {
518 uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);506 g->builtin_types.entry_isize->type_ref,
519507 };
520 TypeTableEntry *isize_type = g->builtin_types.entry_isize;508 LLVMStructSetBody(entry->type_ref, element_types, 1, false);
521 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, isize_type->type_ref);509
522 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, isize_type->type_ref);510 slice_type_common_init(g, child_type, is_const, entry);
523 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);511
524512 entry->data.structure.gen_field_count = 1;
525 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);513 entry->data.structure.fields[0].gen_index = -1;
526 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);514 entry->data.structure.fields[1].gen_index = 0;
527515
528 LLVMZigDIType *di_element_types[] = {516 TypeTableEntry *isize_type = g->builtin_types.entry_isize;
529 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),517 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, isize_type->type_ref);
530 "ptr", di_file, line,518 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, isize_type->type_ref);
531 ptr_debug_size_in_bits,519 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
532 ptr_debug_align_in_bits,520
533 ptr_offset_in_bits,521 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
534 0, pointer_type->di_type),522 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
535 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),523
536 "len", di_file, line,524 LLVMZigDIType *di_element_types[] = {
537 len_debug_size_in_bits,525 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
538 len_debug_align_in_bits,526 "len", di_file, line,
539 len_offset_in_bits,527 len_debug_size_in_bits,
540 0, isize_type->di_type),528 len_debug_align_in_bits,
541 };529 len_offset_in_bits,
542 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,530 0, isize_type->di_type),
543 compile_unit_scope,531 };
544 buf_ptr(&entry->name),532 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
545 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,533 compile_unit_scope,
546 nullptr, di_element_types, 2, 0, nullptr, "");534 buf_ptr(&entry->name),
547535 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
548 LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);536 nullptr, di_element_types, 1, 0, nullptr, "");
549 entry->di_type = replacement_di_type;537
538 LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
539 entry->di_type = replacement_di_type;
540 } else {
541 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
542
543 unsigned element_count = 2;
544 LLVMTypeRef element_types[] = {
545 pointer_type->type_ref,
546 g->builtin_types.entry_isize->type_ref,
547 };
548 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
549
550 slice_type_common_init(g, child_type, is_const, entry);
551
552
553 uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref);
554 uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref);
555 uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0);
556
557 TypeTableEntry *isize_type = g->builtin_types.entry_isize;
558 uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, isize_type->type_ref);
559 uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, isize_type->type_ref);
560 uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1);
561
562 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
563 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
564
565 LLVMZigDIType *di_element_types[] = {
566 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
567 "ptr", di_file, line,
568 ptr_debug_size_in_bits,
569 ptr_debug_align_in_bits,
570 ptr_offset_in_bits,
571 0, pointer_type->di_type),
572 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
573 "len", di_file, line,
574 len_debug_size_in_bits,
575 len_debug_align_in_bits,
576 len_offset_in_bits,
577 0, isize_type->di_type),
578 };
579 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
580 compile_unit_scope,
581 buf_ptr(&entry->name),
582 di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
583 nullptr, di_element_types, 2, 0, nullptr, "");
584
585 LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
586 entry->di_type = replacement_di_type;
587 }
550588
551589
552 entry->data.structure.complete = true;590 entry->data.structure.complete = true;
src/codegen.cpp+33-13
...@@ -714,11 +714,15 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -714,11 +714,15 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
714714
715 add_debug_source_node(g, node);715 add_debug_source_node(g, node);
716716
717 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");717 int ptr_index = wanted_type->data.structure.fields[0].gen_index;
718 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");718 if (ptr_index >= 0) {
719 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);719 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, ptr_index, "");
720 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
721 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
722 }
720723
721 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");724 int len_index = wanted_type->data.structure.fields[1].gen_index;
725 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, len_index, "");
722 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref,726 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref,
723 actual_type->data.array.len, false);727 actual_type->data.array.len, false);
724 LLVMBuildStore(g->builder, len_val, len_ptr);728 LLVMBuildStore(g->builder, len_val, len_ptr);
...@@ -884,7 +888,9 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal...@@ -884,7 +888,9 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
884 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);888 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
885889
886 add_debug_source_node(g, source_node);890 add_debug_source_node(g, source_node);
887 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 0, "");891 int ptr_index = array_type->data.structure.fields[0].gen_index;
892 assert(ptr_index >= 0);
893 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
888 LLVMValueRef ptr = LLVMBuildLoad(g->builder, ptr_ptr, "");894 LLVMValueRef ptr = LLVMBuildLoad(g->builder, ptr_ptr, "");
889 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");895 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
890 } else {896 } else {
...@@ -1002,18 +1008,25 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1002,18 +1008,25 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1002 end_val = gen_expr(g, node->data.slice_expr.end);1008 end_val = gen_expr(g, node->data.slice_expr.end);
1003 } else {1009 } else {
1004 add_debug_source_node(g, node);1010 add_debug_source_node(g, node);
1005 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 1, "");1011 int len_index = array_type->data.structure.fields[1].gen_index;
1012 assert(len_index >= 0);
1013 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
1006 end_val = LLVMBuildLoad(g->builder, src_len_ptr, "");1014 end_val = LLVMBuildLoad(g->builder, src_len_ptr, "");
1007 }1015 }
10081016
1017 int ptr_index = array_type->data.structure.fields[0].gen_index;
1018 assert(ptr_index >= 0);
1019 int len_index = array_type->data.structure.fields[1].gen_index;
1020 assert(len_index >= 0);
1021
1009 add_debug_source_node(g, node);1022 add_debug_source_node(g, node);
1010 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, 0, "");1023 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
1011 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");1024 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
1012 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");1025 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");
1013 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");1026 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, len_index, "");
1014 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);1027 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
10151028
1016 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");1029 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, len_index, "");
1017 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");1030 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
1018 LLVMBuildStore(g->builder, len_value, len_field_ptr);1031 LLVMBuildStore(g->builder, len_value, len_field_ptr);
10191032
...@@ -2419,7 +2432,9 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {...@@ -2419,7 +2432,9 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
2419 TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;2432 TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
2420 assert(child_ptr_type->id == TypeTableEntryIdPointer);2433 assert(child_ptr_type->id == TypeTableEntryIdPointer);
2421 child_type = child_ptr_type->data.pointer.child_type;2434 child_type = child_ptr_type->data.pointer.child_type;
2422 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, 1, "");2435 int len_index = array_type->data.structure.fields[1].gen_index;
2436 assert(len_index >= 0);
2437 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
2423 len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");2438 len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
2424 } else {2439 } else {
2425 zig_unreachable();2440 zig_unreachable();
...@@ -2537,14 +2552,19 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa...@@ -2537,14 +2552,19 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
2537 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,2552 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
2538 size_val, "");2553 size_val, "");
25392554
2555 int ptr_index = var_type->data.structure.fields[0].gen_index;
2556 assert(ptr_index >= 0);
2557 int len_index = var_type->data.structure.fields[1].gen_index;
2558 assert(len_index >= 0);
2559
2540 // store the freshly allocated pointer in the unknown size array struct2560 // store the freshly allocated pointer in the unknown size array struct
2541 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,2561 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
2542 variable->value_ref, 0, "");2562 variable->value_ref, ptr_index, "");
2543 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);2563 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
25442564
2545 // store the size in the len field2565 // store the size in the len field
2546 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,2566 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
2547 variable->value_ref, 1, "");2567 variable->value_ref, len_index, "");
2548 LLVMBuildStore(g->builder, size_val, len_field_ptr);2568 LLVMBuildStore(g->builder, size_val, len_field_ptr);
25492569
2550 // don't clobber what we just did with debug initialization2570 // don't clobber what we just did with debug initialization
test/self_hosted.zig+8
...@@ -1314,3 +1314,11 @@ fn test_return_empty_struct_from_fn() -> EmptyStruct2 {...@@ -1314,3 +1314,11 @@ fn test_return_empty_struct_from_fn() -> EmptyStruct2 {
1314fn test_return_empty_struct_from_fn_noeval() -> EmptyStruct2 {1314fn test_return_empty_struct_from_fn_noeval() -> EmptyStruct2 {
1315 EmptyStruct2 {}1315 EmptyStruct2 {}
1316}1316}
1317
1318#attribute("test")
1319fn pass_slice_of_empty_struct_to_fn() {
1320 assert(test_pass_slice_of_empty_struct_to_fn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
1321}
1322fn test_pass_slice_of_empty_struct_to_fn(slice: []EmptyStruct2) -> isize {
1323 slice.len
1324}