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 {...@@ -142,14 +142,14 @@ fn posixCallMainAndExit() noreturn {
142 const argc = starting_stack_ptr[0];142 const argc = starting_stack_ptr[0];
143 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);143 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));
146 var envp_count: usize = 0;146 var envp_count: usize = 0;
147 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}147 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
148 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];148 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
149149
150 if (builtin.os == .linux) {150 if (builtin.os == .linux) {
151 // Find the beginning of the auxiliary vector151 // 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));
153 std.os.linux.elf_aux_maybe = auxv;153 std.os.linux.elf_aux_maybe = auxv;
154 // Initialize the TLS area154 // Initialize the TLS area
155 const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");155 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...@@ -15776,19 +15776,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15776 return ir_const_undef(ira, &instruction->base, op1->value->type);15776 return ir_const_undef(ira, &instruction->base, op1->value->type);
15777 }15777 }
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
15779 if (op2_val != nullptr && op1_val != nullptr &&15811 if (op2_val != nullptr && op1_val != nullptr &&
15780 (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||15812 (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
15781 op1->value->data.x_ptr.special == ConstPtrSpecialNull))15813 op1->value->data.x_ptr.special == ConstPtrSpecialNull))
15782 {15814 {
15783 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?15815 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
15784 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;15816 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;
15792 uint64_t new_addr;15817 uint64_t new_addr;
15793 if (op_id == IrBinOpAdd) {15818 if (op_id == IrBinOpAdd) {
15794 new_addr = start_addr + byte_offset;15819 new_addr = start_addr + byte_offset;
...@@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15797 } else {15822 } else {
15798 zig_unreachable();15823 zig_unreachable();
15799 }15824 }
15800 IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type);15825 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
15801 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;15826 result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
15802 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;15827 result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
15803 result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr;15828 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...@@ -15806,7 +15831,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1580615831
15807 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,15832 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
15808 instruction->base.source_node, op_id, op1, casted_op2, true);15833 instruction->base.source_node, op_id, op1, casted_op2, true);
15809 result->value->type = op1->value->type;15834 result->value->type = result_type;
15810 return result;15835 return result;
15811 }15836 }
1581215837
test/stage1/behavior/pointers.zig+16
...@@ -288,3 +288,19 @@ test "pointer to array at fixed address" {...@@ -288,3 +288,19 @@ test "pointer to array at fixed address" {
288 // Silly check just to reference `array`288 // Silly check just to reference `array`
289 expect(@ptrToInt(&array[0]) == 0x10);289 expect(@ptrToInt(&array[0]) == 0x10);
290}290}
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}