authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-18 19:07:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-19 09:53:55-04:00
log2164b511cce235ec4a49de99452e4900835bfba8
tree69f5d5f45c0da78d1b2767651a7e4ed6af08bd4a
parent8688c437455d8e8f1f031177375e570022c16ce7
signaturelock-open Commit is signed but in an unrecognized format.

partial revert of an improvement this branch made

because it uncovered a result location bug, and I need to get this branch merged before going into a result location rabbit hole. also fix the result type of slicing when the indexes are runtime known and the result should be sentinel terminated.

3 files changed, 79 insertions(+), 51 deletions(-)

src/ir.cpp+66-45
...@@ -12693,34 +12693,50 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc...@@ -12693,34 +12693,50 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc
12693 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);12693 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
1269412694
12695 ZigType *array_type = array_ptr->value->type->data.pointer.child_type;12695 ZigType *array_type = array_ptr->value->type->data.pointer.child_type;
12696 const size_t array_len = array_type->data.array.len;12696 size_t array_len = array_type->data.array.len;
1269712697
12698 // A zero-sized array can be casted regardless of the destination alignment, or12698 // A zero-sized array can be casted regardless of the destination alignment, or
12699 // whether the pointer is undefined, and the result is always comptime known.12699 // whether the pointer is undefined, and the result is always comptime known.
12700 if (array_len == 0) {12700 // TODO However, this is exposing a result location bug that I failed to solve on the first try.
12701 ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();12701 // If you want to try to fix the bug, uncomment this block and get the tests passing.
12702 undef_array->special = ConstValSpecialUndef;12702 //if (array_len == 0 && array_type->data.array.sentinel == nullptr) {
12703 undef_array->type = array_type;12703 // ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
1270412704 // undef_array->special = ConstValSpecialUndef;
12705 IrInstGen *result = ir_const(ira, source_instr, wanted_type);12705 // undef_array->type = array_type;
12706 init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);12706
12707 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;12707 // IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12708 result->value->type = wanted_type;12708 // init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12709 return result;12709 // result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
12710 }12710 // result->value->type = wanted_type;
12711 // return result;
12712 //}
1271112713
12712 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {12714 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
12713 return ira->codegen->invalid_inst_gen;12715 return ira->codegen->invalid_inst_gen;
12714 }12716 }
1271512717
12716 wanted_type = adjust_slice_align(ira->codegen, wanted_type,12718 if (array_len != 0) {
12717 get_ptr_align(ira->codegen, array_ptr->value->type));12719 wanted_type = adjust_slice_align(ira->codegen, wanted_type,
12720 get_ptr_align(ira->codegen, array_ptr->value->type));
12721 }
1271812722
12719 if (instr_is_comptime(array_ptr)) {12723 if (instr_is_comptime(array_ptr)) {
12720 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);12724 UndefAllowed undef_allowed = (array_len == 0) ? UndefOk : UndefBad;
12725 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, undef_allowed);
12721 if (array_ptr_val == nullptr)12726 if (array_ptr_val == nullptr)
12722 return ira->codegen->invalid_inst_gen;12727 return ira->codegen->invalid_inst_gen;
12723 ir_assert(is_slice(wanted_type), source_instr);12728 ir_assert(is_slice(wanted_type), source_instr);
12729 if (array_ptr_val->special == ConstValSpecialUndef) {
12730 ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
12731 undef_array->special = ConstValSpecialUndef;
12732 undef_array->type = array_type;
12733
12734 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12735 init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12736 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
12737 result->value->type = wanted_type;
12738 return result;
12739 }
12724 bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;12740 bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
12725 // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee12741 // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee
12726 if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {12742 if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {
...@@ -26314,18 +26330,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26314,18 +26330,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26314 // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these26330 // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these
26315 // values by making the return type a slice.26331 // values by making the return type a slice.
26316 ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc);26332 ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc);
2631726333 bool result_loc_is_slice = (res_loc_type != nullptr && is_slice(res_loc_type));
26318 if ((res_loc_type == nullptr || !is_slice(res_loc_type)) &&26334 bool end_is_known = !result_loc_is_slice &&
26319 value_is_comptime(casted_start->value) &&
26320 ((end != nullptr && value_is_comptime(end->value)) ||26335 ((end != nullptr && value_is_comptime(end->value)) ||
26321 (end == nullptr && child_array_type->id == ZigTypeIdArray)))26336 (end == nullptr && child_array_type->id == ZigTypeIdArray));
26322 {
26323 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
26324 if (!start_val)
26325 return ira->codegen->invalid_inst_gen;
26326
26327 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
2632826337
26338 ZigValue *array_sentinel = sentinel_val;
26339 if (end_is_known) {
26329 uint64_t end_scalar;26340 uint64_t end_scalar;
26330 if (end != nullptr) {26341 if (end != nullptr) {
26331 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);26342 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
...@@ -26335,36 +26346,46 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26335,36 +26346,46 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26335 } else {26346 } else {
26336 end_scalar = child_array_type->data.array.len;26347 end_scalar = child_array_type->data.array.len;
26337 }26348 }
26338 ZigValue *array_sentinel = (child_array_type->id == ZigTypeIdArray &&26349 array_sentinel = (child_array_type->id == ZigTypeIdArray && end_scalar == child_array_type->data.array.len)
26339 end_scalar == child_array_type->data.array.len)26350 ? child_array_type->data.array.sentinel : sentinel_val;
26340 ? child_array_type->data.array.sentinel : nullptr;
2634126351
26342 if (start_scalar > end_scalar) {26352 if (value_is_comptime(casted_start->value)) {
26343 ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice"));26353 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
26344 return ira->codegen->invalid_inst_gen;26354 if (!start_val)
26345 }26355 return ira->codegen->invalid_inst_gen;
2634626356
26347 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;26357 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
26348 uint32_t ptr_byte_alignment = 0;26358
26349 if (end_scalar > start_scalar) {26359 if (start_scalar > end_scalar) {
26350 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))26360 ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice"));
26351 return ira->codegen->invalid_inst_gen;26361 return ira->codegen->invalid_inst_gen;
26352 }26362 }
26363
26364 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;
26365 uint32_t ptr_byte_alignment = 0;
26366 if (end_scalar > start_scalar) {
26367 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))
26368 return ira->codegen->invalid_inst_gen;
26369 }
2635326370
26354 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,26371 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
26355 array_sentinel);26372 array_sentinel);
26356 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,26373 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
26357 non_sentinel_slice_ptr_type->data.pointer.is_const,26374 non_sentinel_slice_ptr_type->data.pointer.is_const,
26358 non_sentinel_slice_ptr_type->data.pointer.is_volatile,26375 non_sentinel_slice_ptr_type->data.pointer.is_volatile,
26359 PtrLenSingle, ptr_byte_alignment, 0, 0, false);26376 PtrLenSingle, ptr_byte_alignment, 0, 0, false);
26360 } else if (sentinel_val != nullptr) {26377 goto done_with_return_type;
26378 }
26379 }
26380 if (array_sentinel != nullptr) {
26361 // TODO deal with non-abi-alignment here26381 // TODO deal with non-abi-alignment here
26362 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);26382 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, array_sentinel);
26363 return_type = get_slice_type(ira->codegen, slice_ptr_type);26383 return_type = get_slice_type(ira->codegen, slice_ptr_type);
26364 } else {26384 } else {
26365 // TODO deal with non-abi-alignment here26385 // TODO deal with non-abi-alignment here
26366 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);26386 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);
26367 }26387 }
26388done_with_return_type:
2636826389
26369 if (instr_is_comptime(ptr_ptr) &&26390 if (instr_is_comptime(ptr_ptr) &&
26370 value_is_comptime(casted_start->value) &&26391 value_is_comptime(casted_start->value) &&
test/stage1/behavior/align.zig+11-4
...@@ -5,10 +5,17 @@ const builtin = @import("builtin");...@@ -5,10 +5,17 @@ const builtin = @import("builtin");
5var foo: u8 align(4) = 100;5var foo: u8 align(4) = 100;
66
7test "global variable alignment" {7test "global variable alignment" {
8 expect(@TypeOf(&foo).alignment == 4);8 comptime expect(@TypeOf(&foo).alignment == 4);
9 expect(@TypeOf(&foo) == *align(4) u8);9 comptime expect(@TypeOf(&foo) == *align(4) u8);
10 const slice = @as(*[1]u8, &foo)[0..];10 {
11 expect(@TypeOf(slice) == []align(4) u8);11 const slice = @as(*[1]u8, &foo)[0..];
12 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
13 }
14 {
15 var runtime_zero: usize = 0;
16 const slice = @as(*[1]u8, &foo)[runtime_zero..];
17 comptime expect(@TypeOf(slice) == []align(4) u8);
18 }
12}19}
1320
14fn derp() align(@sizeOf(usize) * 2) i32 {21fn derp() align(@sizeOf(usize) * 2) i32 {
test/stage1/behavior/misc.zig+2-2
...@@ -572,9 +572,9 @@ test "slice string literal has correct type" {...@@ -572,9 +572,9 @@ test "slice string literal has correct type" {
572 expect(@TypeOf(array[0..]) == *const [4]i32);572 expect(@TypeOf(array[0..]) == *const [4]i32);
573 }573 }
574 var runtime_zero: usize = 0;574 var runtime_zero: usize = 0;
575 expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);575 comptime expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
576 const array = [_]i32{ 1, 2, 3, 4 };576 const array = [_]i32{ 1, 2, 3, 4 };
577 expect(@TypeOf(array[runtime_zero..]) == []const u8);577 comptime expect(@TypeOf(array[runtime_zero..]) == []const i32);
578}578}
579579
580test "pointer child field" {580test "pointer child field" {