| ... | @@ -1260,7 +1260,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1260,7 +1260,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1260 | const dst_mcv: MCValue = blk: { | 1260 | const dst_mcv: MCValue = blk: { |
| 1261 | switch (operand) { | 1261 | switch (operand) { |
| 1262 | .stack_offset => |off| { | 1262 | .stack_offset => |off| { |
| 1263 | break :blk MCValue{ .stack_offset = off }; | 1263 | break :blk MCValue{ .stack_offset = off + 8 }; |
| 1264 | }, | 1264 | }, |
| 1265 | else => return self.fail("TODO implement slice_ptr for {}", .{operand}), | 1265 | else => return self.fail("TODO implement slice_ptr for {}", .{operand}), |
| 1266 | } | 1266 | } |
| ... | @@ -1277,7 +1277,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1277,7 +1277,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1277 | const dst_mcv: MCValue = blk: { | 1277 | const dst_mcv: MCValue = blk: { |
| 1278 | switch (operand) { | 1278 | switch (operand) { |
| 1279 | .stack_offset => |off| { | 1279 | .stack_offset => |off| { |
| 1280 | break :blk MCValue{ .stack_offset = off + 8 }; | 1280 | break :blk MCValue{ .stack_offset = off }; |
| 1281 | }, | 1281 | }, |
| 1282 | else => return self.fail("TODO implement slice_len for {}", .{operand}), | 1282 | else => return self.fail("TODO implement slice_len for {}", .{operand}), |
| 1283 | } | 1283 | } |
| ... | @@ -1515,18 +1515,22 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1515,18 +1515,22 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1515 | .data = .{ .imm = 0 }, | 1515 | .data = .{ .imm = 0 }, |
| 1516 | }); | 1516 | }); |
| 1517 | }, | 1517 | }, |
| 1518 | .stack_offset => |unadjusted_off| { | 1518 | .stack_offset => |off| { |
| 1519 | if (abi_size <= 8) { | 1519 | if (abi_size <= 8) { |
| 1520 | const tmp_reg = try self.register_manager.allocReg(null, &.{reg}); | 1520 | const tmp_reg = try self.register_manager.allocReg(null, &.{reg}); |
| 1521 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); | 1521 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 1522 | return self.genSetStack(elem_ty, unadjusted_off, MCValue{ .register = tmp_reg }); | 1522 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 1523 | } | 1523 | } |
| 1524 | | 1524 | |
| 1525 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ reg, .rax, .rcx }); | 1525 | const regs = try self.register_manager.allocRegs( |
| | 1526 | 3, |
| | 1527 | .{ null, null, null }, |
| | 1528 | &.{ reg, .rax, .rcx }, |
| | 1529 | ); |
| 1526 | const addr_reg = regs[0]; | 1530 | const addr_reg = regs[0]; |
| 1527 | const len_reg = regs[1]; | 1531 | const len_reg = regs[1]; |
| | 1532 | const tmp_reg = regs[2]; |
| 1528 | | 1533 | |
| 1529 | const off = unadjusted_off + abi_size; | | |
| 1530 | _ = try self.addInst(.{ | 1534 | _ = try self.addInst(.{ |
| 1531 | .tag = .mov, | 1535 | .tag = .mov, |
| 1532 | .ops = (Mir.Ops{ | 1536 | .ops = (Mir.Ops{ |
| ... | @@ -1536,13 +1540,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1536,13 +1540,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1536 | .data = undefined, | 1540 | .data = undefined, |
| 1537 | }); | 1541 | }); |
| 1538 | | 1542 | |
| | 1543 | try self.register_manager.getReg(.rax, null); |
| | 1544 | try self.register_manager.getReg(.rcx, null); |
| | 1545 | |
| 1539 | // TODO allow for abi size to be u64 | 1546 | // TODO allow for abi size to be u64 |
| 1540 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); | 1547 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 1541 | | 1548 | |
| 1542 | return self.genInlineMemcpy( | 1549 | return self.genInlineMemcpy( |
| 1543 | -@intCast(i32, off), | 1550 | -@intCast(i32, off + abi_size), |
| 1544 | registerAlias(addr_reg, @divExact(reg.size(), 8)), | 1551 | registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 1545 | len_reg.to64(), | 1552 | len_reg.to64(), |
| | 1553 | tmp_reg.to8(), |
| 1546 | ); | 1554 | ); |
| 1547 | }, | 1555 | }, |
| 1548 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), | 1556 | else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}), |
| ... | @@ -2148,6 +2156,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2148,6 +2156,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2148 | assert(ty.zigTypeTag() == .Pointer); | 2156 | assert(ty.zigTypeTag() == .Pointer); |
| 2149 | const mcv = try self.resolveInst(callee); | 2157 | const mcv = try self.resolveInst(callee); |
| 2150 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | 2158 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| | 2159 | _ = try self.addInst(.{ |
| | 2160 | .tag = .call, |
| | 2161 | .ops = (Mir.Ops{ |
| | 2162 | .reg1 = .rax, |
| | 2163 | .flags = 0b01, |
| | 2164 | }).encode(), |
| | 2165 | .data = undefined, |
| | 2166 | }); |
| 2151 | } | 2167 | } |
| 2152 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 2168 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 2153 | for (info.args) |mc_arg, arg_i| { | 2169 | for (info.args) |mc_arg, arg_i| { |
| ... | @@ -2217,6 +2233,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2217,6 +2233,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2217 | assert(ty.zigTypeTag() == .Pointer); | 2233 | assert(ty.zigTypeTag() == .Pointer); |
| 2218 | const mcv = try self.resolveInst(callee); | 2234 | const mcv = try self.resolveInst(callee); |
| 2219 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | 2235 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| | 2236 | _ = try self.addInst(.{ |
| | 2237 | .tag = .call, |
| | 2238 | .ops = (Mir.Ops{ |
| | 2239 | .reg1 = .rax, |
| | 2240 | .flags = 0b01, |
| | 2241 | }).encode(), |
| | 2242 | .data = undefined, |
| | 2243 | }); |
| 2220 | } | 2244 | } |
| 2221 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | 2245 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 2222 | for (info.args) |mc_arg, arg_i| { | 2246 | for (info.args) |mc_arg, arg_i| { |
| ... | @@ -2269,7 +2293,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2269,7 +2293,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2269 | }); | 2293 | }); |
| 2270 | } else return self.fail("TODO implement calling extern fn on plan9", .{}); | 2294 | } else return self.fail("TODO implement calling extern fn on plan9", .{}); |
| 2271 | } else { | 2295 | } else { |
| 2272 | return self.fail("TODO implement calling runtime known function pointer", .{}); | 2296 | assert(ty.zigTypeTag() == .Pointer); |
| | 2297 | const mcv = try self.resolveInst(callee); |
| | 2298 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| | 2299 | _ = try self.addInst(.{ |
| | 2300 | .tag = .call, |
| | 2301 | .ops = (Mir.Ops{ |
| | 2302 | .reg1 = .rax, |
| | 2303 | .flags = 0b01, |
| | 2304 | }).encode(), |
| | 2305 | .data = undefined, |
| | 2306 | }); |
| 2273 | } | 2307 | } |
| 2274 | } else unreachable; | 2308 | } else unreachable; |
| 2275 | | 2309 | |
| ... | @@ -3118,8 +3152,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3118,8 +3152,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3118 | } | 3152 | } |
| 3119 | return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); | 3153 | return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); |
| 3120 | }, | 3154 | }, |
| 3121 | .stack_offset => |unadjusted_off| { | 3155 | .stack_offset => |off| { |
| 3122 | if (stack_offset == unadjusted_off) { | 3156 | if (stack_offset == off) { |
| 3123 | // Copy stack variable to itself; nothing to do. | 3157 | // Copy stack variable to itself; nothing to do. |
| 3124 | return; | 3158 | return; |
| 3125 | } | 3159 | } |
| ... | @@ -3130,33 +3164,43 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3130,33 +3164,43 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3130 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3164 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3131 | } | 3165 | } |
| 3132 | | 3166 | |
| 3133 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ .rax, .rcx }); | 3167 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx }); |
| 3134 | const addr_reg = regs[0]; | 3168 | const addr_reg = regs[0]; |
| 3135 | const len_reg = regs[1]; | 3169 | const len_reg = regs[1]; |
| | 3170 | const tmp_reg = regs[2]; |
| | 3171 | |
| | 3172 | try self.register_manager.getReg(.rax, null); |
| | 3173 | try self.register_manager.getReg(.rcx, null); |
| 3136 | | 3174 | |
| 3137 | const off = unadjusted_off + abi_size; | | |
| 3138 | _ = try self.addInst(.{ | 3175 | _ = try self.addInst(.{ |
| 3139 | .tag = .lea, | 3176 | .tag = .lea, |
| 3140 | .ops = (Mir.Ops{ | 3177 | .ops = (Mir.Ops{ |
| 3141 | .reg1 = addr_reg.to64(), | 3178 | .reg1 = addr_reg.to64(), |
| 3142 | .reg2 = .rbp, | 3179 | .reg2 = .rbp, |
| 3143 | }).encode(), | 3180 | }).encode(), |
| 3144 | .data = .{ .imm = -@intCast(i32, off) }, | 3181 | .data = .{ .imm = -@intCast(i32, off + abi_size) }, |
| 3145 | }); | 3182 | }); |
| 3146 | | 3183 | |
| 3147 | // TODO allow for abi_size to be u64 | 3184 | // TODO allow for abi_size to be u64 |
| 3148 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); | 3185 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3149 | | 3186 | |
| 3150 | return self.genInlineMemcpy(-@intCast(i32, off), addr_reg.to64(), len_reg.to64()); | 3187 | return self.genInlineMemcpy( |
| | 3188 | -@intCast(i32, stack_offset + abi_size), |
| | 3189 | addr_reg.to64(), |
| | 3190 | len_reg.to64(), |
| | 3191 | tmp_reg.to8(), |
| | 3192 | ); |
| 3151 | }, | 3193 | }, |
| 3152 | } | 3194 | } |
| 3153 | } | 3195 | } |
| 3154 | | 3196 | |
| 3155 | fn genInlineMemcpy(self: *Self, stack_offset: i32, addr_reg: Register, len_reg: Register) InnerError!void { | 3197 | fn genInlineMemcpy( |
| 3156 | try self.register_manager.getReg(.rax, null); | 3198 | self: *Self, |
| 3157 | try self.register_manager.getReg(.rcx, null); | 3199 | stack_offset: i32, |
| 3158 | const tmp_reg = try self.register_manager.allocReg(null, &.{ addr_reg, len_reg, .rax, .rcx }); | 3200 | addr_reg: Register, |
| 3159 | | 3201 | len_reg: Register, |
| | 3202 | tmp_reg: Register, |
| | 3203 | ) InnerError!void { |
| 3160 | // mov rcx, 0 | 3204 | // mov rcx, 0 |
| 3161 | _ = try self.addInst(.{ | 3205 | _ = try self.addInst(.{ |
| 3162 | .tag = .mov, | 3206 | .tag = .mov, |