Commit 3ec74a1cd8

Jakub Konka <kubkon@jakubkonka.com>
2022-03-03 00:03:54
codegen: handle elem_ptr when lowering to memory
* x64: handle storing from-to non-stack memory
1 parent 1c8a86f
Changed files (3)
src
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -2599,6 +2599,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
             defer value.unfreezeIfRegister(&self.register_manager);
 
             const addr_reg = try self.register_manager.allocReg(null);
+            self.register_manager.freezeRegs(&.{addr_reg});
+            defer self.register_manager.unfreezeRegs(&.{addr_reg});
+
             try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr);
 
             // to get the actual address of the value we want to modify we have to go through the GOT
@@ -2662,6 +2665,40 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
                         .data = .{ .imm = 0 },
                     });
                 },
+                .got_load,
+                .direct_load,
+                .memory,
+                => {
+                    if (abi_size <= 8) {
+                        const tmp_reg = try self.register_manager.allocReg(null);
+                        self.register_manager.freezeRegs(&.{tmp_reg});
+                        defer self.register_manager.unfreezeRegs(&.{tmp_reg});
+
+                        try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value);
+
+                        _ = try self.addInst(.{
+                            .tag = .mov,
+                            .ops = (Mir.Ops{
+                                .reg1 = tmp_reg,
+                                .reg2 = tmp_reg,
+                                .flags = 0b01,
+                            }).encode(),
+                            .data = .{ .imm = 0 },
+                        });
+                        _ = try self.addInst(.{
+                            .tag = .mov,
+                            .ops = (Mir.Ops{
+                                .reg1 = addr_reg.to64(),
+                                .reg2 = tmp_reg,
+                                .flags = 0b10,
+                            }).encode(),
+                            .data = .{ .imm = 0 },
+                        });
+                        return;
+                    }
+
+                    try self.genInlineMemcpy(.{ .register = addr_reg.to64() }, value, .{ .immediate = abi_size }, .{});
+                },
                 else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}),
             }
         },
src/codegen.zig
@@ -392,6 +392,30 @@ pub fn generateSymbol(
                     },
                 }
             },
+            .elem_ptr => {
+                const elem_ptr = typed_value.val.castTag(.elem_ptr).?.data;
+                const elem_size = typed_value.ty.childType().abiSize(target);
+                const addend = @intCast(u32, elem_ptr.index * elem_size);
+                const array_ptr = elem_ptr.array_ptr;
+
+                switch (array_ptr.tag()) {
+                    .decl_ref => {
+                        const decl = array_ptr.castTag(.decl_ref).?.data;
+                        return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, .{
+                            .parent_atom_index = reloc_info.parent_atom_index,
+                            .addend = (reloc_info.addend orelse 0) + addend,
+                        });
+                    },
+                    else => return Result{
+                        .fail = try ErrorMsg.create(
+                            bin_file.allocator,
+                            src_loc,
+                            "TODO implement generateSymbol for pointer type value: '{s}'",
+                            .{@tagName(typed_value.val.tag())},
+                        ),
+                    },
+                }
+            },
             else => return Result{
                 .fail = try ErrorMsg.create(
                     bin_file.allocator,
test/behavior/array.zig
@@ -179,7 +179,6 @@ fn plusOne(x: u32) u32 {
 
 test "single-item pointer to array indexing and slicing" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 
     try testSingleItemPtrArrayIndexSlice();
@@ -206,7 +205,6 @@ fn doSomeMangling(array: *[4]u8) void {
 
 test "implicit cast zero sized array ptr to slice" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 
     {
@@ -244,7 +242,6 @@ const Str = struct { a: []Sub };
 test "set global var array via slice embedded in struct" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     var s = Str{ .a = s_array[0..] };
@@ -261,7 +258,6 @@ test "set global var array via slice embedded in struct" {
 test "read/write through global variable array of struct fields initialized via array mult" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     const S = struct {