Commit ef4c54ba38

mparadinha <miguel.p.paradinha@gmail.com>
2022-02-02 09:48:00
need to go through the GOT, and use a temporary register
1 parent b67b890
Changed files (1)
src
arch
src/arch/x86_64/CodeGen.zig
@@ -1781,18 +1781,70 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
             }
         },
         .memory => |addr| {
-            const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr });
+            // TODO: in case the address fits in an imm32 we can use [ds:imm32]
+            // instead of wasting an instruction copying the address to a register
+
+            const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr });
+            // to get the actual address of the value we want to modify we have to go through the GOT
             // mov reg, [reg]
             _ = try self.addInst(.{
                 .tag = .mov,
                 .ops = (Mir.Ops{
-                    .reg1 = reg.to64(),
-                    .reg2 = reg.to64(),
-                    .flags = 0b10,
+                    .reg1 = addr_reg.to64(),
+                    .reg2 = addr_reg.to64(),
+                    .flags = 0b01,
                 }).encode(),
                 .data = .{ .imm = 0 },
             });
-            return self.store(.{ .register = reg }, value, ptr_ty, value_ty);
+
+            const abi_size = value_ty.abiSize(self.target.*);
+            switch (value) {
+                .immediate => |imm| {
+                    const payload = try self.addExtra(Mir.ImmPair{
+                        .dest_off = 0,
+                        .operand = @intCast(u32, imm),
+                    });
+                    _ = try self.addInst(.{
+                        .tag = .mov_mem_imm,
+                        .ops = (Mir.Ops{
+                            .reg1 = addr_reg.to64(),
+                            .flags = switch (abi_size) {
+                                1 => 0b00,
+                                2 => 0b01,
+                                4 => 0b10,
+                                8 => flag: {
+                                    const top_bits: u32 = @intCast(u32, imm >> 32);
+                                    const can_extend = if (value_ty.isUnsignedInt())
+                                        (top_bits == 0) and (imm & 0x8000_0000) == 0
+                                    else
+                                        top_bits == 0xffff_ffff;
+
+                                    if (!can_extend) {
+                                        return self.fail("TODO imm64 would get incorrectly sign extended", .{});
+                                    }
+                                    break :flag 0b11;
+                                },
+                                else => {
+                                    return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size});
+                                },
+                            },
+                        }).encode(),
+                        .data = .{ .payload = payload },
+                    });
+                },
+                .register => |reg| {
+                    _ = try self.addInst(.{
+                        .tag = .mov,
+                        .ops = (Mir.Ops{
+                            .reg1 = addr_reg.to64(),
+                            .reg2 = reg,
+                            .flags = 0b10,
+                        }).encode(),
+                        .data = .{ .imm = 0 },
+                    });
+                },
+                else => return self.fail("TODO implement storing {} to MCValue.memory", .{value}),
+            }
         },
         .stack_offset => {
             return self.fail("TODO implement storing to MCValue.stack_offset", .{});