authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-07 15:29:14+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-07 20:10:01+01:00
log0a7801236cf3601ff20b3c1c16cd27c1d089157e
tree43236dc3015e8b9712a4e802a0b0c3f0c4bdeb51
parent9acf06d28ac77a52028697dc01f42fd96c230ca9

stage2,arm: add lowering of unnamed consts

* implement `struct_field_ptr` when `MCValue == .stack_argument_offset` * enable simple `struct` test for ARM

2 files changed, 47 insertions(+), 5 deletions(-)

src/arch/arm/CodeGen.zig+45-1
......@@ -1643,7 +1643,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
16431643fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
16441644 return if (self.liveness.isUnused(inst)) .dead else result: {
16451645 const mcv = try self.resolveInst(operand);
1646 const struct_ty = self.air.typeOf(operand).childType();
1646 const ptr_ty = self.air.typeOf(operand);
1647 const struct_ty = ptr_ty.childType();
16471648 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
16481649 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
16491650 const struct_field_ty = struct_ty.structFieldType(index);
......@@ -1652,6 +1653,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
16521653 .ptr_stack_offset => |off| {
16531654 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
16541655 },
1656 .stack_argument_offset => {
1657 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
1658 .immediate = struct_field_offset,
1659 });
1660 self.register_manager.freezeRegs(&.{offset_reg});
1661 defer self.register_manager.unfreezeRegs(&.{offset_reg});
1662
1663 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);
1664 self.register_manager.freezeRegs(&.{addr_reg});
1665 defer self.register_manager.unfreezeRegs(&.{addr_reg});
1666
1667 const dst_reg = try self.register_manager.allocReg(inst);
1668 try self.genBinOpCode(
1669 dst_reg,
1670 .{ .register = addr_reg },
1671 .{ .register = offset_reg },
1672 false,
1673 .add,
1674 .unsigned,
1675 );
1676 break :result MCValue{ .register = dst_reg };
1677 },
16551678 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
16561679 }
16571680 };
......@@ -3841,6 +3864,24 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
38413864 _ = tv;
38423865}
38433866
3867fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
3868 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
3869 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
3870 };
3871 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3872 const vaddr = elf_file.local_symbols.items[local_sym_index].st_value;
3873 return MCValue{ .memory = vaddr };
3874 } else if (self.bin_file.cast(link.File.MachO)) |_| {
3875 unreachable;
3876 } else if (self.bin_file.cast(link.File.Coff)) |_| {
3877 return self.fail("TODO lower unnamed const in COFF", .{});
3878 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
3879 return self.fail("TODO lower unnamed const in Plan9", .{});
3880 } else {
3881 return self.fail("TODO lower unnamed const", .{});
3882 }
3883}
3884
38443885fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
38453886 if (typed_value.val.isUndef())
38463887 return MCValue{ .undef = {} };
......@@ -3953,6 +3994,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
39533994 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});
39543995 }
39553996 },
3997 .Struct => {
3998 return self.lowerUnnamedConst(typed_value);
3999 },
39564000 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),
39574001 }
39584002}
test/behavior/struct.zig+2-4
......@@ -53,20 +53,18 @@ test "non-packed struct has fields padded out to the required alignment" {
5353
5454const SmallStruct = struct {
5555 a: u8,
56 b: u32,
56 b: u8,
5757
5858 fn first(self: *SmallStruct) u8 {
5959 return self.a;
6060 }
6161
62 fn second(self: *SmallStruct) u32 {
62 fn second(self: *SmallStruct) u8 {
6363 return self.b;
6464 }
6565};
6666
6767test "lower unnamed constants" {
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
69
7068 var foo = SmallStruct{ .a = 1, .b = 255 };
7169 try expect(foo.first() == 1);
7270 try expect(foo.second() == 255);