authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-09 06:01:28-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:47:30-05:00
log6d1fc0f51cf835e8ed503a2089450b1f280d1216
treee0a610b4c1a79a61264b9ae06f9786c6b9ca91bc
parent63730441d01a860a53d190e88079452947a4149d

x86_64: implement aggregate access


1 files changed, 67 insertions(+), 19 deletions(-)

src/arch/x86_64/CodeGen.zig+67-19
...@@ -2457,7 +2457,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2457,7 +2457,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2457 .load => try cg.airLoad(inst),2457 .load => try cg.airLoad(inst),
2458 .store => try cg.airStore(inst, false),2458 .store => try cg.airStore(inst, false),
2459 .store_safe => try cg.airStore(inst, true),2459 .store_safe => try cg.airStore(inst, true),
2460 .struct_field_val => try cg.airStructFieldVal(inst),
2461 .float_from_int => try cg.airFloatFromInt(inst),2460 .float_from_int => try cg.airFloatFromInt(inst),
2462 .int_from_float => try cg.airIntFromFloat(inst),2461 .int_from_float => try cg.airIntFromFloat(inst),
2463 .cmpxchg_strong => try cg.airCmpxchg(inst),2462 .cmpxchg_strong => try cg.airCmpxchg(inst),
...@@ -9723,11 +9722,32 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9723,11 +9722,32 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9723 ), cg);9722 ), cg);
9724 try ops[0].moveTo(inst, cg);9723 try ops[0].moveTo(inst, cg);
9725 },9724 },
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 },
9726 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {9745 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
9727 const bin_op = air_datas[@intFromEnum(inst)].bin_op;9746 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
9728 const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);9747 const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);
9729 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });9748 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9730 const union_layout = union_ty.unionGetLayout(zcu);9749 const union_layout = union_ty.unionGetLayout(zcu);
9750 // hack around Sema OPV bugs
9731 if (union_layout.tag_size > 0) try ops[0].store(@intCast(union_layout.tagOffset()), &ops[1], cg);9751 if (union_layout.tag_size > 0) try ops[0].store(@intCast(union_layout.tagOffset()), &ops[1], cg);
9732 for (ops) |op| try op.die(cg);9752 for (ops) |op| try op.die(cg);
9733 },9753 },
...@@ -9857,6 +9877,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9857,6 +9877,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9857 } },9877 } },
9858 } }) catch |err| switch (err) {9878 } }) catch |err| switch (err) {
9859 error.SelectFailed => switch (res_ty.abiSize(zcu)) {9879 error.SelectFailed => switch (res_ty.abiSize(zcu)) {
9880 // hack around Sema OPV bugs
9860 0 => res[0] = try cg.tempInit(res_ty, .none),9881 0 => res[0] = try cg.tempInit(res_ty, .none),
9861 else => |elem_size| {9882 else => |elem_size| {
9862 while (true) for (&ops) |*op| {9883 while (true) for (&ops) |*op| {
...@@ -9917,6 +9938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9917,6 +9938,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9917 const dst_ty = ty_pl.ty.toType();9938 const dst_ty = ty_pl.ty.toType();
9918 if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {9939 if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
9919 const elem_size = dst_ty.childType(zcu).abiSize(zcu);9940 const elem_size = dst_ty.childType(zcu).abiSize(zcu);
9941 // hack around Sema OPV bugs
9920 if (elem_size == 0) break :zero_offset;9942 if (elem_size == 0) break :zero_offset;
9921 while (true) for (&ops) |*op| {9943 while (true) for (&ops) |*op| {
9922 if (try op.toRegClass(true, .general_purpose, cg)) break;9944 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...@@ -15804,7 +15826,7 @@ fn fieldOffset(self: *CodeGen, ptr_agg_ty: Type, ptr_field_ty: Type, field_index
15804 return switch (agg_ty.containerLayout(zcu)) {15826 return switch (agg_ty.containerLayout(zcu)) {
15805 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),15827 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),
15806 .@"packed" => @divExact(@as(i32, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +15828 .@"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) -
15808 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),15830 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
15809 };15831 };
15810}15832}
...@@ -15828,8 +15850,8 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -15828,8 +15850,8 @@ fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void {
15828 const src_mcv = try self.resolveInst(operand);15850 const src_mcv = try self.resolveInst(operand);
15829 const field_off: u32 = switch (container_ty.containerLayout(zcu)) {15851 const field_off: u32 = switch (container_ty.containerLayout(zcu)) {
15830 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, zcu) * 8),15852 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, zcu) * 8),
15831 .@"packed" => if (zcu.typeToStruct(container_ty)) |struct_obj|15853 .@"packed" => if (zcu.typeToStruct(container_ty)) |loaded_struct|
15832 pt.structPackedFieldBitOffset(struct_obj, extra.field_index)15854 pt.structPackedFieldBitOffset(loaded_struct, extra.field_index)
15833 else15855 else
15834 0,15856 0,
15835 };15857 };
...@@ -26448,7 +26470,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -26448,7 +26470,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
26448 .@"struct" => {26470 .@"struct" => {
26449 const frame_index = try self.allocFrameIndex(.initSpill(result_ty, zcu));26471 const frame_index = try self.allocFrameIndex(.initSpill(result_ty, zcu));
26450 if (result_ty.containerLayout(zcu) == .@"packed") {26472 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());
26452 try self.genInlineMemset(26474 try self.genInlineMemset(
26453 .{ .lea_frame = .{ .index = frame_index } },26475 .{ .lea_frame = .{ .index = frame_index } },
26454 .{ .immediate = 0 },26476 .{ .immediate = 0 },
...@@ -26469,7 +26491,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -26469,7 +26491,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
26469 }26491 }
26470 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));26492 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));
26471 const elem_abi_bits = elem_abi_size * 8;26493 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);
26473 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);26495 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
26474 const elem_bit_off = elem_off % elem_abi_bits;26496 const elem_bit_off = elem_off % elem_abi_bits;
26475 const elem_mcv = try self.resolveInst(elem);26497 const elem_mcv = try self.resolveInst(elem);
...@@ -26651,9 +26673,9 @@ fn airUnionInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -26651,9 +26673,9 @@ fn airUnionInit(self: *CodeGen, inst: Air.Inst.Index) !void {
2665126673
26652 const dst_mcv = try self.allocRegOrMem(inst, false);26674 const dst_mcv = try self.allocRegOrMem(inst, false);
2665326675
26654 const union_obj = zcu.typeToUnion(union_ty).?;26676 const loaded_union = zcu.typeToUnion(union_ty).?;
26655 const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];26677 const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index];
26656 const tag_ty: Type = .fromInterned(union_obj.enum_tag_ty);26678 const tag_ty: Type = .fromInterned(loaded_union.enum_tag_ty);
26657 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;26679 const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
26658 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);26680 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
26659 const tag_int_val = try tag_val.intFromEnum(tag_ty, pt);26681 const tag_int_val = try tag_val.intFromEnum(tag_ty, pt);
...@@ -28393,17 +28415,43 @@ const Temp = struct {...@@ -28393,17 +28415,43 @@ const Temp = struct {
28393 }28415 }
2839428416
28395 fn read(src: *Temp, disp: i32, val_ty: Type, cg: *CodeGen) !Temp {28417 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);
28397 while (try src.toBase(cg)) {}28419 while (try src.toBase(cg)) {}
28398 const val_mcv = val.tracking(cg).short;28420 val_to_gpr: while (true) : (while (try val.toRegClass(false, .general_purpose, cg)) {}) {
28399 switch (val_mcv) {28421 const val_mcv = val.tracking(cg).short;
28400 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),28422 switch (val_mcv) {
28401 .register => |val_reg| try src.readReg(disp, val_ty, registerAlias(28423 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
28402 val_reg,28424 .register => |val_reg| try src.readReg(disp, val_ty, registerAlias(
28403 @intCast(val_ty.abiSize(cg.pt.zcu)),28425 val_reg,
28404 ), cg),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;
28405 }28454 }
28406 return val;
28407 }28455 }
2840828456
28409 fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void {28457 fn readReg(src: Temp, disp: i32, dst_ty: Type, dst_reg: Register, cg: *CodeGen) !void {
...@@ -28466,7 +28514,7 @@ const Temp = struct {...@@ -28466,7 +28514,7 @@ const Temp = struct {
28466 try len.die(cg);28514 try len.die(cg);
28467 },28515 },
28468 }28516 }
28469 break;28517 return;
28470 }28518 }
28471 }28519 }
2847228520