| ... | @@ -2970,27 +2970,137 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2970,27 +2970,137 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2970 | .data = .{ .imm = -@intCast(i32, adj_off) }, | 2970 | .data = .{ .imm = -@intCast(i32, adj_off) }, |
| 2971 | }); | 2971 | }); |
| 2972 | }, | 2972 | }, |
| 2973 | .stack_offset, | 2973 | .memory, .embedded_in_code => { |
| 2974 | .embedded_in_code, | 2974 | if (ty.abiSize(self.target.*) <= 8) { |
| 2975 | .memory, | 2975 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 2976 | => { | 2976 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 2977 | // TODO this needs to get improved to support types greater than | 2977 | } |
| 2978 | // register size, and do general memcpy | 2978 | return self.fail("TODO implement memcpy for setting stack from {}", .{mcv}); |
| 2979 | if (mcv == .stack_offset and mcv.stack_offset == stack_offset) { | 2979 | }, |
| | 2980 | .stack_offset => |unadjusted_off| { |
| | 2981 | if (stack_offset == unadjusted_off) { |
| 2980 | // Copy stack variable to itself; nothing to do. | 2982 | // Copy stack variable to itself; nothing to do. |
| 2981 | return; | 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 | const reg = try self.copyToTmpRegister(ty, mcv); | 2988 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 2986 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 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 | /// Set pointee via pointer stored in a register. | 3104 | /// Set pointee via pointer stored in a register. |
| 2995 | /// mov [reg], value | 3105 | /// mov [reg], value |
| 2996 | fn genSetPtrReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 3106 | fn genSetPtrReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |