| ... | ... | @@ -1260,7 +1260,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1260 | 1260 | const dst_mcv: MCValue = blk: { |
| 1261 | 1261 | switch (operand) { |
| 1262 | 1262 | .stack_offset => |off| { |
| 1263 | | break :blk MCValue{ .stack_offset = off }; |
| 1263 | break :blk MCValue{ .stack_offset = off + 8 }; |
| 1264 | 1264 | }, |
| 1265 | 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 | 1277 | const dst_mcv: MCValue = blk: { |
| 1278 | 1278 | switch (operand) { |
| 1279 | 1279 | .stack_offset => |off| { |
| 1280 | | break :blk MCValue{ .stack_offset = off + 8 }; |
| 1280 | break :blk MCValue{ .stack_offset = off }; |
| 1281 | 1281 | }, |
| 1282 | 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 | 1515 | .data = .{ .imm = 0 }, |
| 1516 | 1516 | }); |
| 1517 | 1517 | }, |
| 1518 | | .stack_offset => |unadjusted_off| { |
| 1518 | .stack_offset => |off| { |
| 1519 | 1519 | if (abi_size <= 8) { |
| 1520 | 1520 | const tmp_reg = try self.register_manager.allocReg(null, &.{reg}); |
| 1521 | 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 | 1530 | const addr_reg = regs[0]; |
| 1527 | 1531 | const len_reg = regs[1]; |
| 1532 | const tmp_reg = regs[2]; |
| 1528 | 1533 | |
| 1529 | | const off = unadjusted_off + abi_size; |
| 1530 | 1534 | _ = try self.addInst(.{ |
| 1531 | 1535 | .tag = .mov, |
| 1532 | 1536 | .ops = (Mir.Ops{ |
| ... | ... | @@ -1536,13 +1540,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1536 | 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 | 1546 | // TODO allow for abi size to be u64 |
| 1540 | 1547 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 1541 | 1548 | |
| 1542 | 1549 | return self.genInlineMemcpy( |
| 1543 | | -@intCast(i32, off), |
| 1550 | -@intCast(i32, off + abi_size), |
| 1544 | 1551 | registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 1545 | 1552 | len_reg.to64(), |
| 1553 | tmp_reg.to8(), |
| 1546 | 1554 | ); |
| 1547 | 1555 | }, |
| 1548 | 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 | 2156 | assert(ty.zigTypeTag() == .Pointer); |
| 2149 | 2157 | const mcv = try self.resolveInst(callee); |
| 2150 | 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 | 2168 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 2153 | 2169 | for (info.args) |mc_arg, arg_i| { |
| ... | ... | @@ -2217,6 +2233,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2217 | 2233 | assert(ty.zigTypeTag() == .Pointer); |
| 2218 | 2234 | const mcv = try self.resolveInst(callee); |
| 2219 | 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 | 2245 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 2222 | 2246 | for (info.args) |mc_arg, arg_i| { |
| ... | ... | @@ -2269,7 +2293,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2269 | 2293 | }); |
| 2270 | 2294 | } else return self.fail("TODO implement calling extern fn on plan9", .{}); |
| 2271 | 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 | 2308 | } else unreachable; |
| 2275 | 2309 | |
| ... | ... | @@ -3118,8 +3152,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3118 | 3152 | } |
| 3119 | 3153 | return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); |
| 3120 | 3154 | }, |
| 3121 | | .stack_offset => |unadjusted_off| { |
| 3122 | | if (stack_offset == unadjusted_off) { |
| 3155 | .stack_offset => |off| { |
| 3156 | if (stack_offset == off) { |
| 3123 | 3157 | // Copy stack variable to itself; nothing to do. |
| 3124 | 3158 | return; |
| 3125 | 3159 | } |
| ... | ... | @@ -3130,33 +3164,43 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3130 | 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 | 3168 | const addr_reg = regs[0]; |
| 3135 | 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 | 3175 | _ = try self.addInst(.{ |
| 3139 | 3176 | .tag = .lea, |
| 3140 | 3177 | .ops = (Mir.Ops{ |
| 3141 | 3178 | .reg1 = addr_reg.to64(), |
| 3142 | 3179 | .reg2 = .rbp, |
| 3143 | 3180 | }).encode(), |
| 3144 | | .data = .{ .imm = -@intCast(i32, off) }, |
| 3181 | .data = .{ .imm = -@intCast(i32, off + abi_size) }, |
| 3145 | 3182 | }); |
| 3146 | 3183 | |
| 3147 | 3184 | // TODO allow for abi_size to be u64 |
| 3148 | 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 { |
| 3156 | | try self.register_manager.getReg(.rax, null); |
| 3157 | | try self.register_manager.getReg(.rcx, null); |
| 3158 | | const tmp_reg = try self.register_manager.allocReg(null, &.{ addr_reg, len_reg, .rax, .rcx }); |
| 3159 | | |
| 3197 | fn genInlineMemcpy( |
| 3198 | self: *Self, |
| 3199 | stack_offset: i32, |
| 3200 | addr_reg: Register, |
| 3201 | len_reg: Register, |
| 3202 | tmp_reg: Register, |
| 3203 | ) InnerError!void { |
| 3160 | 3204 | // mov rcx, 0 |
| 3161 | 3205 | _ = try self.addInst(.{ |
| 3162 | 3206 | .tag = .mov, |