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 {...@@ -1643,7 +1643,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
1643fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {1643fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
1644 return if (self.liveness.isUnused(inst)) .dead else result: {1644 return if (self.liveness.isUnused(inst)) .dead else result: {
1645 const mcv = try self.resolveInst(operand);1645 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();
1647 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));1648 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
1648 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));1649 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1649 const struct_field_ty = struct_ty.structFieldType(index);1650 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...@@ -1652,6 +1653,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
1652 .ptr_stack_offset => |off| {1653 .ptr_stack_offset => |off| {
1653 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };1654 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1654 },1655 },
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 },
1655 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),1678 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
1656 }1679 }
1657 };1680 };
...@@ -3841,6 +3864,24 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa...@@ -3841,6 +3864,24 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
3841 _ = tv;3864 _ = tv;
3842}3865}
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
3844fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {3885fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3845 if (typed_value.val.isUndef())3886 if (typed_value.val.isUndef())
3846 return MCValue{ .undef = {} };3887 return MCValue{ .undef = {} };
...@@ -3953,6 +3994,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3953,6 +3994,9 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3953 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});3994 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});
3954 }3995 }
3955 },3996 },
3997 .Struct => {
3998 return self.lowerUnnamedConst(typed_value);
3999 },
3956 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),4000 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty}),
3957 }4001 }
3958}4002}
test/behavior/struct.zig+2-4
...@@ -53,20 +53,18 @@ test "non-packed struct has fields padded out to the required alignment" {...@@ -53,20 +53,18 @@ test "non-packed struct has fields padded out to the required alignment" {
5353
54const SmallStruct = struct {54const SmallStruct = struct {
55 a: u8,55 a: u8,
56 b: u32,56 b: u8,
5757
58 fn first(self: *SmallStruct) u8 {58 fn first(self: *SmallStruct) u8 {
59 return self.a;59 return self.a;
60 }60 }
6161
62 fn second(self: *SmallStruct) u32 {62 fn second(self: *SmallStruct) u8 {
63 return self.b;63 return self.b;
64 }64 }
65};65};
6666
67test "lower unnamed constants" {67test "lower unnamed constants" {
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
69
70 var foo = SmallStruct{ .a = 1, .b = 255 };68 var foo = SmallStruct{ .a = 1, .b = 255 };
71 try expect(foo.first() == 1);69 try expect(foo.first() == 1);
72 try expect(foo.second() == 255);70 try expect(foo.second() == 255);