authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-17 19:45:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-19 09:53:54-04:00
log2b4134459d468812ac106c124ee6fa5f5e8b9574
treeb25a3da862251ca353cdf3c8272dd498ffeb5ef9
parent8ea0a00f406bb04c08a8fa4471c3a3895f82b24a
signaturelock-open Commit is signed but in an unrecognized format.

fix alignment when slicing with comptime start and end index


2 files changed, 54 insertions(+), 27 deletions(-)

src/ir.cpp+53-26
...@@ -20575,6 +20575,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_...@@ -20575,6 +20575,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_
20575 allow_zero);20575 allow_zero);
20576}20576}
2057720577
20578static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
20579 uint64_t elem_index, uint32_t *result)
20580{
20581 Error err;
20582
20583 if (base_ptr_align == 0) {
20584 *result = 0;
20585 return ErrorNone;
20586 }
20587
20588 // figure out the largest alignment possible
20589 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
20590 return err;
20591
20592 uint64_t elem_size = type_size(ira->codegen, elem_type);
20593 uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type);
20594 uint64_t ptr_align = base_ptr_align;
20595
20596 uint64_t chosen_align = abi_align;
20597 if (ptr_align >= abi_align) {
20598 while (ptr_align > abi_align) {
20599 if ((elem_index * elem_size) % ptr_align == 0) {
20600 chosen_align = ptr_align;
20601 break;
20602 }
20603 ptr_align >>= 1;
20604 }
20605 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20606 chosen_align = ptr_align;
20607 } else {
20608 // can't get here because guaranteed elem_size >= abi_align
20609 zig_unreachable();
20610 }
20611
20612 *result = chosen_align;
20613 return ErrorNone;
20614}
20615
20578static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) {20616static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) {
20579 Error err;20617 Error err;
20580 IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child;20618 IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child;
...@@ -20713,29 +20751,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20713,29 +20751,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20713 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,20751 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
20714 nullptr, nullptr);20752 nullptr, nullptr);
20715 } else if (return_type->data.pointer.explicit_alignment != 0) {20753 } else if (return_type->data.pointer.explicit_alignment != 0) {
20716 // figure out the largest alignment possible20754 uint32_t chosen_align;
2071720755 if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
20718 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))20756 return_type->data.pointer.explicit_alignment, index, &chosen_align)))
20757 {
20719 return ira->codegen->invalid_inst_gen;20758 return ira->codegen->invalid_inst_gen;
20720
20721 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
20722 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
20723 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
20724
20725 uint64_t chosen_align = abi_align;
20726 if (ptr_align >= abi_align) {
20727 while (ptr_align > abi_align) {
20728 if ((index * elem_size) % ptr_align == 0) {
20729 chosen_align = ptr_align;
20730 break;
20731 }
20732 ptr_align >>= 1;
20733 }
20734 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20735 chosen_align = ptr_align;
20736 } else {
20737 // can't get here because guaranteed elem_size >= abi_align
20738 zig_unreachable();
20739 }20759 }
20740 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);20760 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);
20741 }20761 }
...@@ -26172,6 +26192,8 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy...@@ -26172,6 +26192,8 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
26172}26192}
2617326193
26174static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) {26194static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) {
26195 Error err;
26196
26175 IrInstGen *ptr_ptr = instruction->ptr->child;26197 IrInstGen *ptr_ptr = instruction->ptr->child;
26176 if (type_is_invalid(ptr_ptr->value->type))26198 if (type_is_invalid(ptr_ptr->value->type))
26177 return ira->codegen->invalid_inst_gen;26199 return ira->codegen->invalid_inst_gen;
...@@ -26307,10 +26329,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26307,10 +26329,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26307 return ira->codegen->invalid_inst_gen;26329 return ira->codegen->invalid_inst_gen;
26308 }26330 }
2630926331
26310 // TODO in the case of non-zero start index, the byte alignment should be smarter here.26332 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;
26311 // we should be able to use the same logic as indexing.26333 uint32_t ptr_byte_alignment = 0;
26312 uint32_t ptr_byte_alignment = ((end_scalar - start_scalar != 0) && start_scalar == 0) ?26334 if (end_scalar > start_scalar) {
26313 non_sentinel_slice_ptr_type->data.pointer.explicit_alignment : 0;26335 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))
26336 return ira->codegen->invalid_inst_gen;
26337 }
26338
26314 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,26339 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
26315 array_sentinel);26340 array_sentinel);
26316 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,26341 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
...@@ -26318,9 +26343,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26318,9 +26343,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26318 non_sentinel_slice_ptr_type->data.pointer.is_volatile,26343 non_sentinel_slice_ptr_type->data.pointer.is_volatile,
26319 PtrLenSingle, ptr_byte_alignment, 0, 0, false);26344 PtrLenSingle, ptr_byte_alignment, 0, 0, false);
26320 } else if (sentinel_val != nullptr) {26345 } else if (sentinel_val != nullptr) {
26346 // TODO deal with non-abi-alignment here
26321 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);26347 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);
26322 return_type = get_slice_type(ira->codegen, slice_ptr_type);26348 return_type = get_slice_type(ira->codegen, slice_ptr_type);
26323 } else {26349 } else {
26350 // TODO deal with non-abi-alignment here
26324 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);26351 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);
26325 }26352 }
2632626353
test/stage1/behavior/slice.zig+1-1
...@@ -10,7 +10,7 @@ test "compile time slice of pointer to hard coded address" {...@@ -10,7 +10,7 @@ test "compile time slice of pointer to hard coded address" {
10 expect(@ptrToInt(x) == 0x1000);10 expect(@ptrToInt(x) == 0x1000);
11 expect(x.len == 0x500);11 expect(x.len == 0x500);
1212
13 expect(@ptrToInt(y.ptr) == 0x1100);13 expect(@ptrToInt(y) == 0x1100);
14 expect(y.len == 0x400);14 expect(y.len == 0x400);
15}15}
1616