| ... | @@ -932,6 +932,25 @@ fn gen(self: *Self) !void { | ... | @@ -932,6 +932,25 @@ fn gen(self: *Self) !void { |
| 932 | const backpatch_fp_add = try self.addPseudo(.pseudo_dead); | 932 | const backpatch_fp_add = try self.addPseudo(.pseudo_dead); |
| 933 | const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead); | 933 | const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead); |
| 934 | | 934 | |
| | 935 | switch (self.ret_mcv.long) { |
| | 936 | .none, .unreach => {}, |
| | 937 | .indirect => { |
| | 938 | // The address where to store the return value for the caller is in a |
| | 939 | // register which the callee is free to clobber. Therefore, we purposely |
| | 940 | // spill it to stack immediately. |
| | 941 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod)); |
| | 942 | try self.genSetMem( |
| | 943 | .{ .frame = frame_index }, |
| | 944 | 0, |
| | 945 | Type.usize, |
| | 946 | self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off), |
| | 947 | ); |
| | 948 | self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; |
| | 949 | tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index }); |
| | 950 | }, |
| | 951 | else => unreachable, |
| | 952 | } |
| | 953 | |
| 935 | try self.genBody(self.air.getMainBody()); | 954 | try self.genBody(self.air.getMainBody()); |
| 936 | | 955 | |
| 937 | for (self.exitlude_jump_relocs.items) |jmp_reloc| { | 956 | for (self.exitlude_jump_relocs.items) |jmp_reloc| { |
| ... | @@ -1306,12 +1325,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1306,12 +1325,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1306 | var it = self.register_manager.free_registers.iterator(.{ .kind = .unset }); | 1325 | var it = self.register_manager.free_registers.iterator(.{ .kind = .unset }); |
| 1307 | while (it.next()) |index| { | 1326 | while (it.next()) |index| { |
| 1308 | const tracked_inst = self.register_manager.registers[index]; | 1327 | const tracked_inst = self.register_manager.registers[index]; |
| | 1328 | tracking_log.debug("tracked inst: {}", .{tracked_inst}); |
| 1309 | const tracking = self.getResolvedInstValue(tracked_inst); | 1329 | const tracking = self.getResolvedInstValue(tracked_inst); |
| 1310 | for (tracking.getRegs()) |reg| { | 1330 | for (tracking.getRegs()) |reg| { |
| 1311 | if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break; | 1331 | if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break; |
| 1312 | } else return self.fail( | 1332 | } else return std.debug.panic( |
| 1313 | \\%{} takes up these regs: {any}, however those regs don't use it | 1333 | \\%{} takes up these regs: {any}, however these regs {any}, don't use it |
| 1314 | , .{ index, tracking.getRegs() }); | 1334 | , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) }); |
| 1315 | } | 1335 | } |
| 1316 | } | 1336 | } |
| 1317 | } | 1337 | } |
| ... | @@ -1540,7 +1560,7 @@ fn symbolIndex(self: *Self) !u32 { | ... | @@ -1540,7 +1560,7 @@ fn symbolIndex(self: *Self) !u32 { |
| 1540 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | 1560 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1541 | break :blk atom_index; | 1561 | break :blk atom_index; |
| 1542 | }, | 1562 | }, |
| 1543 | else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}), | 1563 | else => return self.fail("TODO symbolIndex {s}", .{@tagName(self.bin_file.tag)}), |
| 1544 | }; | 1564 | }; |
| 1545 | } | 1565 | } |
| 1546 | | 1566 | |
| ... | @@ -1961,7 +1981,7 @@ fn binOp( | ... | @@ -1961,7 +1981,7 @@ fn binOp( |
| 1961 | switch (lhs_ty.zigTypeTag(zcu)) { | 1981 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 1962 | .Float => return self.fail("TODO binary operations on floats", .{}), | 1982 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1963 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1983 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1964 | .Int, .Enum => { | 1984 | .Int, .Enum, .ErrorSet => { |
| 1965 | assert(lhs_ty.eql(rhs_ty, zcu)); | 1985 | assert(lhs_ty.eql(rhs_ty, zcu)); |
| 1966 | const int_info = lhs_ty.intInfo(zcu); | 1986 | const int_info = lhs_ty.intInfo(zcu); |
| 1967 | if (int_info.bits <= 64) { | 1987 | if (int_info.bits <= 64) { |
| ... | @@ -2304,8 +2324,127 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2304,8 +2324,127 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2304 | } | 2324 | } |
| 2305 | | 2325 | |
| 2306 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 2326 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2307 | _ = inst; | 2327 | const zcu = self.bin_file.comp.module.?; |
| 2308 | return self.fail("TODO implement airSubWithOverflow for {}", .{self.target.cpu.arch}); | 2328 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| | 2329 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 2330 | |
| | 2331 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| | 2332 | const lhs = try self.resolveInst(extra.lhs); |
| | 2333 | const rhs = try self.resolveInst(extra.rhs); |
| | 2334 | const lhs_ty = self.typeOf(extra.lhs); |
| | 2335 | const rhs_ty = self.typeOf(extra.rhs); |
| | 2336 | |
| | 2337 | const int_info = lhs_ty.intInfo(zcu); |
| | 2338 | |
| | 2339 | if (!math.isPowerOfTwo(int_info.bits) or !(int_info.bits >= 8)) { |
| | 2340 | return self.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{}); |
| | 2341 | } |
| | 2342 | |
| | 2343 | const tuple_ty = self.typeOfIndex(inst); |
| | 2344 | const result_mcv = try self.allocRegOrMem(inst, false); |
| | 2345 | const offset = result_mcv.load_frame; |
| | 2346 | |
| | 2347 | const lhs_reg, const lhs_lock = blk: { |
| | 2348 | if (lhs == .register) break :blk .{ lhs.register, null }; |
| | 2349 | |
| | 2350 | const lhs_reg, const lhs_lock = try self.allocReg(); |
| | 2351 | try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| | 2352 | break :blk .{ lhs_reg, lhs_lock }; |
| | 2353 | }; |
| | 2354 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 2355 | |
| | 2356 | const rhs_reg, const rhs_lock = blk: { |
| | 2357 | if (rhs == .register) break :blk .{ rhs.register, null }; |
| | 2358 | |
| | 2359 | const rhs_reg, const rhs_lock = try self.allocReg(); |
| | 2360 | try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| | 2361 | break :blk .{ rhs_reg, rhs_lock }; |
| | 2362 | }; |
| | 2363 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 2364 | |
| | 2365 | const dest_reg, const dest_lock = try self.allocReg(); |
| | 2366 | defer self.register_manager.unlockReg(dest_lock); |
| | 2367 | |
| | 2368 | switch (int_info.signedness) { |
| | 2369 | .unsigned => return self.fail("TODO: airSubWithOverflow unsigned", .{}), |
| | 2370 | .signed => { |
| | 2371 | switch (int_info.bits) { |
| | 2372 | 64 => { |
| | 2373 | // result |
| | 2374 | _ = try self.addInst(.{ |
| | 2375 | .tag = .sub, |
| | 2376 | .ops = .rrr, |
| | 2377 | .data = .{ .r_type = .{ |
| | 2378 | .rd = dest_reg, |
| | 2379 | .rs1 = lhs_reg, |
| | 2380 | .rs2 = rhs_reg, |
| | 2381 | } }, |
| | 2382 | }); |
| | 2383 | |
| | 2384 | try self.genSetMem( |
| | 2385 | .{ .frame = offset.index }, |
| | 2386 | offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))), |
| | 2387 | lhs_ty, |
| | 2388 | .{ .register = dest_reg }, |
| | 2389 | ); |
| | 2390 | |
| | 2391 | // overflow check |
| | 2392 | const overflow_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = 0 }); |
| | 2393 | |
| | 2394 | _ = try self.addInst(.{ |
| | 2395 | .tag = .slt, |
| | 2396 | .ops = .rrr, |
| | 2397 | .data = .{ .r_type = .{ |
| | 2398 | .rd = overflow_reg, |
| | 2399 | .rs1 = overflow_reg, |
| | 2400 | .rs2 = rhs_reg, |
| | 2401 | } }, |
| | 2402 | }); |
| | 2403 | |
| | 2404 | _ = try self.addInst(.{ |
| | 2405 | .tag = .slt, |
| | 2406 | .ops = .rrr, |
| | 2407 | .data = .{ .r_type = .{ |
| | 2408 | .rd = rhs_reg, |
| | 2409 | .rs1 = rhs_reg, |
| | 2410 | .rs2 = lhs_reg, |
| | 2411 | } }, |
| | 2412 | }); |
| | 2413 | |
| | 2414 | _ = try self.addInst(.{ |
| | 2415 | .tag = .xor, |
| | 2416 | .ops = .rrr, |
| | 2417 | .data = .{ .r_type = .{ |
| | 2418 | .rd = lhs_reg, |
| | 2419 | .rs1 = overflow_reg, |
| | 2420 | .rs2 = rhs_reg, |
| | 2421 | } }, |
| | 2422 | }); |
| | 2423 | |
| | 2424 | const overflow_mcv = try self.binOp( |
| | 2425 | .cmp_neq, |
| | 2426 | .{ .register = overflow_reg }, |
| | 2427 | Type.usize, |
| | 2428 | .{ .register = rhs_reg }, |
| | 2429 | Type.usize, |
| | 2430 | ); |
| | 2431 | |
| | 2432 | try self.genSetMem( |
| | 2433 | .{ .frame = offset.index }, |
| | 2434 | offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))), |
| | 2435 | Type.u1, |
| | 2436 | overflow_mcv, |
| | 2437 | ); |
| | 2438 | |
| | 2439 | break :result result_mcv; |
| | 2440 | }, |
| | 2441 | else => |int_bits| return self.fail("TODO: airSubWithOverflow signed {}", .{int_bits}), |
| | 2442 | } |
| | 2443 | }, |
| | 2444 | } |
| | 2445 | }; |
| | 2446 | |
| | 2447 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 2309 | } | 2448 | } |
| 2310 | | 2449 | |
| 2311 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | 2450 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -2644,8 +2783,25 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2644,8 +2783,25 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2644 | | 2783 | |
| 2645 | /// T to E!T | 2784 | /// T to E!T |
| 2646 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 2785 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| | 2786 | const zcu = self.bin_file.comp.module.?; |
| 2647 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 2787 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 2648 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch}); | 2788 | |
| | 2789 | const eu_ty = ty_op.ty.toType(); |
| | 2790 | const pl_ty = eu_ty.errorUnionPayload(zcu); |
| | 2791 | const err_ty = eu_ty.errorUnionSet(zcu); |
| | 2792 | const operand = try self.resolveInst(ty_op.operand); |
| | 2793 | |
| | 2794 | const result: MCValue = result: { |
| | 2795 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 }; |
| | 2796 | |
| | 2797 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); |
| | 2798 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); |
| | 2799 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu)); |
| | 2800 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand); |
| | 2801 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }); |
| | 2802 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| | 2803 | }; |
| | 2804 | |
| 2649 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2805 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2650 | } | 2806 | } |
| 2651 | | 2807 | |
| ... | @@ -3361,8 +3517,6 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3361,8 +3517,6 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3361 | .rs1 = dst_reg, | 3517 | .rs1 = dst_reg, |
| 3362 | } }, | 3518 | } }, |
| 3363 | }); | 3519 | }); |
| 3364 | | | |
| 3365 | return self.fail("TODO: airStructFieldVal register with field_off > 0", .{}); | | |
| 3366 | } | 3520 | } |
| 3367 | | 3521 | |
| 3368 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); | 3522 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); |
| ... | @@ -3444,7 +3598,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { | ... | @@ -3444,7 +3598,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 3444 | } | 3598 | } |
| 3445 | | 3599 | |
| 3446 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { | 3600 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3447 | const zcu = self.bin_file.comp.module.?; | | |
| 3448 | var arg_index = self.arg_index; | 3601 | var arg_index = self.arg_index; |
| 3449 | | 3602 | |
| 3450 | // we skip over args that have no bits | 3603 | // we skip over args that have no bits |
| ... | @@ -3453,31 +3606,10 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3453,31 +3606,10 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3453 | | 3606 | |
| 3454 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | 3607 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 3455 | const src_mcv = self.args[arg_index]; | 3608 | const src_mcv = self.args[arg_index]; |
| 3456 | | | |
| 3457 | const arg_ty = self.typeOfIndex(inst); | 3609 | const arg_ty = self.typeOfIndex(inst); |
| 3458 | | 3610 | |
| 3459 | const dst_mcv = switch (src_mcv) { | 3611 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 3460 | .register => dst: { | 3612 | try self.genCopy(arg_ty, dst_mcv, src_mcv); |
| 3461 | const frame = try self.allocFrameIndex(FrameAlloc.init(.{ | | |
| 3462 | .size = Type.usize.abiSize(zcu), | | |
| 3463 | .alignment = Type.usize.abiAlignment(zcu), | | |
| 3464 | })); | | |
| 3465 | const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } }; | | |
| 3466 | try self.genCopy(Type.usize, dst_mcv, src_mcv); | | |
| 3467 | break :dst dst_mcv; | | |
| 3468 | }, | | |
| 3469 | .register_pair => dst: { | | |
| 3470 | const frame = try self.allocFrameIndex(FrameAlloc.init(.{ | | |
| 3471 | .size = Type.usize.abiSize(zcu) * 2, | | |
| 3472 | .alignment = Type.usize.abiAlignment(zcu), | | |
| 3473 | })); | | |
| 3474 | const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } }; | | |
| 3475 | try self.genCopy(arg_ty, dst_mcv, src_mcv); | | |
| 3476 | break :dst dst_mcv; | | |
| 3477 | }, | | |
| 3478 | .load_frame => src_mcv, | | |
| 3479 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), | | |
| 3480 | }; | | |
| 3481 | | 3613 | |
| 3482 | try self.genArgDbgInfo(inst, src_mcv); | 3614 | try self.genArgDbgInfo(inst, src_mcv); |
| 3483 | break :result dst_mcv; | 3615 | break :result dst_mcv; |
| ... | @@ -3612,7 +3744,68 @@ fn genCall( | ... | @@ -3612,7 +3744,68 @@ fn genCall( |
| 3612 | stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align); | 3744 | stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align); |
| 3613 | } | 3745 | } |
| 3614 | | 3746 | |
| 3615 | for (call_info.args, 0..) |mc_arg, arg_i| try self.genCopy(arg_tys[arg_i], mc_arg, args[arg_i]); | 3747 | var reg_locks = std.ArrayList(?RegisterLock).init(allocator); |
| | 3748 | defer reg_locks.deinit(); |
| | 3749 | try reg_locks.ensureTotalCapacity(8); |
| | 3750 | defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3751 | |
| | 3752 | const frame_indices = try allocator.alloc(FrameIndex, args.len); |
| | 3753 | defer allocator.free(frame_indices); |
| | 3754 | |
| | 3755 | switch (call_info.return_value.long) { |
| | 3756 | .none, .unreach => {}, |
| | 3757 | .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null), |
| | 3758 | else => unreachable, |
| | 3759 | } |
| | 3760 | for (call_info.args, args, arg_tys, frame_indices) |dst_arg, src_arg, arg_ty, *frame_index| { |
| | 3761 | switch (dst_arg) { |
| | 3762 | .none => {}, |
| | 3763 | .register => |reg| { |
| | 3764 | try self.register_manager.getReg(reg, null); |
| | 3765 | try reg_locks.append(self.register_manager.lockReg(reg)); |
| | 3766 | }, |
| | 3767 | .register_pair => |regs| { |
| | 3768 | for (regs) |reg| try self.register_manager.getReg(reg, null); |
| | 3769 | try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs)); |
| | 3770 | }, |
| | 3771 | .indirect => |reg_off| { |
| | 3772 | frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, zcu)); |
| | 3773 | try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg); |
| | 3774 | try self.register_manager.getReg(reg_off.reg, null); |
| | 3775 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| | 3776 | }, |
| | 3777 | else => return self.fail("TODO: genCall set arg {s}", .{@tagName(dst_arg)}), |
| | 3778 | } |
| | 3779 | } |
| | 3780 | |
| | 3781 | switch (call_info.return_value.long) { |
| | 3782 | .none, .unreach => {}, |
| | 3783 | .indirect => |reg_off| { |
| | 3784 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| | 3785 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, zcu)); |
| | 3786 | try self.genSetReg(Type.usize, reg_off.reg, .{ |
| | 3787 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| | 3788 | }); |
| | 3789 | call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; |
| | 3790 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| | 3791 | }, |
| | 3792 | else => unreachable, |
| | 3793 | } |
| | 3794 | |
| | 3795 | for (call_info.args, arg_tys, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| { |
| | 3796 | switch (dst_arg) { |
| | 3797 | .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg), |
| | 3798 | .register => |dst_reg| try self.genSetReg( |
| | 3799 | arg_ty, |
| | 3800 | dst_reg, |
| | 3801 | src_arg, |
| | 3802 | ), |
| | 3803 | .indirect => |reg_off| try self.genSetReg(Type.usize, reg_off.reg, .{ |
| | 3804 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| | 3805 | }), |
| | 3806 | else => return self.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}), |
| | 3807 | } |
| | 3808 | } |
| 3616 | | 3809 | |
| 3617 | // Due to incremental compilation, how function calls are generated depends | 3810 | // Due to incremental compilation, how function calls are generated depends |
| 3618 | // on linking. | 3811 | // on linking. |
| ... | @@ -3715,9 +3908,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -3715,9 +3908,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 3715 | defer self.register_manager.unlockReg(lock); | 3908 | defer self.register_manager.unlockReg(lock); |
| 3716 | | 3909 | |
| 3717 | try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long); | 3910 | try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long); |
| 3718 | try self.genCopy( | 3911 | try self.genSetMem( |
| | 3912 | .{ .reg = reg_off.reg }, |
| | 3913 | reg_off.off, |
| 3719 | ret_ty, | 3914 | ret_ty, |
| 3720 | .{ .register_offset = reg_off }, | | |
| 3721 | .{ .air_ref = un_op }, | 3915 | .{ .air_ref = un_op }, |
| 3722 | ); | 3916 | ); |
| 3723 | }, | 3917 | }, |
| ... | @@ -3745,6 +3939,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3745,6 +3939,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3745 | switch (self.ret_mcv.short) { | 3939 | switch (self.ret_mcv.short) { |
| 3746 | .none => {}, | 3940 | .none => {}, |
| 3747 | .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty), | 3941 | .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty), |
| | 3942 | .indirect => |reg_off| try self.genSetReg(ptr_ty, reg_off.reg, ptr), |
| 3748 | else => unreachable, | 3943 | else => unreachable, |
| 3749 | } | 3944 | } |
| 3750 | self.ret_mcv.liveOut(self, inst); | 3945 | self.ret_mcv.liveOut(self, inst); |
| ... | @@ -4058,7 +4253,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) | ... | @@ -4058,7 +4253,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) |
| 4058 | | 4253 | |
| 4059 | _ = maybe_inst; | 4254 | _ = maybe_inst; |
| 4060 | | 4255 | |
| 4061 | const err_off = errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu); | 4256 | const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu)); |
| 4062 | | 4257 | |
| 4063 | switch (eu_mcv) { | 4258 | switch (eu_mcv) { |
| 4064 | .register => |reg| { | 4259 | .register => |reg| { |
| ... | @@ -4081,15 +4276,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) | ... | @@ -4081,15 +4276,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) |
| 4081 | ); | 4276 | ); |
| 4082 | } | 4277 | } |
| 4083 | | 4278 | |
| 4084 | return_mcv = try self.binOp( | 4279 | return try self.binOp( |
| 4085 | .cmp_neq, | 4280 | .cmp_neq, |
| 4086 | return_mcv, | 4281 | return_mcv, |
| 4087 | Type.u16, | 4282 | Type.u16, |
| 4088 | .{ .immediate = 0 }, | 4283 | .{ .immediate = 0 }, |
| 4089 | Type.u16, | 4284 | Type.u16, |
| 4090 | ); | 4285 | ); |
| 4091 | | 4286 | }, |
| 4092 | return return_mcv; | 4287 | .load_frame => |frame_addr| { |
| | 4288 | return self.binOp( |
| | 4289 | .cmp_neq, |
| | 4290 | .{ .load_frame = .{ |
| | 4291 | .index = frame_addr.index, |
| | 4292 | .off = frame_addr.off + err_off, |
| | 4293 | } }, |
| | 4294 | Type.anyerror, |
| | 4295 | .{ .immediate = 0 }, |
| | 4296 | Type.anyerror, |
| | 4297 | ); |
| 4093 | }, | 4298 | }, |
| 4094 | else => return self.fail("TODO implement isErr for {}", .{eu_mcv}), | 4299 | else => return self.fail("TODO implement isErr for {}", .{eu_mcv}), |
| 4095 | } | 4300 | } |
| ... | @@ -4839,7 +5044,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -4839,7 +5044,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 4839 | const zcu = self.bin_file.comp.module.?; | 5044 | const zcu = self.bin_file.comp.module.?; |
| 4840 | const abi_size: u32 = @intCast(ty.abiSize(zcu)); | 5045 | const abi_size: u32 = @intCast(ty.abiSize(zcu)); |
| 4841 | | 5046 | |
| 4842 | if (abi_size > 8) return self.fail("tried to set reg with size {}", .{abi_size}); | 5047 | if (abi_size > 8) return std.debug.panic("tried to set reg with size {}", .{abi_size}); |
| 4843 | | 5048 | |
| 4844 | switch (src_mcv) { | 5049 | switch (src_mcv) { |
| 4845 | .dead => unreachable, | 5050 | .dead => unreachable, |
| ... | @@ -4924,7 +5129,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -4924,7 +5129,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 4924 | if (src_reg.id() == reg.id()) | 5129 | if (src_reg.id() == reg.id()) |
| 4925 | return; | 5130 | return; |
| 4926 | | 5131 | |
| 4927 | // mov reg, src_reg | 5132 | // mv reg, src_reg |
| 4928 | _ = try self.addInst(.{ | 5133 | _ = try self.addInst(.{ |
| 4929 | .tag = .pseudo, | 5134 | .tag = .pseudo, |
| 4930 | .ops = .pseudo_mv, | 5135 | .ops = .pseudo_mv, |
| ... | @@ -4934,20 +5139,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -4934,20 +5139,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 4934 | } }, | 5139 | } }, |
| 4935 | }); | 5140 | }); |
| 4936 | }, | 5141 | }, |
| 4937 | .register_pair => |pair| try self.genSetReg(ty, reg, .{ .register = pair[0] }), | 5142 | .register_pair => return self.fail("genSetReg should we allow reg -> reg_pair?", .{}), |
| 4938 | .memory => |addr| { | | |
| 4939 | try self.genSetReg(ty, reg, .{ .immediate = addr }); | | |
| 4940 | | | |
| 4941 | _ = try self.addInst(.{ | | |
| 4942 | .tag = .ld, | | |
| 4943 | .ops = .rri, | | |
| 4944 | .data = .{ .i_type = .{ | | |
| 4945 | .rd = reg, | | |
| 4946 | .rs1 = reg, | | |
| 4947 | .imm12 = Immediate.s(0), | | |
| 4948 | } }, | | |
| 4949 | }); | | |
| 4950 | }, | | |
| 4951 | .load_frame => |frame| { | 5143 | .load_frame => |frame| { |
| 4952 | _ = try self.addInst(.{ | 5144 | _ = try self.addInst(.{ |
| 4953 | .tag = .pseudo, | 5145 | .tag = .pseudo, |
| ... | @@ -4966,28 +5158,49 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -4966,28 +5158,49 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 4966 | } }, | 5158 | } }, |
| 4967 | }); | 5159 | }); |
| 4968 | }, | 5160 | }, |
| 4969 | .lea_frame => |frame| { | 5161 | .memory => |addr| { |
| | 5162 | try self.genSetReg(ty, reg, .{ .immediate = addr }); |
| | 5163 | |
| | 5164 | _ = try self.addInst(.{ |
| | 5165 | .tag = .ld, |
| | 5166 | .ops = .rri, |
| | 5167 | .data = .{ .i_type = .{ |
| | 5168 | .rd = reg, |
| | 5169 | .rs1 = reg, |
| | 5170 | .imm12 = Immediate.s(0), |
| | 5171 | } }, |
| | 5172 | }); |
| | 5173 | }, |
| | 5174 | .lea_frame, .register_offset => { |
| 4970 | _ = try self.addInst(.{ | 5175 | _ = try self.addInst(.{ |
| 4971 | .tag = .pseudo, | 5176 | .tag = .pseudo, |
| 4972 | .ops = .pseudo_lea_rm, | 5177 | .ops = .pseudo_lea_rm, |
| 4973 | .data = .{ .rm = .{ | 5178 | .data = .{ .rm = .{ |
| 4974 | .r = reg, | 5179 | .r = reg, |
| 4975 | .m = .{ | 5180 | .m = switch (src_mcv) { |
| 4976 | .base = .{ .frame = frame.index }, | 5181 | .register_offset => |reg_off| .{ |
| 4977 | .mod = .{ | 5182 | .base = .{ .reg = reg_off.reg }, |
| 4978 | .rm = .{ | 5183 | .mod = .{ |
| 4979 | .size = self.memSize(ty), | 5184 | .rm = .{ |
| 4980 | .disp = frame.off, | 5185 | .size = self.memSize(ty), |
| | 5186 | .disp = reg_off.off, |
| | 5187 | }, |
| | 5188 | }, |
| | 5189 | }, |
| | 5190 | .lea_frame => |frame| .{ |
| | 5191 | .base = .{ .frame = frame.index }, |
| | 5192 | .mod = .{ |
| | 5193 | .rm = .{ |
| | 5194 | .size = self.memSize(ty), |
| | 5195 | .disp = frame.off, |
| | 5196 | }, |
| 4981 | }, | 5197 | }, |
| 4982 | }, | 5198 | }, |
| | 5199 | else => unreachable, |
| 4983 | }, | 5200 | }, |
| 4984 | } }, | 5201 | } }, |
| 4985 | }); | 5202 | }); |
| 4986 | }, | 5203 | }, |
| 4987 | .load_symbol => { | | |
| 4988 | try self.genSetReg(ty, reg, src_mcv.address()); | | |
| 4989 | try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = reg } }); | | |
| 4990 | }, | | |
| 4991 | .indirect => |reg_off| { | 5204 | .indirect => |reg_off| { |
| 4992 | const load_tag: Mir.Inst.Tag = switch (abi_size) { | 5205 | const load_tag: Mir.Inst.Tag = switch (abi_size) { |
| 4993 | 1 => .lb, | 5206 | 1 => .lb, |
| ... | @@ -5022,6 +5235,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -5022,6 +5235,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 5022 | }) }, | 5235 | }) }, |
| 5023 | }); | 5236 | }); |
| 5024 | }, | 5237 | }, |
| | 5238 | .load_symbol => { |
| | 5239 | try self.genSetReg(ty, reg, src_mcv.address()); |
| | 5240 | try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = reg } }); |
| | 5241 | }, |
| 5025 | .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)), | 5242 | .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)), |
| 5026 | else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), | 5243 | else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), |
| 5027 | } | 5244 | } |
| ... | @@ -5052,7 +5269,6 @@ fn genSetMem( | ... | @@ -5052,7 +5269,6 @@ fn genSetMem( |
| 5052 | src_mcv, | 5269 | src_mcv, |
| 5053 | .{ .immediate = abi_size }, | 5270 | .{ .immediate = abi_size }, |
| 5054 | ), | 5271 | ), |
| 5055 | | | |
| 5056 | .register_offset, | 5272 | .register_offset, |
| 5057 | .memory, | 5273 | .memory, |
| 5058 | .indirect, | 5274 | .indirect, |
| ... | @@ -5100,14 +5316,15 @@ fn genSetMem( | ... | @@ -5100,14 +5316,15 @@ fn genSetMem( |
| 5100 | _ = try self.addInst(.{ | 5316 | _ = try self.addInst(.{ |
| 5101 | .tag = .pseudo, | 5317 | .tag = .pseudo, |
| 5102 | .ops = .pseudo_store_rm, | 5318 | .ops = .pseudo_store_rm, |
| 5103 | .data = .{ | 5319 | .data = .{ .rm = .{ |
| 5104 | .rm = .{ .r = reg, .m = .{ | 5320 | .r = reg, |
| | 5321 | .m = .{ |
| 5105 | .base = .{ .frame = frame_index }, | 5322 | .base = .{ .frame = frame_index }, |
| 5106 | .mod = .{ .rm = .{ | 5323 | .mod = .{ .rm = .{ |
| 5107 | .size = Memory.Size.fromByteSize(src_size), | 5324 | .size = Memory.Size.fromByteSize(src_size), |
| 5108 | } }, | 5325 | } }, |
| 5109 | } }, | 5326 | }, |
| 5110 | }, | 5327 | } }, |
| 5111 | }); | 5328 | }); |
| 5112 | try self.genSetMem(base, disp, ty, frame_mcv); | 5329 | try self.genSetMem(base, disp, ty, frame_mcv); |
| 5113 | try self.freeValue(frame_mcv); | 5330 | try self.freeValue(frame_mcv); |