| ... | ... | @@ -807,7 +807,7 @@ pub fn generate( |
| 807 | 807 | .lower = .{ |
| 808 | 808 | .allocator = bin_file.allocator, |
| 809 | 809 | .mir = mir, |
| 810 | | .target = &bin_file.options.target, |
| 810 | .cc = abi.resolveCallingConvention(fn_info.cc, function.target.*), |
| 811 | 811 | .src_loc = src_loc, |
| 812 | 812 | }, |
| 813 | 813 | .bin_file = bin_file, |
| ... | ... | @@ -893,7 +893,7 @@ pub fn generateLazy( |
| 893 | 893 | .lower = .{ |
| 894 | 894 | .allocator = bin_file.allocator, |
| 895 | 895 | .mir = mir, |
| 896 | | .target = &bin_file.options.target, |
| 896 | .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), |
| 897 | 897 | .src_loc = src_loc, |
| 898 | 898 | }, |
| 899 | 899 | .bin_file = bin_file, |
| ... | ... | @@ -980,6 +980,7 @@ fn formatWipMir( |
| 980 | 980 | _: std.fmt.FormatOptions, |
| 981 | 981 | writer: anytype, |
| 982 | 982 | ) @TypeOf(writer).Error!void { |
| 983 | const mod = data.self.bin_file.options.module.?; |
| 983 | 984 | var lower = Lower{ |
| 984 | 985 | .allocator = data.self.gpa, |
| 985 | 986 | .mir = .{ |
| ... | ... | @@ -987,7 +988,7 @@ fn formatWipMir( |
| 987 | 988 | .extra = data.self.mir_extra.items, |
| 988 | 989 | .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(), |
| 989 | 990 | }, |
| 990 | | .target = data.self.target, |
| 991 | .cc = mod.typeToFunc(data.self.fn_type).?.cc, |
| 991 | 992 | .src_loc = data.self.src_loc, |
| 992 | 993 | }; |
| 993 | 994 | for ((lower.lowerMir(data.inst) catch |err| switch (err) { |
| ... | ... | @@ -1680,7 +1681,7 @@ fn gen(self: *Self) InnerError!void { |
| 1680 | 1681 | try self.asmRegister(.{ ._, .pop }, .rbp); |
| 1681 | 1682 | try self.asmOpOnly(.{ ._, .ret }); |
| 1682 | 1683 | |
| 1683 | | const frame_layout = try self.computeFrameLayout(); |
| 1684 | const frame_layout = try self.computeFrameLayout(cc); |
| 1684 | 1685 | const need_frame_align = frame_layout.stack_mask != math.maxInt(u32); |
| 1685 | 1686 | const need_stack_adjust = frame_layout.stack_adjust > 0; |
| 1686 | 1687 | const need_save_reg = frame_layout.save_reg_list.count() > 0; |
| ... | ... | @@ -2075,7 +2076,8 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2075 | 2076 | const enum_ty = lazy_sym.ty; |
| 2076 | 2077 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)}); |
| 2077 | 2078 | |
| 2078 | | const param_regs = abi.getCAbiIntParamRegs(self.target.*); |
| 2079 | const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*); |
| 2080 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| 2079 | 2081 | const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*); |
| 2080 | 2082 | defer for (param_locks) |lock| self.register_manager.unlockReg(lock); |
| 2081 | 2083 | |
| ... | ... | @@ -2208,7 +2210,7 @@ fn setFrameLoc( |
| 2208 | 2210 | offset.* += self.frame_allocs.items(.abi_size)[frame_i]; |
| 2209 | 2211 | } |
| 2210 | 2212 | |
| 2211 | | fn computeFrameLayout(self: *Self) !FrameLayout { |
| 2213 | fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayout { |
| 2212 | 2214 | const frame_allocs_len = self.frame_allocs.len; |
| 2213 | 2215 | try self.frame_locs.resize(self.gpa, frame_allocs_len); |
| 2214 | 2216 | const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count); |
| ... | ... | @@ -2240,7 +2242,8 @@ fn computeFrameLayout(self: *Self) !FrameLayout { |
| 2240 | 2242 | // Create list of registers to save in the prologue. |
| 2241 | 2243 | // TODO handle register classes |
| 2242 | 2244 | var save_reg_list = Mir.RegisterList{}; |
| 2243 | | const callee_preserved_regs = abi.getCalleePreservedRegs(self.target.*); |
| 2245 | const callee_preserved_regs = |
| 2246 | abi.getCalleePreservedRegs(abi.resolveCallingConvention(cc, self.target.*)); |
| 2244 | 2247 | for (callee_preserved_regs) |reg| { |
| 2245 | 2248 | if (self.register_manager.isRegAllocated(reg)) { |
| 2246 | 2249 | save_reg_list.push(callee_preserved_regs, reg); |
| ... | ... | @@ -8477,8 +8480,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 8477 | 8480 | try arg_locks.ensureTotalCapacity(16); |
| 8478 | 8481 | defer for (arg_locks.items) |arg_lock| if (arg_lock) |lock| self.register_manager.unlockReg(lock); |
| 8479 | 8482 | |
| 8480 | | var call_info = |
| 8481 | | try self.resolveCallingConventionValues(fn_info, var_args, .call_frame); |
| 8483 | var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame); |
| 8482 | 8484 | defer call_info.deinit(self); |
| 8483 | 8485 | |
| 8484 | 8486 | // We need a properly aligned and sized call frame to be able to call this function. |
| ... | ... | @@ -8497,7 +8499,9 @@ fn genCall(self: *Self, info: union(enum) { |
| 8497 | 8499 | } |
| 8498 | 8500 | |
| 8499 | 8501 | try self.spillEflagsIfOccupied(); |
| 8500 | | try self.spillRegisters(abi.getCallerPreservedRegs(self.target.*)); |
| 8502 | try self.spillRegisters(abi.getCallerPreservedRegs( |
| 8503 | abi.resolveCallingConvention(fn_info.cc, self.target.*), |
| 8504 | )); |
| 8501 | 8505 | |
| 8502 | 8506 | // set stack arguments first because this can clobber registers |
| 8503 | 8507 | // also clobber spill arguments as we go |
| ... | ... | @@ -11727,6 +11731,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 11727 | 11731 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 11728 | 11732 | const inst_ty = self.typeOfIndex(inst); |
| 11729 | 11733 | const enum_ty = self.typeOf(un_op); |
| 11734 | const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*); |
| 11730 | 11735 | |
| 11731 | 11736 | // We need a properly aligned and sized call frame to be able to call this function. |
| 11732 | 11737 | { |
| ... | ... | @@ -11744,9 +11749,9 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 11744 | 11749 | } |
| 11745 | 11750 | |
| 11746 | 11751 | try self.spillEflagsIfOccupied(); |
| 11747 | | try self.spillRegisters(abi.getCallerPreservedRegs(self.target.*)); |
| 11752 | try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc)); |
| 11748 | 11753 | |
| 11749 | | const param_regs = abi.getCAbiIntParamRegs(self.target.*); |
| 11754 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| 11750 | 11755 | |
| 11751 | 11756 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 11752 | 11757 | try self.genSetReg(param_regs[0], Type.usize, dst_mcv.address()); |
| ... | ... | @@ -12523,23 +12528,25 @@ fn resolveCallingConventionValues( |
| 12523 | 12528 | |
| 12524 | 12529 | const ret_ty = fn_info.return_type.toType(); |
| 12525 | 12530 | |
| 12531 | const resolved_cc = abi.resolveCallingConvention(cc, self.target.*); |
| 12526 | 12532 | switch (cc) { |
| 12527 | 12533 | .Naked => { |
| 12528 | 12534 | assert(result.args.len == 0); |
| 12529 | 12535 | result.return_value = InstTracking.init(.unreach); |
| 12530 | 12536 | result.stack_align = .@"8"; |
| 12531 | 12537 | }, |
| 12532 | | .C => { |
| 12538 | .C, .SysV, .Win64 => { |
| 12533 | 12539 | var param_reg_i: usize = 0; |
| 12534 | 12540 | var param_sse_reg_i: usize = 0; |
| 12535 | 12541 | result.stack_align = .@"16"; |
| 12536 | 12542 | |
| 12537 | | switch (self.target.os.tag) { |
| 12538 | | .windows => { |
| 12543 | switch (resolved_cc) { |
| 12544 | .SysV => {}, |
| 12545 | .Win64 => { |
| 12539 | 12546 | // Align the stack to 16bytes before allocating shadow stack space (if any). |
| 12540 | 12547 | result.stack_byte_count += @intCast(4 * Type.usize.abiSize(mod)); |
| 12541 | 12548 | }, |
| 12542 | | else => {}, |
| 12549 | else => unreachable, |
| 12543 | 12550 | } |
| 12544 | 12551 | |
| 12545 | 12552 | // Return values |
| ... | ... | @@ -12549,13 +12556,14 @@ fn resolveCallingConventionValues( |
| 12549 | 12556 | // TODO: is this even possible for C calling convention? |
| 12550 | 12557 | result.return_value = InstTracking.init(.none); |
| 12551 | 12558 | } else { |
| 12552 | | const classes = switch (self.target.os.tag) { |
| 12553 | | .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, mod)}, |
| 12554 | | else => mem.sliceTo(&abi.classifySystemV(ret_ty, mod, .ret), .none), |
| 12559 | const classes = switch (resolved_cc) { |
| 12560 | .SysV => mem.sliceTo(&abi.classifySystemV(ret_ty, mod, .ret), .none), |
| 12561 | .Win64 => &[1]abi.Class{abi.classifyWindows(ret_ty, mod)}, |
| 12562 | else => unreachable, |
| 12555 | 12563 | }; |
| 12556 | 12564 | for ( |
| 12557 | 12565 | classes, |
| 12558 | | abi.getCAbiIntReturnRegs(self.target.*)[0..classes.len], |
| 12566 | abi.getCAbiIntReturnRegs(resolved_cc)[0..classes.len], |
| 12559 | 12567 | 0.., |
| 12560 | 12568 | ) |class, ret_reg, ret_reg_i| { |
| 12561 | 12569 | result.return_value = switch (classes[0]) { |
| ... | ... | @@ -12577,7 +12585,7 @@ fn resolveCallingConventionValues( |
| 12577 | 12585 | .memory => switch (ret_reg_i) { |
| 12578 | 12586 | 0 => ret: { |
| 12579 | 12587 | const ret_indirect_reg = |
| 12580 | | abi.getCAbiIntParamRegs(self.target.*)[param_reg_i]; |
| 12588 | abi.getCAbiIntParamRegs(resolved_cc)[param_reg_i]; |
| 12581 | 12589 | param_reg_i += 1; |
| 12582 | 12590 | break :ret .{ |
| 12583 | 12591 | .short = .{ .indirect = .{ .reg = ret_reg } }, |
| ... | ... | @@ -12603,8 +12611,8 @@ fn resolveCallingConventionValues( |
| 12603 | 12611 | }; |
| 12604 | 12612 | for (classes, 0..) |class, class_i| { |
| 12605 | 12613 | switch (class) { |
| 12606 | | .integer => if (param_reg_i < abi.getCAbiIntParamRegs(self.target.*).len) { |
| 12607 | | const param_reg = abi.getCAbiIntParamRegs(self.target.*)[param_reg_i]; |
| 12614 | .integer => if (param_reg_i < abi.getCAbiIntParamRegs(resolved_cc).len) { |
| 12615 | const param_reg = abi.getCAbiIntParamRegs(resolved_cc)[param_reg_i]; |
| 12608 | 12616 | param_reg_i += 1; |
| 12609 | 12617 | |
| 12610 | 12618 | arg.* = switch (class_i) { |
| ... | ... | @@ -12661,13 +12669,13 @@ fn resolveCallingConventionValues( |
| 12661 | 12669 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 12662 | 12670 | result.return_value = InstTracking.init(.none); |
| 12663 | 12671 | } else { |
| 12664 | | const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0]; |
| 12672 | const ret_reg = abi.getCAbiIntReturnRegs(resolved_cc)[0]; |
| 12665 | 12673 | const ret_ty_size: u31 = @intCast(ret_ty.abiSize(mod)); |
| 12666 | 12674 | if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) { |
| 12667 | 12675 | const aliased_reg = registerAlias(ret_reg, ret_ty_size); |
| 12668 | 12676 | result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none }; |
| 12669 | 12677 | } else { |
| 12670 | | const ret_indirect_reg = abi.getCAbiIntParamRegs(self.target.*)[0]; |
| 12678 | const ret_indirect_reg = abi.getCAbiIntParamRegs(resolved_cc)[0]; |
| 12671 | 12679 | result.return_value = .{ |
| 12672 | 12680 | .short = .{ .indirect = .{ .reg = ret_reg } }, |
| 12673 | 12681 | .long = .{ .indirect = .{ .reg = ret_indirect_reg } }, |