Skip to content

Commit 6d1fc0f

Browse files
committed
x86_64: implement aggregate access
1 parent 6373044 commit 6d1fc0f

File tree

1 file changed

+67
-19
lines changed

1 file changed

+67
-19
lines changed

src/arch/x86_64/CodeGen.zig

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24572457
.load => try cg.airLoad(inst),
24582458
.store => try cg.airStore(inst, false),
24592459
.store_safe => try cg.airStore(inst, true),
2460-
.struct_field_val => try cg.airStructFieldVal(inst),
24612460
.float_from_int => try cg.airFloatFromInt(inst),
24622461
.int_from_float => try cg.airIntFromFloat(inst),
24632462
.cmpxchg_strong => try cg.airCmpxchg(inst),
@@ -9723,11 +9722,32 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
97239722
), cg);
97249723
try ops[0].moveTo(inst, cg);
97259724
},
9725+
.struct_field_val => if (use_old) try cg.airStructFieldVal(inst) else fallback: {
9726+
const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
9727+
const extra = cg.air.extraData(Air.StructField, ty_pl.payload).data;
9728+
const agg_ty = cg.typeOf(extra.struct_operand);
9729+
const field_ty = ty_pl.ty.toType();
9730+
const field_off: u31 = switch (agg_ty.containerLayout(zcu)) {
9731+
.auto, .@"extern" => @intCast(agg_ty.structFieldOffset(extra.field_index, zcu)),
9732+
.@"packed" => break :fallback try cg.airStructFieldVal(inst),
9733+
};
9734+
if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
9735+
var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand});
9736+
var res = try ops[0].read(field_off, field_ty, cg);
9737+
for (ops) |op| if (op.index != res.index) try op.die(cg);
9738+
try res.moveTo(inst, cg);
9739+
} else {
9740+
// hack around Sema OPV bugs
9741+
const res = try cg.tempInit(field_ty, .none);
9742+
try res.moveTo(inst, cg);
9743+
}
9744+
},
97269745
.set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
97279746
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
97289747
const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);
97299748
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
97309749
const union_layout = union_ty.unionGetLayout(zcu);
9750+
// hack around Sema OPV bugs
97319751
if (union_layout.tag_size > 0) try ops[0].store(@intCast(union_layout.tagOffset()), &ops[1], cg);
97329752
for (ops) |op| try op.die(cg);
97339753
},
@@ -9857,6 +9877,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
98579877
} },
98589878
} }) catch |err| switch (err) {
98599879
error.SelectFailed => switch (res_ty.abiSize(zcu)) {
9880+
// hack around Sema OPV bugs
98609881
0 => res[0] = try cg.tempInit(res_ty, .none),
98619882
else => |elem_size| {
98629883
while (true) for (&ops) |*op| {
@@ -9917,6 +9938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
99179938
const dst_ty = ty_pl.ty.toType();
99189939
if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
99199940
const elem_size = dst_ty.childType(zcu).abiSize(zcu);
9941+
// hack around Sema OPV bugs
99209942
if (elem_size == 0) break :zero_offset;
99219943
while (true) for (&ops) |*op| {
99229944
if (try op.toRegClass(true, .general_purpose, cg)) break;
@@ -15804,7 +15826,7 @@ fn fieldOffset(self: *CodeGen, ptr_agg_ty: Type, ptr_field_ty: Type, field_index
1580415826
return switch (agg_ty.containerLayout(zcu)) {
1580515827
.auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),
1580615828
.@"packed" => @divExact(@as(i32, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +
15807-
(if (zcu.typeToStruct(agg_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, field_index) else 0) -
15829+
(if (zcu.typeToStruct(agg_ty)) |loaded_struct| pt.structPackedFieldBitOffset(loaded_struct, field_index) else 0) -
1580815830
ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
1580915831
};
1581015832
}
@@ -15828,8 +15850,8 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
1582815850
const src_mcv = try self.resolveInst(operand);
1582915851
const field_off: u32 = switch (container_ty.containerLayout(zcu)) {
1583015852
.auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, zcu) * 8),
15831-
.@"packed" => if (zcu.typeToStruct(container_ty)) |struct_obj|
15832-
pt.structPackedFieldBitOffset(struct_obj, extra.field_index)
15853+
.@"packed" => if (zcu.typeToStruct(container_ty)) |loaded_struct|
15854+
pt.structPackedFieldBitOffset(loaded_struct, extra.field_index)
1583315855
else
1583415856
0,
1583515857
};
@@ -26448,7 +26470,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
2644826470
.@"struct" => {
2644926471
const frame_index = try self.allocFrameIndex(.initSpill(result_ty, zcu));
2645026472
if (result_ty.containerLayout(zcu) == .@"packed") {
26451-
const struct_obj = zcu.typeToStruct(result_ty).?;
26473+
const loaded_struct = zcu.intern_pool.loadStructType(result_ty.toIntern());
2645226474
try self.genInlineMemset(
2645326475
.{ .lea_frame = .{ .index = frame_index } },
2645426476
.{ .immediate = 0 },
@@ -26469,7 +26491,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
2646926491
}
2647026492
const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));
2647126493
const elem_abi_bits = elem_abi_size * 8;
26472-
const elem_off = pt.structPackedFieldBitOffset(struct_obj, elem_i);
26494+
const elem_off = pt.structPackedFieldBitOffset(loaded_struct, elem_i);
2647326495
const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
2647426496
const elem_bit_off = elem_off % elem_abi_bits;
2647526497
const elem_mcv = try self.resolveInst(elem);
@@ -26651,9 +26673,9 @@ fn airUnionInit(self: *CodeGen, inst: Air.Inst.Index) !void {
2665126673

2665226674
const dst_mcv = try self.allocRegOrMem(inst, false);
2665326675

26654-
const union_obj = zcu.typeToUnion(union_ty).?;
26655-
const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
26656-
const tag_ty: Type = .fromInterned(union_obj.enum_tag_ty);
26676+
const loaded_union = zcu.typeToUnion(union_ty).?;
26677+
const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index];
26678+
const tag_ty: Type = .fromInterned(loaded_union.enum_tag_ty);
2665726679
const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
2665826680
const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
2665926681
const tag_int_val = try tag_val.intFromEnum(tag_ty, pt);
@@ -28393,17 +28415,43 @@ const Temp = struct {
2839328415
}
2839428416

2839528417
fn read(src: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp {
28396-
const val = try cg.tempAlloc(val_ty);
28418+
var val = try cg.tempAlloc(val_ty);
2839728419
while (try src.toBase(cg)) {}
28398-
const val_mcv = val.tracking(cg).short;
28399-
switch (val_mcv) {
28400-
else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28401-
.register => |val_reg| try src.readReg(disp, val_ty, registerAlias(
28402-
val_reg,
28403-
@intCast(val_ty.abiSize(cg.pt.zcu)),
28404-
), cg),
28420+
val_to_gpr: while (true) : (while (try val.toRegClass(false, .general_purpose, cg)) {}) {
28421+
const val_mcv = val.tracking(cg).short;
28422+
switch (val_mcv) {
28423+
else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28424+
.register => |val_reg| try src.readReg(disp, val_ty, registerAlias(
28425+
val_reg,
28426+
@intCast(val_ty.abiSize(cg.pt.zcu)),
28427+
), cg),
28428+
inline .register_pair, .register_triple, .register_quadruple => |val_regs| {
28429+
var part_disp = disp;
28430+
for (val_regs) |val_reg| {
28431+
try src.readReg(disp, val_ty, val_reg, cg);
28432+
part_disp += @divExact(val_reg.bitSize(), 8);
28433+
}
28434+
},
28435+
.register_offset => |val_reg_off| switch (val_reg_off.off) {
28436+
0 => try src.readReg(disp, val_ty, registerAlias(
28437+
val_reg_off.reg,
28438+
@intCast(val_ty.abiSize(cg.pt.zcu)),
28439+
), cg),
28440+
else => continue :val_to_gpr,
28441+
},
28442+
.lea_frame, .lea_symbol => continue :val_to_gpr,
28443+
.memory, .indirect, .load_frame, .load_symbol => {
28444+
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
28445+
var src_ptr = try cg.tempInit(.usize, src.tracking(cg).short.address().offset(disp));
28446+
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
28447+
try val_ptr.memcpy(&src_ptr, &len, cg);
28448+
try val_ptr.die(cg);
28449+
try src_ptr.die(cg);
28450+
try len.die(cg);
28451+
},
28452+
}
28453+
return val;
2840528454
}
28406-
return val;
2840728455
}
2840828456

2840928457
fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void {
@@ -28466,7 +28514,7 @@ const Temp = struct {
2846628514
try len.die(cg);
2846728515
},
2846828516
}
28469-
break;
28517+
return;
2847028518
}
2847128519
}
2847228520

0 commit comments

Comments
 (0)