Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/arch/wasm/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3090,12 +3090,19 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
return func.lowerParentPtr(elem.base.toValue(), @as(u32, @intCast(elem_offset + offset)));
},
.field => |field| {
const parent_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
const parent_ptr_ty = mod.intern_pool.typeOf(field.base).toType();
const parent_ty = parent_ptr_ty.childType(mod);
const field_index: u32 = @intCast(field.index);

const field_offset = switch (parent_ty.zigTypeTag(mod)) {
.Struct => switch (parent_ty.containerLayout(mod)) {
.Packed => parent_ty.packedStructFieldByteOffset(@as(usize, @intCast(field.index)), mod),
else => parent_ty.structFieldOffset(@as(usize, @intCast(field.index)), mod),
.Struct => blk: {
if (mod.typeToPackedStruct(parent_ty)) |struct_type| {
if (ptr.ty.toType().ptrInfo(mod).packed_offset.host_size == 0)
break :blk @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + parent_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8)
else
break :blk 0;
}
break :blk parent_ty.structFieldOffset(field_index, mod);
},
.Union => switch (parent_ty.containerLayout(mod)) {
.Packed => 0,
Expand Down Expand Up @@ -3821,7 +3828,8 @@ fn structFieldPtr(
if (result_ty.ptrInfo(mod).packed_offset.host_size != 0) {
break :offset @as(u32, 0);
}
break :offset struct_ty.packedStructFieldByteOffset(index, mod) + @divExact(struct_ptr_ty_info.packed_offset.bit_offset, 8);
const struct_type = mod.typeToStruct(struct_ty).?;
break :offset @divExact(mod.structPackedFieldBitOffset(struct_type, index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);
},
.Union => 0,
else => unreachable,
Expand Down
17 changes: 9 additions & 8 deletions src/arch/x86_64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5774,14 +5774,15 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
const ptr_container_ty_info = ptr_container_ty.ptrInfo(mod);
const container_ty = ptr_container_ty.childType(mod);

const field_offset: i32 = @intCast(switch (container_ty.containerLayout(mod)) {
.Auto, .Extern => container_ty.structFieldOffset(index, mod),
.Packed => if (container_ty.zigTypeTag(mod) == .Struct and
ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0)
container_ty.packedStructFieldByteOffset(index, mod) + @divExact(ptr_container_ty_info.packed_offset.bit_offset, 8)
else
0,
});
const field_offset: i32 = blk: {
if (mod.typeToPackedStruct(container_ty)) |struct_type| {
break :blk if (ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0)
@divExact(mod.structPackedFieldBitOffset(struct_type, index) + ptr_container_ty_info.packed_offset.bit_offset, 8)
else
0;
}
break :blk @intCast(container_ty.structFieldOffset(index, mod));
};

const src_mcv = try self.resolveInst(operand);
const dst_mcv = if (switch (src_mcv) {
Expand Down
20 changes: 12 additions & 8 deletions src/codegen/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5269,22 +5269,26 @@ fn fieldLocation(
const ip = &mod.intern_pool;
const container_ty = container_ptr_ty.childType(mod);
return switch (container_ty.zigTypeTag(mod)) {
.Struct => switch (container_ty.containerLayout(mod)) {
.Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| {
.Struct => blk: {
if (mod.typeToPackedStruct(container_ty)) |struct_type| {
if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0)
break :blk .{ .byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) }
else
break :blk .begin;
}

for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| {
const next_field_index: u32 = @intCast(next_field_index_usize);
if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
const field_ty = container_ty.structFieldType(next_field_index, mod);
if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;

break .{ .field = if (container_ty.isSimpleTuple(mod))
break :blk .{ .field = if (container_ty.isSimpleTuple(mod))
.{ .field = next_field_index }
else
.{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } };
} else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
.Packed => if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0)
.{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) + @divExact(container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) }
else
.begin,
}
break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin;
},
.Union => {
const union_obj = mod.typeToUnion(container_ty).?;
Expand Down
45 changes: 19 additions & 26 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const log = std.log.scoped(.codegen);
const math = std.math;
const native_endian = builtin.cpu.arch.endian();
const DW = std.dwarf;

const Builder = @import("llvm/Builder.zig");
Expand Down Expand Up @@ -3770,7 +3769,7 @@ pub const Object = struct {
.opt_payload,
.elem,
.field,
=> try o.lowerParentPtr(val, ty.ptrInfo(mod).packed_offset.bit_offset % 8 == 0),
=> try o.lowerParentPtr(val),
.comptime_field => unreachable,
};
switch (ptr.len) {
Expand Down Expand Up @@ -4230,15 +4229,16 @@ pub const Object = struct {
return o.lowerDeclRefValue(ptr_ty, decl_index);
}

fn lowerParentPtr(o: *Object, ptr_val: Value, byte_aligned: bool) Allocator.Error!Builder.Constant {
fn lowerParentPtr(o: *Object, ptr_val: Value) Allocator.Error!Builder.Constant {
const mod = o.module;
const ip = &mod.intern_pool;
return switch (ip.indexToKey(ptr_val.toIntern()).ptr.addr) {
const ptr = ip.indexToKey(ptr_val.toIntern()).ptr;
return switch (ptr.addr) {
.decl => |decl| o.lowerParentPtrDecl(decl),
.mut_decl => |mut_decl| o.lowerParentPtrDecl(mut_decl.decl),
.int => |int| try o.lowerIntAsPtr(int),
.eu_payload => |eu_ptr| {
const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue(), true);
const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());

const eu_ty = ip.typeOf(eu_ptr).toType().childType(mod);
const payload_ty = eu_ty.errorUnionPayload(mod);
Expand All @@ -4256,7 +4256,7 @@ pub const Object = struct {
});
},
.opt_payload => |opt_ptr| {
const parent_ptr = try o.lowerParentPtr(opt_ptr.toValue(), true);
const parent_ptr = try o.lowerParentPtr(opt_ptr.toValue());

const opt_ty = ip.typeOf(opt_ptr).toType().childType(mod);
const payload_ty = opt_ty.optionalChild(mod);
Expand All @@ -4274,17 +4274,17 @@ pub const Object = struct {
},
.comptime_field => unreachable,
.elem => |elem_ptr| {
const parent_ptr = try o.lowerParentPtr(elem_ptr.base.toValue(), true);
const parent_ptr = try o.lowerParentPtr(elem_ptr.base.toValue());
const elem_ty = ip.typeOf(elem_ptr.base).toType().elemType2(mod);

return o.builder.gepConst(.inbounds, try o.lowerType(elem_ty), parent_ptr, null, &.{
try o.builder.intConst(try o.lowerType(Type.usize), elem_ptr.index),
});
},
.field => |field_ptr| {
const parent_ptr = try o.lowerParentPtr(field_ptr.base.toValue(), byte_aligned);
const parent_ty = ip.typeOf(field_ptr.base).toType().childType(mod);

const parent_ptr = try o.lowerParentPtr(field_ptr.base.toValue());
const parent_ptr_ty = ip.typeOf(field_ptr.base).toType();
const parent_ty = parent_ptr_ty.childType(mod);
const field_index: u32 = @intCast(field_ptr.index);
switch (parent_ty.zigTypeTag(mod)) {
.Union => {
Expand All @@ -4309,22 +4309,14 @@ pub const Object = struct {
},
.Struct => {
if (mod.typeToPackedStruct(parent_ty)) |struct_type| {
if (!byte_aligned) return parent_ptr;
const ptr_info = ptr.ty.toType().ptrInfo(mod);
if (ptr_info.packed_offset.host_size != 0) return parent_ptr;

const parent_ptr_info = parent_ptr_ty.ptrInfo(mod);
const bit_offset = mod.structPackedFieldBitOffset(struct_type, field_index) + parent_ptr_info.packed_offset.bit_offset;
const llvm_usize = try o.lowerType(Type.usize);
const base_addr =
try o.builder.castConst(.ptrtoint, parent_ptr, llvm_usize);
// count bits of fields before this one
// TODO https://github.com/ziglang/zig/issues/17178
const prev_bits = b: {
var b: usize = 0;
for (0..field_index) |i| {
const field_ty = struct_type.field_types.get(ip)[i].toType();
if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
b += @intCast(field_ty.bitSize(mod));
}
break :b b;
};
const byte_offset = try o.builder.intConst(llvm_usize, prev_bits / 8);
const base_addr = try o.builder.castConst(.ptrtoint, parent_ptr, llvm_usize);
const byte_offset = try o.builder.intConst(llvm_usize, @divExact(bit_offset, 8));
const field_addr = try o.builder.binConst(.add, base_addr, byte_offset);
return o.builder.castConst(.inttoptr, field_addr, .ptr);
}
Expand Down Expand Up @@ -10148,6 +10140,7 @@ pub const FuncGen = struct {
const result_ty = self.typeOfIndex(inst);
const result_ty_info = result_ty.ptrInfo(mod);
const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod);
const struct_type = mod.typeToStruct(struct_ty).?;

if (result_ty_info.packed_offset.host_size != 0) {
// From LLVM's perspective, a pointer to a packed struct and a pointer
Expand All @@ -10159,7 +10152,7 @@ pub const FuncGen = struct {

// We have a pointer to a packed struct field that happens to be byte-aligned.
// Offset our operand pointer by the correct number of bytes.
const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod) + @divExact(struct_ptr_ty_info.packed_offset.bit_offset, 8);
const byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);
if (byte_offset == 0) return struct_ptr;
const usize_ty = try o.lowerType(Type.usize);
const llvm_index = try o.builder.intValue(usize_ty, byte_offset);
Expand Down
20 changes: 0 additions & 20 deletions src/type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3028,26 +3028,6 @@ pub const Type = struct {
};
}

pub fn packedStructFieldBitOffset(ty: Type, field_index: usize, mod: *Module) u32 {
const ip = &mod.intern_pool;
const struct_type = ip.indexToKey(ty.toIntern()).struct_type;
assert(struct_type.layout == .Packed);
comptime assert(Type.packed_struct_layout_version == 2);

var running_bits: u32 = 0;
for (struct_type.field_types.get(ip), 0..) |field_ty, i| {
if (i == field_index) break;
if (!field_ty.toType().hasRuntimeBits(mod)) continue;
const field_bits: u32 = @intCast(field_ty.toType().bitSize(mod));
running_bits += field_bits;
}
return running_bits;
}

pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
return packedStructFieldBitOffset(ty, field_index, mod) / 8;
}

pub const FieldOffset = struct {
field: usize,
offset: u64,
Expand Down
Loading