| ... | ... | @@ -932,6 +932,25 @@ fn gen(self: *Self) !void { |
| 932 | 932 | const backpatch_fp_add = try self.addPseudo(.pseudo_dead); |
| 933 | 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 | 954 | try self.genBody(self.air.getMainBody()); |
| 936 | 955 | |
| 937 | 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 | 1325 | var it = self.register_manager.free_registers.iterator(.{ .kind = .unset }); |
| 1307 | 1326 | while (it.next()) |index| { |
| 1308 | 1327 | const tracked_inst = self.register_manager.registers[index]; |
| 1328 | tracking_log.debug("tracked inst: {}", .{tracked_inst}); |
| 1309 | 1329 | const tracking = self.getResolvedInstValue(tracked_inst); |
| 1310 | 1330 | for (tracking.getRegs()) |reg| { |
| 1311 | 1331 | if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break; |
| 1312 | | } else return self.fail( |
| 1313 | | \\%{} takes up these regs: {any}, however those regs don't use it |
| 1314 | | , .{ index, tracking.getRegs() }); |
| 1332 | } else return std.debug.panic( |
| 1333 | \\%{} takes up these regs: {any}, however these regs {any}, don't use it |
| 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 | 1560 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); |
| 1541 | 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 | 1981 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 1962 | 1982 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1963 | 1983 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1964 | | .Int, .Enum => { |
| 1984 | .Int, .Enum, .ErrorSet => { |
| 1965 | 1985 | assert(lhs_ty.eql(rhs_ty, zcu)); |
| 1966 | 1986 | const int_info = lhs_ty.intInfo(zcu); |
| 1967 | 1987 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2304,8 +2324,127 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2304 | 2324 | } |
| 2305 | 2325 | |
| 2306 | 2326 | fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2307 | | _ = inst; |
| 2308 | | return self.fail("TODO implement airSubWithOverflow for {}", .{self.target.cpu.arch}); |
| 2327 | const zcu = self.bin_file.comp.module.?; |
| 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 | 2450 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -2644,8 +2783,25 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2644 | 2783 | |
| 2645 | 2784 | /// T to E!T |
| 2646 | 2785 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2786 | const zcu = self.bin_file.comp.module.?; |
| 2647 | 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 | 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 | 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 | 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 | 3598 | } |
| 3445 | 3599 | |
| 3446 | 3600 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3447 | | const zcu = self.bin_file.comp.module.?; |
| 3448 | 3601 | var arg_index = self.arg_index; |
| 3449 | 3602 | |
| 3450 | 3603 | // we skip over args that have no bits |
| ... | ... | @@ -3453,31 +3606,10 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3453 | 3606 | |
| 3454 | 3607 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 3455 | 3608 | const src_mcv = self.args[arg_index]; |
| 3456 | | |
| 3457 | 3609 | const arg_ty = self.typeOfIndex(inst); |
| 3458 | 3610 | |
| 3459 | | const dst_mcv = switch (src_mcv) { |
| 3460 | | .register => dst: { |
| 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 | | }; |
| 3611 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 3612 | try self.genCopy(arg_ty, dst_mcv, src_mcv); |
| 3481 | 3613 | |
| 3482 | 3614 | try self.genArgDbgInfo(inst, src_mcv); |
| 3483 | 3615 | break :result dst_mcv; |
| ... | ... | @@ -3612,7 +3744,68 @@ fn genCall( |
| 3612 | 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 | 3810 | // Due to incremental compilation, how function calls are generated depends |
| 3618 | 3811 | // on linking. |
| ... | ... | @@ -3715,9 +3908,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 3715 | 3908 | defer self.register_manager.unlockReg(lock); |
| 3716 | 3909 | |
| 3717 | 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 | 3914 | ret_ty, |
| 3720 | | .{ .register_offset = reg_off }, |
| 3721 | 3915 | .{ .air_ref = un_op }, |
| 3722 | 3916 | ); |
| 3723 | 3917 | }, |
| ... | ... | @@ -3745,6 +3939,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3745 | 3939 | switch (self.ret_mcv.short) { |
| 3746 | 3940 | .none => {}, |
| 3747 | 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 | 3943 | else => unreachable, |
| 3749 | 3944 | } |
| 3750 | 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 | 4253 | |
| 4059 | 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 | 4258 | switch (eu_mcv) { |
| 4064 | 4259 | .register => |reg| { |
| ... | ... | @@ -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 | 4280 | .cmp_neq, |
| 4086 | 4281 | return_mcv, |
| 4087 | 4282 | Type.u16, |
| 4088 | 4283 | .{ .immediate = 0 }, |
| 4089 | 4284 | Type.u16, |
| 4090 | 4285 | ); |
| 4091 | | |
| 4092 | | return return_mcv; |
| 4286 | }, |
| 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 | 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 | 5044 | const zcu = self.bin_file.comp.module.?; |
| 4840 | 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 | 5049 | switch (src_mcv) { |
| 4845 | 5050 | .dead => unreachable, |
| ... | ... | @@ -4924,7 +5129,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 4924 | 5129 | if (src_reg.id() == reg.id()) |
| 4925 | 5130 | return; |
| 4926 | 5131 | |
| 4927 | | // mov reg, src_reg |
| 5132 | // mv reg, src_reg |
| 4928 | 5133 | _ = try self.addInst(.{ |
| 4929 | 5134 | .tag = .pseudo, |
| 4930 | 5135 | .ops = .pseudo_mv, |
| ... | ... | @@ -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] }), |
| 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 | | }, |
| 5142 | .register_pair => return self.fail("genSetReg should we allow reg -> reg_pair?", .{}), |
| 4951 | 5143 | .load_frame => |frame| { |
| 4952 | 5144 | _ = try self.addInst(.{ |
| 4953 | 5145 | .tag = .pseudo, |
| ... | ... | @@ -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 | 5175 | _ = try self.addInst(.{ |
| 4971 | 5176 | .tag = .pseudo, |
| 4972 | 5177 | .ops = .pseudo_lea_rm, |
| 4973 | 5178 | .data = .{ .rm = .{ |
| 4974 | 5179 | .r = reg, |
| 4975 | | .m = .{ |
| 4976 | | .base = .{ .frame = frame.index }, |
| 4977 | | .mod = .{ |
| 4978 | | .rm = .{ |
| 4979 | | .size = self.memSize(ty), |
| 4980 | | .disp = frame.off, |
| 5180 | .m = switch (src_mcv) { |
| 5181 | .register_offset => |reg_off| .{ |
| 5182 | .base = .{ .reg = reg_off.reg }, |
| 5183 | .mod = .{ |
| 5184 | .rm = .{ |
| 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 | 5204 | .indirect => |reg_off| { |
| 4992 | 5205 | const load_tag: Mir.Inst.Tag = switch (abi_size) { |
| 4993 | 5206 | 1 => .lb, |
| ... | ... | @@ -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 | 5242 | .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)), |
| 5026 | 5243 | else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), |
| 5027 | 5244 | } |
| ... | ... | @@ -5052,7 +5269,6 @@ fn genSetMem( |
| 5052 | 5269 | src_mcv, |
| 5053 | 5270 | .{ .immediate = abi_size }, |
| 5054 | 5271 | ), |
| 5055 | | |
| 5056 | 5272 | .register_offset, |
| 5057 | 5273 | .memory, |
| 5058 | 5274 | .indirect, |
| ... | ... | @@ -5100,14 +5316,15 @@ fn genSetMem( |
| 5100 | 5316 | _ = try self.addInst(.{ |
| 5101 | 5317 | .tag = .pseudo, |
| 5102 | 5318 | .ops = .pseudo_store_rm, |
| 5103 | | .data = .{ |
| 5104 | | .rm = .{ .r = reg, .m = .{ |
| 5319 | .data = .{ .rm = .{ |
| 5320 | .r = reg, |
| 5321 | .m = .{ |
| 5105 | 5322 | .base = .{ .frame = frame_index }, |
| 5106 | 5323 | .mod = .{ .rm = .{ |
| 5107 | 5324 | .size = Memory.Size.fromByteSize(src_size), |
| 5108 | 5325 | } }, |
| 5109 | | } }, |
| 5110 | | }, |
| 5326 | }, |
| 5327 | } }, |
| 5111 | 5328 | }); |
| 5112 | 5329 | try self.genSetMem(base, disp, ty, frame_mcv); |
| 5113 | 5330 | try self.freeValue(frame_mcv); |