authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-19 22:38:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-19 22:38:02-05:00
logd686113bd2b2e2207137de6ef81e515bc4a3aa07
treeb39a465aa6ea298a4e6226e3cafb028d35807d61
parent1cc450e6e70008eb2eaf62f2992d9d3e8b3ab87a

fix crash when implicitly casting array of len 0 to slice

closes #660

3 files changed, 31 insertions(+), 8 deletions(-)

src/codegen.cpp+12
...@@ -2722,6 +2722,9 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru...@@ -2722,6 +2722,9 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
2722}2722}
27232723
2724static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {2724static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {
2725 if (!type_has_bits(instruction->base.value.type)) {
2726 return nullptr;
2727 }
2725 LLVMValueRef value = ir_llvm_value(g, instruction->value);2728 LLVMValueRef value = ir_llvm_value(g, instruction->value);
2726 if (handle_is_ptr(instruction->value->value.type)) {2729 if (handle_is_ptr(instruction->value->value.type)) {
2727 return value;2730 return value;
...@@ -3013,6 +3016,15 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst...@@ -3013,6 +3016,15 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
3013 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);3016 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
3014 }3017 }
3015 }3018 }
3019 if (!type_has_bits(array_type)) {
3020 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
3021
3022 // TODO if debug safety is on, store 0xaaaaaaa in ptr field
3023 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
3024 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
3025 return tmp_struct_ptr;
3026 }
3027
30163028
3017 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");3029 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
3018 LLVMValueRef indices[] = {3030 LLVMValueRef indices[] = {
src/ir.cpp+10-8
...@@ -7748,8 +7748,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7748,8 +7748,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7748static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *type_entry) {7748static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *type_entry) {
7749 if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {7749 if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {
7750 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);7750 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
7751 assert(fn_entry);7751 if (fn_entry != nullptr) {
7752 fn_entry->alloca_list.append(instruction);7752 fn_entry->alloca_list.append(instruction);
7753 }
7753 }7754 }
7754}7755}
77557756
...@@ -7851,9 +7852,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -7851,9 +7852,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
7851 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);7852 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);
7852 result->value.type = wanted_type;7853 result->value.type = wanted_type;
7853 if (need_alloca) {7854 if (need_alloca) {
7854 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);7855 ir_add_alloca(ira, result, wanted_type);
7855 if (fn_entry)
7856 fn_entry->alloca_list.append(result);
7857 }7856 }
7858 return result;7857 return result;
7859 }7858 }
...@@ -8287,6 +8286,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_...@@ -8287,6 +8286,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
8287 assert(fn_entry);8286 assert(fn_entry);
8288 fn_entry->alloca_list.append(new_instruction);8287 fn_entry->alloca_list.append(new_instruction);
8289 }8288 }
8289 ir_add_alloca(ira, new_instruction, child_type);
8290 return new_instruction;8290 return new_instruction;
8291 }8291 }
8292}8292}
...@@ -8330,13 +8330,15 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -8330,13 +8330,15 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
83308330
8331 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,8331 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
8332 is_const, is_volatile, get_abi_alignment(ira->codegen, value->value.type), 0, 0);8332 is_const, is_volatile, get_abi_alignment(ira->codegen, value->value.type), 0, 0);
8333 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
8334 assert(fn_entry);
8335 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,8333 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
8336 source_instruction->source_node, value, is_const, is_volatile);8334 source_instruction->source_node, value, is_const, is_volatile);
8337 new_instruction->value.type = ptr_type;8335 new_instruction->value.type = ptr_type;
8338 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;8336 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
8339 fn_entry->alloca_list.append(new_instruction);8337 if (type_has_bits(ptr_type)) {
8338 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
8339 assert(fn_entry);
8340 fn_entry->alloca_list.append(new_instruction);
8341 }
8340 return new_instruction;8342 return new_instruction;
8341}8343}
83428344
test/cases/slice.zig+9
...@@ -25,3 +25,12 @@ test "debug safety lets us slice from len..len" {...@@ -25,3 +25,12 @@ test "debug safety lets us slice from len..len" {
25fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) -> []u8 {25fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) -> []u8 {
26 return a_slice[start..end];26 return a_slice[start..end];
27}27}
28
29test "implicitly cast array of size 0 to slice" {
30 var msg = []u8 {};
31 assertLenIsZero(msg);
32}
33
34fn assertLenIsZero(msg: []const u8) {
35 assert(msg.len == 0);
36}