| ... | ... | @@ -2970,27 +2970,137 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2970 | 2970 | .data = .{ .imm = -@intCast(i32, adj_off) }, |
| 2971 | 2971 | }); |
| 2972 | 2972 | }, |
| 2973 | | .stack_offset, |
| 2974 | | .embedded_in_code, |
| 2975 | | .memory, |
| 2976 | | => { |
| 2977 | | // TODO this needs to get improved to support types greater than |
| 2978 | | // register size, and do general memcpy |
| 2979 | | if (mcv == .stack_offset and mcv.stack_offset == stack_offset) { |
| 2973 | .memory, .embedded_in_code => { |
| 2974 | if (ty.abiSize(self.target.*) <= 8) { |
| 2975 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 2976 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 2977 | } |
| 2978 | return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); |
| 2979 | }, |
| 2980 | .stack_offset => |unadjusted_off| { |
| 2981 | if (stack_offset == unadjusted_off) { |
| 2980 | 2982 | // Copy stack variable to itself; nothing to do. |
| 2981 | 2983 | return; |
| 2982 | 2984 | } |
| 2983 | 2985 | |
| 2984 | | if (ty.abiSize(self.target.*) <= 8) { |
| 2986 | const abi_size = ty.abiSize(self.target.*); |
| 2987 | if (abi_size <= 8) { |
| 2985 | 2988 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 2986 | 2989 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 2987 | 2990 | } |
| 2988 | 2991 | |
| 2989 | | return self.fail("TODO implement memcpy for ABI size {} > 8", .{ty.abiSize(self.target.*)}); |
| 2992 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{}); |
| 2993 | const addr_reg = regs[0]; |
| 2994 | const len_reg = regs[1]; |
| 2995 | |
| 2996 | const off = unadjusted_off + abi_size; |
| 2997 | _ = try self.addInst(.{ |
| 2998 | .tag = .lea, |
| 2999 | .ops = (Mir.Ops{ |
| 3000 | .reg1 = addr_reg.to64(), |
| 3001 | .reg2 = .rbp, |
| 3002 | }).encode(), |
| 3003 | .data = .{ .imm = -@intCast(i32, off) }, |
| 3004 | }); |
| 3005 | |
| 3006 | // TODO allow for abi_size to be u64 |
| 3007 | try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3008 | |
| 3009 | return self.genInlineMemcpy(-@intCast(i32, off), addr_reg.to64(), len_reg.to64()); |
| 2990 | 3010 | }, |
| 2991 | 3011 | } |
| 2992 | 3012 | } |
| 2993 | 3013 | |
| 3014 | fn genInlineMemcpy(self: *Self, stack_offset: i32, addr_reg: Register, len_reg: Register) InnerError!void { |
| 3015 | try self.register_manager.getReg(.rax, null); |
| 3016 | try self.register_manager.getReg(.rcx, null); |
| 3017 | const tmp_reg = try self.register_manager.allocReg(null, &.{ addr_reg, len_reg, .rax, .rcx }); |
| 3018 | |
| 3019 | // mov rcx, 0 |
| 3020 | _ = try self.addInst(.{ |
| 3021 | .tag = .mov, |
| 3022 | .ops = (Mir.Ops{ |
| 3023 | .reg1 = .rcx, |
| 3024 | }).encode(), |
| 3025 | .data = .{ .imm = 0 }, |
| 3026 | }); |
| 3027 | |
| 3028 | // mov rax, 0 |
| 3029 | _ = try self.addInst(.{ |
| 3030 | .tag = .mov, |
| 3031 | .ops = (Mir.Ops{ |
| 3032 | .reg1 = .rax, |
| 3033 | }).encode(), |
| 3034 | .data = .{ .imm = 0 }, |
| 3035 | }); |
| 3036 | |
| 3037 | // loop: |
| 3038 | // cmp rcx, len |
| 3039 | const loop_start = try self.addInst(.{ |
| 3040 | .tag = .cmp, |
| 3041 | .ops = (Mir.Ops{ |
| 3042 | .reg1 = .rcx, |
| 3043 | .reg2 = len_reg, |
| 3044 | }).encode(), |
| 3045 | .data = undefined, |
| 3046 | }); |
| 3047 | |
| 3048 | // jge end |
| 3049 | const loop_reloc = try self.addInst(.{ |
| 3050 | .tag = .cond_jmp_above_below, |
| 3051 | .ops = (Mir.Ops{ .flags = 0b00 }).encode(), |
| 3052 | .data = .{ .inst = undefined }, |
| 3053 | }); |
| 3054 | |
| 3055 | // mov tmp, [addr + rcx] |
| 3056 | _ = try self.addInst(.{ |
| 3057 | .tag = .mov_scale_src, |
| 3058 | .ops = (Mir.Ops{ |
| 3059 | .reg1 = tmp_reg.to8(), |
| 3060 | .reg2 = addr_reg, |
| 3061 | }).encode(), |
| 3062 | .data = .{ .imm = 0 }, |
| 3063 | }); |
| 3064 | |
| 3065 | // mov [stack_offset + rax], tmp |
| 3066 | _ = try self.addInst(.{ |
| 3067 | .tag = .mov_scale_dst, |
| 3068 | .ops = (Mir.Ops{ |
| 3069 | .reg1 = .rbp, |
| 3070 | .reg2 = tmp_reg.to8(), |
| 3071 | }).encode(), |
| 3072 | .data = .{ .imm = stack_offset }, |
| 3073 | }); |
| 3074 | |
| 3075 | // add rcx, 1 |
| 3076 | _ = try self.addInst(.{ |
| 3077 | .tag = .add, |
| 3078 | .ops = (Mir.Ops{ |
| 3079 | .reg1 = .rcx, |
| 3080 | }).encode(), |
| 3081 | .data = .{ .imm = 1 }, |
| 3082 | }); |
| 3083 | |
| 3084 | // add rax, 1 |
| 3085 | _ = try self.addInst(.{ |
| 3086 | .tag = .add, |
| 3087 | .ops = (Mir.Ops{ |
| 3088 | .reg1 = .rax, |
| 3089 | }).encode(), |
| 3090 | .data = .{ .imm = 1 }, |
| 3091 | }); |
| 3092 | |
| 3093 | // jmp loop |
| 3094 | _ = try self.addInst(.{ |
| 3095 | .tag = .jmp, |
| 3096 | .ops = (Mir.Ops{ .flags = 0b00 }).encode(), |
| 3097 | .data = .{ .inst = loop_start }, |
| 3098 | }); |
| 3099 | |
| 3100 | // end: |
| 3101 | try self.performReloc(loop_reloc); |
| 3102 | } |
| 3103 | |
| 2994 | 3104 | /// Set pointee via pointer stored in a register. |
| 2995 | 3105 | /// mov [reg], value |
| 2996 | 3106 | fn genSetPtrReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |