authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-03 20:51:49+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-04 01:21:24+01:00
log384b19716d097a20e3cdfb29a6f2d9c5816cbe7f
tree606d015300e90f22c18c422a4db6adad7400c498
parentd288f202a4c0623531ac3f641c850a8401e719f8

stage2: implement inline memcpy


1 files changed, 119 insertions(+), 9 deletions(-)

src/arch/x86_64/CodeGen.zig+119-9
...@@ -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 than2977 }
2978 // register size, and do general memcpy2978 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 }
29832985
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 }
29882991
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}
29933013
3014fn 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], value3105/// mov [reg], value
2996fn genSetPtrReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {3106fn genSetPtrReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {