authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-21 17:43:20+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-22 00:46:35+01:00
log5fb921539b47693f9b28fb414009395e0c7332d5
treeab58b93348a2ab10fc58dc1b7da20adf14786574
parent4a5e75245bc60f76a82bb6bcb70553bec7d7c4f2

stage2: do not copy args passed via stack into functions locals


1 files changed, 108 insertions(+), 154 deletions(-)

src/arch/x86_64/CodeGen.zig+108-154
...@@ -43,7 +43,7 @@ err_msg: ?*ErrorMsg,...@@ -43,7 +43,7 @@ err_msg: ?*ErrorMsg,
43args: []MCValue,43args: []MCValue,
44ret_mcv: MCValue,44ret_mcv: MCValue,
45fn_type: Type,45fn_type: Type,
46arg_index: usize,46arg_index: u32,
47src_loc: Module.SrcLoc,47src_loc: Module.SrcLoc,
48stack_align: u32,48stack_align: u32,
4949
...@@ -117,9 +117,9 @@ pub const MCValue = union(enum) {...@@ -117,9 +117,9 @@ pub const MCValue = union(enum) {
117 memory: u64,117 memory: u64,
118 /// The value is one of the stack variables.118 /// The value is one of the stack variables.
119 /// If the type is a pointer, it means the pointer address is in the stack at this offset.119 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
120 stack_offset: u32,120 stack_offset: i32,
121 /// The value is a pointer to one of the stack variables (payload is stack offset).121 /// The value is a pointer to one of the stack variables (payload is stack offset).
122 ptr_stack_offset: u32,122 ptr_stack_offset: i32,
123 /// The value is in the compare flags assuming an unsigned operation,123 /// The value is in the compare flags assuming an unsigned operation,
124 /// with this operator applied on top of it.124 /// with this operator applied on top of it.
125 compare_flags_unsigned: math.CompareOperator,125 compare_flags_unsigned: math.CompareOperator,
...@@ -485,13 +485,12 @@ fn gen(self: *Self) InnerError!void {...@@ -485,13 +485,12 @@ fn gen(self: *Self) InnerError!void {
485 });485 });
486486
487 // Adjust the stack487 // Adjust the stack
488 const stack_end = self.max_end_stack;488 if (self.max_end_stack > math.maxInt(i32)) {
489 if (stack_end > math.maxInt(i32)) {
490 return self.failSymbol("too much stack used in call parameters", .{});489 return self.failSymbol("too much stack used in call parameters", .{});
491 }490 }
492 // TODO we should reuse this mechanism to align the stack when calling any function even if491 // TODO we should reuse this mechanism to align the stack when calling any function even if
493 // we do not pass any args on the stack BUT we still push regs to stack with `push` inst.492 // we do not pass any args on the stack BUT we still push regs to stack with `push` inst.
494 const aligned_stack_end = @intCast(u32, mem.alignForward(stack_end, self.stack_align));493 const aligned_stack_end = @intCast(u32, mem.alignForward(self.max_end_stack, self.stack_align));
495 if (aligned_stack_end > 0) {494 if (aligned_stack_end > 0) {
496 self.mir_instructions.set(backpatch_stack_sub, .{495 self.mir_instructions.set(backpatch_stack_sub, .{
497 .tag = .sub,496 .tag = .sub,
...@@ -798,7 +797,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -798,7 +797,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
798 }797 }
799 }798 }
800 const stack_offset = try self.allocMem(inst, abi_size, abi_align);799 const stack_offset = try self.allocMem(inst, abi_size, abi_align);
801 return MCValue{ .stack_offset = stack_offset };800 return MCValue{ .stack_offset = @intCast(i32, stack_offset) };
802}801}
803802
804pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {803pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
...@@ -844,12 +843,12 @@ fn copyToNewRegisterWithExceptions(...@@ -844,12 +843,12 @@ fn copyToNewRegisterWithExceptions(
844843
845fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {844fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
846 const stack_offset = try self.allocMemPtr(inst);845 const stack_offset = try self.allocMemPtr(inst);
847 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });846 return self.finishAir(inst, .{ .ptr_stack_offset = @intCast(i32, stack_offset) }, .{ .none, .none, .none });
848}847}
849848
850fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {849fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
851 const stack_offset = try self.allocMemPtr(inst);850 const stack_offset = try self.allocMemPtr(inst);
852 return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none });851 return self.finishAir(inst, .{ .ptr_stack_offset = @intCast(i32, stack_offset) }, .{ .none, .none, .none });
853}852}
854853
855fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {854fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
...@@ -1409,7 +1408,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1409,7 +1408,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1409 .reg1 = addr_reg.to64(),1408 .reg1 = addr_reg.to64(),
1410 .reg2 = .rbp,1409 .reg2 = .rbp,
1411 }).encode(),1410 }).encode(),
1412 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + array_abi_size)) },1411 .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, array_abi_size))) },
1413 });1412 });
1414 },1413 },
1415 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),1414 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
...@@ -1613,7 +1612,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1613,7 +1612,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1613 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });1612 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
16141613
1615 return self.genInlineMemcpy(1614 return self.genInlineMemcpy(
1616 @bitCast(u32, -@intCast(i32, off + abi_size)),1615 -(off + @intCast(i32, abi_size)),
1617 .rbp,1616 .rbp,
1618 registerAlias(addr_reg, @divExact(reg.size(), 8)),1617 registerAlias(addr_reg, @divExact(reg.size(), 8)),
1619 count_reg.to64(),1618 count_reg.to64(),
...@@ -1770,10 +1769,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -1770,10 +1769,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
1770 return if (self.liveness.isUnused(inst)) .dead else result: {1769 return if (self.liveness.isUnused(inst)) .dead else result: {
1771 const mcv = try self.resolveInst(operand);1770 const mcv = try self.resolveInst(operand);
1772 const struct_ty = self.air.typeOf(operand).childType();1771 const struct_ty = self.air.typeOf(operand).childType();
1773 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));1772 const struct_size = @intCast(i32, struct_ty.abiSize(self.target.*));
1774 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));1773 const struct_field_offset = @intCast(i32, struct_ty.structFieldOffset(index, self.target.*));
1775 const struct_field_ty = struct_ty.structFieldType(index);1774 const struct_field_ty = struct_ty.structFieldType(index);
1776 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));1775 const struct_field_size = @intCast(i32, struct_field_ty.abiSize(self.target.*));
17771776
1778 switch (mcv) {1777 switch (mcv) {
1779 .ptr_stack_offset => |off| {1778 .ptr_stack_offset => |off| {
...@@ -1793,10 +1792,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1793,10 +1792,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1793 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1792 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1794 const mcv = try self.resolveInst(operand);1793 const mcv = try self.resolveInst(operand);
1795 const struct_ty = self.air.typeOf(operand);1794 const struct_ty = self.air.typeOf(operand);
1796 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));1795 const struct_size = @intCast(i32, struct_ty.abiSize(self.target.*));
1797 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));1796 const struct_field_offset = @intCast(i32, struct_ty.structFieldOffset(index, self.target.*));
1798 const struct_field_ty = struct_ty.structFieldType(index);1797 const struct_field_ty = struct_ty.structFieldType(index);
1799 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));1798 const struct_field_size = @intCast(i32, struct_field_ty.abiSize(self.target.*));
18001799
1801 switch (mcv) {1800 switch (mcv) {
1802 .stack_offset => |off| {1801 .stack_offset => |off| {
...@@ -1960,7 +1959,7 @@ fn genBinMathOpMir(...@@ -1960,7 +1959,7 @@ fn genBinMathOpMir(
1960 return self.fail("stack offset too large", .{});1959 return self.fail("stack offset too large", .{});
1961 }1960 }
1962 const abi_size = dst_ty.abiSize(self.target.*);1961 const abi_size = dst_ty.abiSize(self.target.*);
1963 const adj_off = off + abi_size;1962 const adj_off = off + @intCast(i32, abi_size);
1964 _ = try self.addInst(.{1963 _ = try self.addInst(.{
1965 .tag = mir_tag,1964 .tag = mir_tag,
1966 .ops = (Mir.Ops{1965 .ops = (Mir.Ops{
...@@ -1968,7 +1967,7 @@ fn genBinMathOpMir(...@@ -1968,7 +1967,7 @@ fn genBinMathOpMir(
1968 .reg2 = .rbp,1967 .reg2 = .rbp,
1969 .flags = 0b01,1968 .flags = 0b01,
1970 }).encode(),1969 }).encode(),
1971 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },1970 .data = .{ .imm = @bitCast(u32, -adj_off) },
1972 });1971 });
1973 },1972 },
1974 .compare_flags_unsigned => {1973 .compare_flags_unsigned => {
...@@ -1987,7 +1986,7 @@ fn genBinMathOpMir(...@@ -1987,7 +1986,7 @@ fn genBinMathOpMir(
1987 if (abi_size > 8) {1986 if (abi_size > 8) {
1988 return self.fail("TODO implement ADD/SUB/CMP for stack dst with large ABI", .{});1987 return self.fail("TODO implement ADD/SUB/CMP for stack dst with large ABI", .{});
1989 }1988 }
1990 const adj_off = off + abi_size;1989 const adj_off = off + @intCast(i32, abi_size);
19911990
1992 switch (src_mcv) {1991 switch (src_mcv) {
1993 .none => unreachable,1992 .none => unreachable,
...@@ -2003,7 +2002,7 @@ fn genBinMathOpMir(...@@ -2003,7 +2002,7 @@ fn genBinMathOpMir(
2003 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),2002 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
2004 .flags = 0b10,2003 .flags = 0b10,
2005 }).encode(),2004 }).encode(),
2006 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },2005 .data = .{ .imm = @bitCast(u32, -adj_off) },
2007 });2006 });
2008 },2007 },
2009 .immediate => |imm| {2008 .immediate => |imm| {
...@@ -2024,7 +2023,7 @@ fn genBinMathOpMir(...@@ -2024,7 +2023,7 @@ fn genBinMathOpMir(
2024 else => unreachable,2023 else => unreachable,
2025 };2024 };
2026 const payload = try self.addExtra(Mir.ImmPair{2025 const payload = try self.addExtra(Mir.ImmPair{
2027 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),2026 .dest_off = @bitCast(u32, -adj_off),
2028 .operand = @truncate(u32, imm),2027 .operand = @truncate(u32, imm),
2029 });2028 });
2030 _ = try self.addInst(.{2029 _ = try self.addInst(.{
...@@ -2162,7 +2161,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -2162,7 +2161,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2162 const mcv = self.args[arg_index];2161 const mcv = self.args[arg_index];
2163 const payload = try self.addExtra(Mir.ArgDbgInfo{2162 const payload = try self.addExtra(Mir.ArgDbgInfo{
2164 .air_inst = inst,2163 .air_inst = inst,
2165 .arg_index = @truncate(u32, arg_index), // TODO can arg_index: u32?2164 .arg_index = arg_index,
2166 });2165 });
2167 _ = try self.addInst(.{2166 _ = try self.addInst(.{
2168 .tag = .arg_dbg_info,2167 .tag = .arg_dbg_info,
...@@ -2178,56 +2177,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -2178,56 +2177,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2178 self.register_manager.getRegAssumeFree(reg.to64(), inst);2177 self.register_manager.getRegAssumeFree(reg.to64(), inst);
2179 break :blk mcv;2178 break :blk mcv;
2180 },2179 },
2181 .stack_offset => |off| {2180 .stack_offset => {
2182 const ty = self.air.typeOfIndex(inst);2181 const ty = self.air.typeOfIndex(inst);
2183 const abi_size = ty.abiSize(self.target.*);2182 const abi_size = ty.abiSize(self.target.*);
21842183 const off = @intCast(i32, (arg_index + 1) * abi_size) + 16;
2185 if (abi_size <= 8) {2184 break :blk MCValue{ .stack_offset = -off };
2186 const reg = try self.register_manager.allocReg(inst, &.{});
2187 _ = try self.addInst(.{
2188 .tag = .mov,
2189 .ops = (Mir.Ops{
2190 .reg1 = registerAlias(reg, @intCast(u32, abi_size)),
2191 .reg2 = .rbp,
2192 .flags = 0b01,
2193 }).encode(),
2194 .data = .{ .imm = off + 16 },
2195 });
2196 break :blk .{ .register = reg };
2197 }
2198
2199 // TODO copy ellision
2200 const dst_mcv = try self.allocRegOrMem(inst, false);
2201 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });
2202 const addr_reg = regs[0];
2203 const count_reg = regs[1];
2204 const tmp_reg = regs[2];
2205
2206 try self.register_manager.getReg(.rax, null);
2207 try self.register_manager.getReg(.rcx, null);
2208
2209 _ = try self.addInst(.{
2210 .tag = .lea,
2211 .ops = (Mir.Ops{
2212 .reg1 = addr_reg.to64(),
2213 .reg2 = .rbp,
2214 }).encode(),
2215 .data = .{ .imm = off + 16 },
2216 });
2217
2218 // TODO allow for abi_size to be u64
2219 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
2220 try self.genInlineMemcpy(
2221 @bitCast(u32, -@intCast(i32, dst_mcv.stack_offset + abi_size)),
2222 .rbp,
2223 addr_reg.to64(),
2224 count_reg.to64(),
2225 tmp_reg.to8(),
2226 );
2227
2228 break :blk dst_mcv;
2229 },2185 },
2230 else => unreachable,2186 else => return self.fail("TODO implement arg for {}", .{mcv}),
2231 }2187 }
2232 };2188 };
22332189
...@@ -2252,64 +2208,6 @@ fn airFence(self: *Self) !void {...@@ -2252,64 +2208,6 @@ fn airFence(self: *Self) !void {
2252 //return self.finishAirBookkeeping();2208 //return self.finishAirBookkeeping();
2253}2209}
22542210
2255fn genSetStackArg(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
2256 const abi_size = ty.abiSize(self.target.*);
2257 switch (mcv) {
2258 .dead => unreachable,
2259 .ptr_embedded_in_code => unreachable,
2260 .unreach, .none => return,
2261 .register => |reg| {
2262 _ = try self.addInst(.{
2263 .tag = .mov,
2264 .ops = (Mir.Ops{
2265 .reg1 = .rsp,
2266 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
2267 .flags = 0b10,
2268 }).encode(),
2269 .data = .{ .imm = @bitCast(u32, -@intCast(i32, stack_offset + abi_size)) },
2270 });
2271 },
2272 .ptr_stack_offset => {
2273 const reg = try self.copyToTmpRegister(ty, mcv);
2274 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
2275 },
2276 .stack_offset => |unadjusted_off| {
2277 if (abi_size <= 8) {
2278 const reg = try self.copyToTmpRegister(ty, mcv);
2279 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
2280 }
2281
2282 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });
2283 const addr_reg = regs[0];
2284 const count_reg = regs[1];
2285 const tmp_reg = regs[2];
2286
2287 try self.register_manager.getReg(.rax, null);
2288 try self.register_manager.getReg(.rcx, null);
2289
2290 _ = try self.addInst(.{
2291 .tag = .lea,
2292 .ops = (Mir.Ops{
2293 .reg1 = addr_reg.to64(),
2294 .reg2 = .rbp,
2295 }).encode(),
2296 .data = .{ .imm = @bitCast(u32, -@intCast(i32, unadjusted_off + abi_size)) },
2297 });
2298
2299 // TODO allow for abi_size to be u64
2300 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
2301 try self.genInlineMemcpy(
2302 @bitCast(u32, -@intCast(i32, stack_offset + abi_size)),
2303 .rsp,
2304 addr_reg.to64(),
2305 count_reg.to64(),
2306 tmp_reg.to8(),
2307 );
2308 },
2309 else => return self.fail("TODO implement args on stack for {}", .{mcv}),
2310 }
2311}
2312
2313fn airCall(self: *Self, inst: Air.Inst.Index) !void {2211fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2314 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2212 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2315 const callee = pl_op.operand;2213 const callee = pl_op.operand;
...@@ -2326,12 +2224,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2326,12 +2224,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2326 var info = try self.resolveCallingConventionValues(fn_ty);2224 var info = try self.resolveCallingConventionValues(fn_ty);
2327 defer info.deinit(self);2225 defer info.deinit(self);
23282226
2329 var count: usize = info.args.len;
2330 var stack_adjustment: u32 = 0;2227 var stack_adjustment: u32 = 0;
2331 while (count > 0) : (count -= 1) {2228 for (args) |arg, arg_i| {
2332 const arg_i = count - 1;
2333 const mc_arg = info.args[arg_i];2229 const mc_arg = info.args[arg_i];
2334 const arg = args[arg_i];
2335 const arg_ty = self.air.typeOf(arg);2230 const arg_ty = self.air.typeOf(arg);
2336 const arg_mcv = try self.resolveInst(args[arg_i]);2231 const arg_mcv = try self.resolveInst(args[arg_i]);
2337 // Here we do not use setRegOrMem even though the logic is similar, because2232 // Here we do not use setRegOrMem even though the logic is similar, because
...@@ -2343,9 +2238,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2343,9 +2238,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2343 try self.genSetReg(arg_ty, reg, arg_mcv);2238 try self.genSetReg(arg_ty, reg, arg_mcv);
2344 },2239 },
2345 .stack_offset => |off| {2240 .stack_offset => |off| {
2346 const abi_size = arg_ty.abiSize(self.target.*);2241 const abi_size = @intCast(u32, arg_ty.abiSize(self.target.*));
2347 try self.genSetStackArg(arg_ty, off, arg_mcv);2242 try self.genSetStackArg(arg_ty, off, arg_mcv);
2348 stack_adjustment += @intCast(u32, abi_size);2243 stack_adjustment += abi_size;
2349 },2244 },
2350 .ptr_stack_offset => {2245 .ptr_stack_offset => {
2351 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});2246 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
...@@ -3257,7 +3152,65 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -3257,7 +3152,65 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
3257 }3152 }
3258}3153}
32593154
3260fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {3155fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void {
3156 const abi_size = ty.abiSize(self.target.*);
3157 switch (mcv) {
3158 .dead => unreachable,
3159 .ptr_embedded_in_code => unreachable,
3160 .unreach, .none => return,
3161 .register => |reg| {
3162 _ = try self.addInst(.{
3163 .tag = .mov,
3164 .ops = (Mir.Ops{
3165 .reg1 = .rsp,
3166 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
3167 .flags = 0b10,
3168 }).encode(),
3169 .data = .{ .imm = @bitCast(u32, -(stack_offset + @intCast(i32, abi_size))) },
3170 });
3171 },
3172 .ptr_stack_offset => {
3173 const reg = try self.copyToTmpRegister(ty, mcv);
3174 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3175 },
3176 .stack_offset => |unadjusted_off| {
3177 if (abi_size <= 8) {
3178 const reg = try self.copyToTmpRegister(ty, mcv);
3179 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3180 }
3181
3182 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });
3183 const addr_reg = regs[0];
3184 const count_reg = regs[1];
3185 const tmp_reg = regs[2];
3186
3187 try self.register_manager.getReg(.rax, null);
3188 try self.register_manager.getReg(.rcx, null);
3189
3190 _ = try self.addInst(.{
3191 .tag = .lea,
3192 .ops = (Mir.Ops{
3193 .reg1 = addr_reg.to64(),
3194 .reg2 = .rbp,
3195 }).encode(),
3196 .data = .{ .imm = @bitCast(u32, -(unadjusted_off + @intCast(i32, abi_size))) },
3197 });
3198
3199 // TODO allow for abi_size to be u64
3200 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
3201 try self.genInlineMemcpy(
3202 -(stack_offset + @intCast(i32, abi_size)),
3203 .rsp,
3204 addr_reg.to64(),
3205 count_reg.to64(),
3206 tmp_reg.to8(),
3207 );
3208 },
3209 else => return self.fail("TODO implement args on stack for {}", .{mcv}),
3210 }
3211}
3212
3213fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void {
3261 switch (mcv) {3214 switch (mcv) {
3262 .dead => unreachable,3215 .dead => unreachable,
3263 .ptr_embedded_in_code => unreachable,3216 .ptr_embedded_in_code => unreachable,
...@@ -3284,7 +3237,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3284,7 +3237,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3284 },3237 },
3285 .immediate => |x_big| {3238 .immediate => |x_big| {
3286 const abi_size = ty.abiSize(self.target.*);3239 const abi_size = ty.abiSize(self.target.*);
3287 const adj_off = stack_offset + abi_size;3240 const adj_off = stack_offset + @intCast(i32, abi_size);
3288 if (adj_off > 128) {3241 if (adj_off > 128) {
3289 return self.fail("TODO implement set stack variable with large stack offset", .{});3242 return self.fail("TODO implement set stack variable with large stack offset", .{});
3290 }3243 }
...@@ -3294,7 +3247,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3294,7 +3247,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3294 // offset from rbp, which is at the top of the stack frame.3247 // offset from rbp, which is at the top of the stack frame.
3295 // mov [rbp+offset], immediate3248 // mov [rbp+offset], immediate
3296 const payload = try self.addExtra(Mir.ImmPair{3249 const payload = try self.addExtra(Mir.ImmPair{
3297 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),3250 .dest_off = @bitCast(u32, -adj_off),
3298 .operand = @truncate(u32, x_big),3251 .operand = @truncate(u32, x_big),
3299 });3252 });
3300 _ = try self.addInst(.{3253 _ = try self.addInst(.{
...@@ -3314,7 +3267,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3314,7 +3267,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3314 8 => {3267 8 => {
3315 // We have a positive stack offset value but we want a twos complement negative3268 // We have a positive stack offset value but we want a twos complement negative
3316 // offset from rbp, which is at the top of the stack frame.3269 // offset from rbp, which is at the top of the stack frame.
3317 const negative_offset = -@intCast(i32, adj_off);3270 const negative_offset = -adj_off;
33183271
3319 // 64 bit write to memory would take two mov's anyways so we3272 // 64 bit write to memory would take two mov's anyways so we
3320 // insted just use two 32 bit writes to avoid register allocation3273 // insted just use two 32 bit writes to avoid register allocation
...@@ -3357,7 +3310,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3357,7 +3310,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3357 return self.fail("stack offset too large", .{});3310 return self.fail("stack offset too large", .{});
3358 }3311 }
3359 const abi_size = ty.abiSize(self.target.*);3312 const abi_size = ty.abiSize(self.target.*);
3360 const adj_off = stack_offset + abi_size;3313 const adj_off = stack_offset + @intCast(i32, abi_size);
3361 _ = try self.addInst(.{3314 _ = try self.addInst(.{
3362 .tag = .mov,3315 .tag = .mov,
3363 .ops = (Mir.Ops{3316 .ops = (Mir.Ops{
...@@ -3365,7 +3318,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3365,7 +3318,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3365 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),3318 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
3366 .flags = 0b10,3319 .flags = 0b10,
3367 }).encode(),3320 }).encode(),
3368 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },3321 .data = .{ .imm = @bitCast(u32, -adj_off) },
3369 });3322 });
3370 },3323 },
3371 .memory, .embedded_in_code => {3324 .memory, .embedded_in_code => {
...@@ -3391,7 +3344,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3391,7 +3344,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3391 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3344 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3392 }3345 }
33933346
3394 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });3347 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx, .rbp });
3395 const addr_reg = regs[0];3348 const addr_reg = regs[0];
3396 const count_reg = regs[1];3349 const count_reg = regs[1];
3397 const tmp_reg = regs[2];3350 const tmp_reg = regs[2];
...@@ -3405,14 +3358,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3405,14 +3358,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3405 .reg1 = addr_reg.to64(),3358 .reg1 = addr_reg.to64(),
3406 .reg2 = .rbp,3359 .reg2 = .rbp,
3407 }).encode(),3360 }).encode(),
3408 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + abi_size)) },3361 .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, abi_size))) },
3409 });3362 });
34103363
3411 // TODO allow for abi_size to be u643364 // TODO allow for abi_size to be u64
3412 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });3365 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
34133366
3414 return self.genInlineMemcpy(3367 return self.genInlineMemcpy(
3415 @bitCast(u32, -@intCast(i32, stack_offset + abi_size)),3368 -(stack_offset + @intCast(i32, abi_size)),
3416 .rbp,3369 .rbp,
3417 addr_reg.to64(),3370 addr_reg.to64(),
3418 count_reg.to64(),3371 count_reg.to64(),
...@@ -3424,7 +3377,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3424,7 +3377,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
34243377
3425fn genInlineMemcpy(3378fn genInlineMemcpy(
3426 self: *Self,3379 self: *Self,
3427 stack_offset: u32,3380 stack_offset: i32,
3428 stack_reg: Register,3381 stack_reg: Register,
3429 addr_reg: Register,3382 addr_reg: Register,
3430 count_reg: Register,3383 count_reg: Register,
...@@ -3482,7 +3435,7 @@ fn genInlineMemcpy(...@@ -3482,7 +3435,7 @@ fn genInlineMemcpy(
3482 .reg1 = stack_reg,3435 .reg1 = stack_reg,
3483 .reg2 = tmp_reg.to8(),3436 .reg2 = tmp_reg.to8(),
3484 }).encode(),3437 }).encode(),
3485 .data = .{ .imm = stack_offset },3438 .data = .{ .imm = @bitCast(u32, stack_offset) },
3486 });3439 });
34873440
3488 // add rcx, 13441 // add rcx, 1
...@@ -3523,14 +3476,14 @@ fn genInlineMemcpy(...@@ -3523,14 +3476,14 @@ fn genInlineMemcpy(
3523 try self.performReloc(loop_reloc);3476 try self.performReloc(loop_reloc);
3524}3477}
35253478
3526fn genInlineMemset(self: *Self, ty: Type, stack_offset: u32, value: MCValue) InnerError!void {3479fn genInlineMemset(self: *Self, ty: Type, stack_offset: i32, value: MCValue) InnerError!void {
3527 try self.register_manager.getReg(.rax, null);3480 try self.register_manager.getReg(.rax, null);
3528 const abi_size = ty.abiSize(self.target.*);3481 const abi_size = ty.abiSize(self.target.*);
3529 const adj_off = stack_offset + abi_size;3482 const adj_off = stack_offset + @intCast(i32, abi_size);
3530 if (adj_off > 128) {3483 if (adj_off > 128) {
3531 return self.fail("TODO inline memset with large stack offset", .{});3484 return self.fail("TODO inline memset with large stack offset", .{});
3532 }3485 }
3533 const negative_offset = @bitCast(u32, -@intCast(i32, adj_off));3486 const negative_offset = @bitCast(u32, -adj_off);
35343487
3535 // We are actually counting `abi_size` bytes; however, we reuse the index register3488 // We are actually counting `abi_size` bytes; however, we reuse the index register
3536 // as both the counter and offset scaler, hence we need to subtract one from `abi_size`3489 // as both the counter and offset scaler, hence we need to subtract one from `abi_size`
...@@ -3621,7 +3574,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3621,7 +3574,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3621 const ptr_abi_size = ty.abiSize(self.target.*);3574 const ptr_abi_size = ty.abiSize(self.target.*);
3622 const elem_ty = ty.childType();3575 const elem_ty = ty.childType();
3623 const elem_abi_size = elem_ty.abiSize(self.target.*);3576 const elem_abi_size = elem_ty.abiSize(self.target.*);
3624 const off = unadjusted_off + elem_abi_size;3577 const off = unadjusted_off + @intCast(i32, elem_abi_size);
3625 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {3578 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {
3626 return self.fail("stack offset too large", .{});3579 return self.fail("stack offset too large", .{});
3627 }3580 }
...@@ -3631,7 +3584,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3631,7 +3584,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3631 .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)),3584 .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)),
3632 .reg2 = .rbp,3585 .reg2 = .rbp,
3633 }).encode(),3586 }).encode(),
3634 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },3587 .data = .{ .imm = @bitCast(u32, -off) },
3635 });3588 });
3636 },3589 },
3637 .ptr_embedded_in_code => unreachable,3590 .ptr_embedded_in_code => unreachable,
...@@ -3818,7 +3771,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3818,7 +3771,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3818 },3771 },
3819 .stack_offset => |unadjusted_off| {3772 .stack_offset => |unadjusted_off| {
3820 const abi_size = ty.abiSize(self.target.*);3773 const abi_size = ty.abiSize(self.target.*);
3821 const off = unadjusted_off + abi_size;3774 const off = unadjusted_off + @intCast(i32, abi_size);
3822 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {3775 if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) {
3823 return self.fail("stack offset too large", .{});3776 return self.fail("stack offset too large", .{});
3824 }3777 }
...@@ -3829,7 +3782,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3829,7 +3782,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3829 .reg2 = .rbp,3782 .reg2 = .rbp,
3830 .flags = 0b01,3783 .flags = 0b01,
3831 }).encode(),3784 }).encode(),
3832 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },3785 .data = .{ .imm = @bitCast(u32, -off) },
3833 });3786 });
3834 },3787 },
3835 }3788 }
...@@ -3854,7 +3807,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -3854,7 +3807,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
3854 const array_ty = ptr_ty.childType();3807 const array_ty = ptr_ty.childType();
3855 const array_len = array_ty.arrayLenIncludingSentinel();3808 const array_len = array_ty.arrayLenIncludingSentinel();
3856 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {3809 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
3857 const stack_offset = try self.allocMem(inst, 16, 16);3810 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
3858 try self.genSetStack(ptr_ty, stack_offset + 8, ptr);3811 try self.genSetStack(ptr_ty, stack_offset + 8, ptr);
3859 try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len });3812 try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len });
3860 break :blk .{ .stack_offset = stack_offset };3813 break :blk .{ .stack_offset = stack_offset };
...@@ -4235,6 +4188,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4235,6 +4188,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4235 var next_stack_offset: u32 = 0;4188 var next_stack_offset: u32 = 0;
4236 var count: usize = param_types.len;4189 var count: usize = param_types.len;
4237 while (count > 0) : (count -= 1) {4190 while (count > 0) : (count -= 1) {
4191 // for (param_types) |ty, i| {
4238 const i = count - 1;4192 const i = count - 1;
4239 const ty = param_types[i];4193 const ty = param_types[i];
4240 if (!ty.hasCodeGenBits()) {4194 if (!ty.hasCodeGenBits()) {
...@@ -4253,7 +4207,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4253,7 +4207,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4253 // such as ptr and len of slices as separate registers.4207 // such as ptr and len of slices as separate registers.
4254 // TODO: also we need to honor the C ABI for relevant types rather than passing on4208 // TODO: also we need to honor the C ABI for relevant types rather than passing on
4255 // the stack here.4209 // the stack here.
4256 result.args[i] = .{ .stack_offset = next_stack_offset };4210 result.args[i] = .{ .stack_offset = @intCast(i32, next_stack_offset) };
4257 next_stack_offset += param_size;4211 next_stack_offset += param_size;
4258 }4212 }
4259 }4213 }