zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 2b4134459d468812ac106c124ee6fa5f5e8b9574 (tree)
parent 8ea0a00f406bb04c08a8fa4471c3a3895f82b24a
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Tue, 17 Mar 2020 19:45:59 -0400

fix alignment when slicing with comptime start and end index

Diffstat:
Msrc/ir.cpp | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mtest/stage1/behavior/slice.zig | 2+-
2 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -20575,6 +20575,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_ allow_zero); } +static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align, + uint64_t elem_index, uint32_t *result) +{ + Error err; + + if (base_ptr_align == 0) { + *result = 0; + return ErrorNone; + } + + // figure out the largest alignment possible + if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) + return err; + + uint64_t elem_size = type_size(ira->codegen, elem_type); + uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type); + uint64_t ptr_align = base_ptr_align; + + uint64_t chosen_align = abi_align; + if (ptr_align >= abi_align) { + while (ptr_align > abi_align) { + if ((elem_index * elem_size) % ptr_align == 0) { + chosen_align = ptr_align; + break; + } + ptr_align >>= 1; + } + } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) { + chosen_align = ptr_align; + } else { + // can't get here because guaranteed elem_size >= abi_align + zig_unreachable(); + } + + *result = chosen_align; + return ErrorNone; +} + static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) { Error err; IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child; @@ -20713,29 +20751,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index, nullptr, nullptr); } else if (return_type->data.pointer.explicit_alignment != 0) { - // figure out the largest alignment possible - - if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) + uint32_t chosen_align; + if ((err = compute_elem_align(ira, return_type->data.pointer.child_type, + return_type->data.pointer.explicit_alignment, index, &chosen_align))) + { return ira->codegen->invalid_inst_gen; - - uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); - uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); - uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); - - uint64_t chosen_align = abi_align; - if (ptr_align >= abi_align) { - while (ptr_align > abi_align) { - if ((index * elem_size) % ptr_align == 0) { - chosen_align = ptr_align; - break; - } - ptr_align >>= 1; - } - } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) { - chosen_align = ptr_align; - } else { - // can't get here because guaranteed elem_size >= abi_align - zig_unreachable(); } return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align); } @@ -26172,6 +26192,8 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy } static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) { + Error err; + IrInstGen *ptr_ptr = instruction->ptr->child; if (type_is_invalid(ptr_ptr->value->type)) return ira->codegen->invalid_inst_gen; @@ -26307,10 +26329,13 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i return ira->codegen->invalid_inst_gen; } - // TODO in the case of non-zero start index, the byte alignment should be smarter here. - // we should be able to use the same logic as indexing. - uint32_t ptr_byte_alignment = ((end_scalar - start_scalar != 0) && start_scalar == 0) ? - non_sentinel_slice_ptr_type->data.pointer.explicit_alignment : 0; + uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment; + uint32_t ptr_byte_alignment = 0; + if (end_scalar > start_scalar) { + if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment))) + return ira->codegen->invalid_inst_gen; + } + ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, array_sentinel); 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 non_sentinel_slice_ptr_type->data.pointer.is_volatile, PtrLenSingle, ptr_byte_alignment, 0, 0, false); } else if (sentinel_val != nullptr) { + // TODO deal with non-abi-alignment here ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); return_type = get_slice_type(ira->codegen, slice_ptr_type); } else { + // TODO deal with non-abi-alignment here return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type); } diff --git a/test/stage1/behavior/slice.zig b/test/stage1/behavior/slice.zig @@ -10,7 +10,7 @@ test "compile time slice of pointer to hard coded address" { expect(@ptrToInt(x) == 0x1000); expect(x.len == 0x500); - expect(@ptrToInt(y.ptr) == 0x1100); + expect(@ptrToInt(y) == 0x1100); expect(y.len == 0x400); }