mirror of
https://github.com/ziglang/zig.git
synced 2024-11-28 08:02:32 +00:00
Merge pull request #3955 from LemonBoy/fix-1528
Pointer arithmetic affects the alignment factor
This commit is contained in:
commit
5e345ff0ee
@ -1084,7 +1084,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
|
||||
std.macho.LC_SYMTAB => break @ptrCast(*std.macho.symtab_command, ptr),
|
||||
else => {},
|
||||
}
|
||||
ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403
|
||||
ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
|
||||
} else {
|
||||
return error.MissingDebugInfo;
|
||||
};
|
||||
@ -2129,7 +2129,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)),
|
||||
else => {},
|
||||
}
|
||||
ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403
|
||||
ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
|
||||
} else {
|
||||
return error.MissingDebugInfo;
|
||||
};
|
||||
|
@ -1263,7 +1263,7 @@ pub fn Watch(comptime V: type) type {
|
||||
var ptr = event_buf[0..].ptr;
|
||||
const end_ptr = ptr + event_buf.len;
|
||||
var ev: *os.linux.inotify_event = undefined;
|
||||
while (@ptrToInt(ptr) < @ptrToInt(end_ptr)) : (ptr += @sizeOf(os.linux.inotify_event) + ev.len) {
|
||||
while (@ptrToInt(ptr) < @ptrToInt(end_ptr)) {
|
||||
ev = @ptrCast(*os.linux.inotify_event, ptr);
|
||||
if (ev.mask & os.linux.IN_CLOSE_WRITE == os.linux.IN_CLOSE_WRITE) {
|
||||
const basename_ptr = ptr + @sizeOf(os.linux.inotify_event);
|
||||
@ -1287,6 +1287,8 @@ pub fn Watch(comptime V: type) type {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ptr = @alignCast(@alignOf(os.linux.inotify_event), ptr + @sizeOf(os.linux.inotify_event) + ev.len);
|
||||
}
|
||||
},
|
||||
os.linux.EINTR => continue,
|
||||
|
@ -142,14 +142,14 @@ fn posixCallMainAndExit() noreturn {
|
||||
const argc = starting_stack_ptr[0];
|
||||
const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
|
||||
|
||||
const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
|
||||
const envp_optional = @ptrCast([*:null]?[*:0]u8, @alignCast(@alignOf(usize), argv + argc + 1));
|
||||
var envp_count: usize = 0;
|
||||
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
|
||||
const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
|
||||
|
||||
if (builtin.os == .linux) {
|
||||
// Find the beginning of the auxiliary vector
|
||||
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
|
||||
const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));
|
||||
std.os.linux.elf_aux_maybe = auxv;
|
||||
// Initialize the TLS area
|
||||
const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
|
||||
|
50
src/ir.cpp
50
src/ir.cpp
@ -15783,19 +15783,51 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
return ir_const_undef(ira, &instruction->base, op1->value->type);
|
||||
}
|
||||
|
||||
ZigType *elem_type = op1->value->type->data.pointer.child_type;
|
||||
if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
// NOTE: this variable is meaningful iff op2_val is not null!
|
||||
uint64_t byte_offset;
|
||||
if (op2_val != nullptr) {
|
||||
uint64_t elem_offset;
|
||||
if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
|
||||
}
|
||||
|
||||
// Fast path for cases where the RHS is zero
|
||||
if (op2_val != nullptr && byte_offset == 0) {
|
||||
return op1;
|
||||
}
|
||||
|
||||
ZigType *result_type = op1->value->type;
|
||||
// Calculate the new alignment of the pointer
|
||||
{
|
||||
uint32_t align_bytes;
|
||||
if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
// If the addend is not a comptime-known value we can still count on
|
||||
// it being a multiple of the type size
|
||||
uint32_t addend = op2_val ? byte_offset : type_size(ira->codegen, elem_type);
|
||||
|
||||
// The resulting pointer is aligned to the lcd between the
|
||||
// offset (an arbitrary number) and the alignment factor (always
|
||||
// a power of two, non zero)
|
||||
uint32_t new_align = 1 << ctzll(addend | align_bytes);
|
||||
// Rough guard to prevent overflows
|
||||
assert(new_align);
|
||||
result_type = adjust_ptr_align(ira->codegen, result_type, new_align);
|
||||
}
|
||||
|
||||
if (op2_val != nullptr && op1_val != nullptr &&
|
||||
(op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
|
||||
op1->value->data.x_ptr.special == ConstPtrSpecialNull))
|
||||
{
|
||||
uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
|
||||
0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
|
||||
uint64_t elem_offset;
|
||||
if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
|
||||
return ira->codegen->invalid_instruction;
|
||||
ZigType *elem_type = op1_val->type->data.pointer.child_type;
|
||||
if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
|
||||
uint64_t new_addr;
|
||||
if (op_id == IrBinOpAdd) {
|
||||
new_addr = start_addr + byte_offset;
|
||||
@ -15804,7 +15836,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type);
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, result_type);
|
||||
result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
|
||||
result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar;
|
||||
result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr;
|
||||
@ -15813,7 +15845,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
|
||||
IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, op_id, op1, casted_op2, true);
|
||||
result->value->type = op1->value->type;
|
||||
result->value->type = result_type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -288,3 +288,33 @@ test "pointer to array at fixed address" {
|
||||
// Silly check just to reference `array`
|
||||
expect(@ptrToInt(&array[0]) == 0x10);
|
||||
}
|
||||
|
||||
test "pointer arithmetic affects the alignment" {
|
||||
{
|
||||
var ptr: [*]align(8) u32 = undefined;
|
||||
var x: usize = 1;
|
||||
|
||||
expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8);
|
||||
const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
|
||||
expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4);
|
||||
const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
|
||||
expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8);
|
||||
const ptr3 = ptr + 0; // no-op
|
||||
expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
|
||||
const ptr4 = ptr + x; // runtime-known addend
|
||||
expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
|
||||
}
|
||||
{
|
||||
var ptr: [*]align(8) [3]u8 = undefined;
|
||||
var x: usize = 1;
|
||||
|
||||
const ptr1 = ptr + 17; // 3 * 17 = 51
|
||||
expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
|
||||
const ptr2 = ptr + x; // runtime-known addend
|
||||
expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
|
||||
const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
|
||||
expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
|
||||
const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
|
||||
expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user