authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-12-20 10:48:03+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-08 20:03:03+01:00
loge134e6c994d6ecd76dc6ae1a24b8de29c4147eab
tree6c0b4e7a367fd0507d0f32e0de131a43d8b9e444
parent02ace4569ec52561f627ad3a33d7b90b7bdbb6f5

Pointer arithmetic affects the alignment factor

Closes #1528

3 files changed, 52 insertions(+), 11 deletions(-)

lib/std/start.zig+2-2
......@@ -142,14 +142,14 @@ fn posixCallMainAndExit() noreturn {
142142 const argc = starting_stack_ptr[0];
143143 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
144144
145 const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
145 const envp_optional = @ptrCast([*:null]?[*:0]u8, @alignCast(@alignOf(usize), argv + argc + 1));
146146 var envp_count: usize = 0;
147147 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
148148 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
149149
150150 if (builtin.os == .linux) {
151151 // Find the beginning of the auxiliary vector
152 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
152 const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));
153153 std.os.linux.elf_aux_maybe = auxv;
154154 // Initialize the TLS area
155155 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
src/ir.cpp+34-9
......@@ -15776,19 +15776,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1577615776 return ir_const_undef(ira, &instruction->base, op1->value->type);
1577715777 }
1577815778
15779 // NOTE: this variable is meaningful iff op2_val is not null!
15780 uint64_t byte_offset;
15781 if (op2_val != nullptr) {
15782 uint64_t elem_offset;
15783 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
15784 return ira->codegen->invalid_instruction;
15785
15786 ZigType *elem_type = op1->value->type->data.pointer.child_type;
15787 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
15788 return ira->codegen->invalid_instruction;
15789 byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
15790 }
15791
15792 // Fast path for cases where the RHS is zero
15793 if (op2_val != nullptr && byte_offset == 0) {
15794 return op1;
15795 }
15796
15797 ZigType *result_type = op1->value->type;
15798 // The resulting pointer may not be aligned anymore
15799 if (op2_val != nullptr) {
15800 uint32_t align_bytes;
15801 if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))
15802 return ira->codegen->invalid_instruction;
15803
15804 if (byte_offset != 0 && byte_offset % align_bytes != 0)
15805 result_type = adjust_ptr_align(ira->codegen, result_type, 1);
15806 } else {
15807 // The addend is not a comptime-known value
15808 result_type = adjust_ptr_align(ira->codegen, result_type, 1);
15809 }
15810
1577915811 if (op2_val != nullptr && op1_val != nullptr &&
1578015812 (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
1578115813 op1->value->data.x_ptr.special == ConstPtrSpecialNull))
1578215814 {
1578315815 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
1578415816 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
15785 uint64_t elem_offset;
15786 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
15787 return ira->codegen->invalid_instruction;
15788 ZigType *elem_type = op1_val->type->data.pointer.child_type;
15789 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
15790 return ira->codegen->invalid_instruction;
15791 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
1579215817 uint64_t new_addr;
1579315818 if (op_id == IrBinOpAdd) {
1579415819 new_addr = start_addr + byte_offset;
......@@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1579715822 } else {
1579815823 zig_unreachable();
1579915824 }
15800 IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type);
15825 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
1580115826 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
1580215827 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
1580315828 result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr;
......@@ -15806,7 +15831,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1580615831
1580715832 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
1580815833 instruction->base.source_node, op_id, op1, casted_op2, true);
15809 result->value->type = op1->value->type;
15834 result->value->type = result_type;
1581015835 return result;
1581115836 }
1581215837
test/stage1/behavior/pointers.zig+16
......@@ -288,3 +288,19 @@ test "pointer to array at fixed address" {
288288 // Silly check just to reference `array`
289289 expect(@ptrToInt(&array[0]) == 0x10);
290290}
291
292test "pointer arithmetic affects the alignment" {
293 var arr: [10]u8 align(2) = undefined;
294 var x: usize = 1;
295
296 const ptr = @as([*]u8, &arr);
297 expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 2);
298 const ptr1 = ptr + 1;
299 expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
300 const ptr2 = ptr + 4;
301 expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 2);
302 const ptr3 = ptr + 0;
303 expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 2);
304 const ptr4 = ptr + x;
305 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 1);
306}