| ... | ... | @@ -73,7 +73,7 @@ end_di_column: u32, |
| 73 | 73 | /// The value is an offset into the `Function` `code` from the beginning. |
| 74 | 74 | /// To perform the reloc, write 32-bit signed little-endian integer |
| 75 | 75 | /// which is a relative jump, based on the address following the reloc. |
| 76 | | exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty, |
| 76 | epilogue_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty, |
| 77 | 77 | |
| 78 | 78 | reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined, |
| 79 | 79 | const_tracking: ConstTrackingMap = .empty, |
| ... | ... | @@ -928,7 +928,7 @@ pub fn generate( |
| 928 | 928 | function.blocks.deinit(gpa); |
| 929 | 929 | function.inst_tracking.deinit(gpa); |
| 930 | 930 | function.const_tracking.deinit(gpa); |
| 931 | | function.exitlude_jump_relocs.deinit(gpa); |
| 931 | function.epilogue_relocs.deinit(gpa); |
| 932 | 932 | function.mir_instructions.deinit(gpa); |
| 933 | 933 | function.mir_extra.deinit(gpa); |
| 934 | 934 | function.mir_table.deinit(gpa); |
| ... | ... | @@ -2193,24 +2193,24 @@ fn gen(self: *CodeGen) InnerError!void { |
| 2193 | 2193 | |
| 2194 | 2194 | try self.genBody(self.air.getMainBody()); |
| 2195 | 2195 | |
| 2196 | | // TODO can single exitlude jump reloc be elided? What if it is not at the end of the code? |
| 2197 | | // Example: |
| 2198 | | // pub fn main() void { |
| 2199 | | // maybeErr() catch return; |
| 2200 | | // unreachable; |
| 2201 | | // } |
| 2202 | | // Eliding the reloc will cause a miscompilation in this case. |
| 2203 | | for (self.exitlude_jump_relocs.items) |jmp_reloc| { |
| 2204 | | self.mir_instructions.items(.data)[jmp_reloc].inst.inst = |
| 2205 | | @intCast(self.mir_instructions.len); |
| 2206 | | } |
| 2207 | | |
| 2208 | | try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); |
| 2209 | | const backpatch_stack_dealloc = try self.asmPlaceholder(); |
| 2210 | | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); |
| 2211 | | try self.asmRegister(.{ ._, .pop }, .rbp); |
| 2212 | | try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8)); |
| 2213 | | try self.asmOpOnly(.{ ._, .ret }); |
| 2196 | const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: { |
| 2197 | const epilogue_relocs_last_index = self.epilogue_relocs.items.len - 1; |
| 2198 | for (if (self.epilogue_relocs.items[epilogue_relocs_last_index] == self.mir_instructions.len - 1) epilogue_relocs: { |
| 2199 | _ = self.mir_instructions.pop(); |
| 2200 | break :epilogue_relocs self.epilogue_relocs.items[0..epilogue_relocs_last_index]; |
| 2201 | } else self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc); |
| 2202 | |
| 2203 | try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); |
| 2204 | const backpatch_stack_dealloc = try self.asmPlaceholder(); |
| 2205 | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); |
| 2206 | try self.asmRegister(.{ ._, .pop }, .rbp); |
| 2207 | try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8)); |
| 2208 | try self.asmOpOnly(.{ ._, .ret }); |
| 2209 | break :epilogue .{ |
| 2210 | .backpatch_stack_dealloc = backpatch_stack_dealloc, |
| 2211 | .backpatch_pop_callee_preserved_regs = backpatch_pop_callee_preserved_regs, |
| 2212 | }; |
| 2213 | } else null; |
| 2214 | 2214 | |
| 2215 | 2215 | const frame_layout = try self.computeFrameLayout(fn_info.cc); |
| 2216 | 2216 | const need_frame_align = frame_layout.stack_mask != std.math.maxInt(u32); |
| ... | ... | @@ -2280,8 +2280,8 @@ fn gen(self: *CodeGen) InnerError!void { |
| 2280 | 2280 | }); |
| 2281 | 2281 | } |
| 2282 | 2282 | } |
| 2283 | | if (need_frame_align or need_stack_adjust) { |
| 2284 | | self.mir_instructions.set(backpatch_stack_dealloc, switch (-frame_layout.save_reg_list.size(self.target)) { |
| 2283 | if (epilogue) |e| if (need_frame_align or need_stack_adjust) { |
| 2284 | self.mir_instructions.set(e.backpatch_stack_dealloc, switch (-frame_layout.save_reg_list.size(self.target)) { |
| 2285 | 2285 | 0 => .{ |
| 2286 | 2286 | .tag = .mov, |
| 2287 | 2287 | .ops = .rr, |
| ... | ... | @@ -2305,14 +2305,14 @@ fn gen(self: *CodeGen) InnerError!void { |
| 2305 | 2305 | } }, |
| 2306 | 2306 | }, |
| 2307 | 2307 | }); |
| 2308 | | } |
| 2308 | }; |
| 2309 | 2309 | if (need_save_reg) { |
| 2310 | 2310 | self.mir_instructions.set(backpatch_push_callee_preserved_regs, .{ |
| 2311 | 2311 | .tag = .pseudo, |
| 2312 | 2312 | .ops = .pseudo_push_reg_list, |
| 2313 | 2313 | .data = .{ .reg_list = frame_layout.save_reg_list }, |
| 2314 | 2314 | }); |
| 2315 | | self.mir_instructions.set(backpatch_pop_callee_preserved_regs, .{ |
| 2315 | if (epilogue) |e| self.mir_instructions.set(e.backpatch_pop_callee_preserved_regs, .{ |
| 2316 | 2316 | .tag = .pseudo, |
| 2317 | 2317 | .ops = .pseudo_pop_reg_list, |
| 2318 | 2318 | .data = .{ .reg_list = frame_layout.save_reg_list }, |
| ... | ... | @@ -10007,8 +10007,8 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 10007 | 10007 | const ret_reg = param_regs[0]; |
| 10008 | 10008 | const enum_mcv = MCValue{ .register = param_regs[1] }; |
| 10009 | 10009 | |
| 10010 | | const exitlude_jump_relocs = try self.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(zcu)); |
| 10011 | | defer self.gpa.free(exitlude_jump_relocs); |
| 10010 | const epilogue_relocs = try self.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(zcu)); |
| 10011 | defer self.gpa.free(epilogue_relocs); |
| 10012 | 10012 | |
| 10013 | 10013 | const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 10014 | 10014 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); |
| ... | ... | @@ -10017,7 +10017,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 10017 | 10017 | |
| 10018 | 10018 | var data_off: i32 = 0; |
| 10019 | 10019 | const tag_names = enum_ty.enumFields(zcu); |
| 10020 | | for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| { |
| 10020 | for (epilogue_relocs, 0..) |*epilogue_reloc, tag_index| { |
| 10021 | 10021 | const tag_name_len = tag_names.get(ip)[tag_index].length(ip); |
| 10022 | 10022 | const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)); |
| 10023 | 10023 | const tag_mcv = try self.genTypedValue(tag_val); |
| ... | ... | @@ -10033,7 +10033,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 10033 | 10033 | ); |
| 10034 | 10034 | try self.genSetMem(.{ .reg = ret_reg }, 8, .usize, .{ .immediate = tag_name_len }, .{}); |
| 10035 | 10035 | |
| 10036 | | exitlude_jump_reloc.* = try self.asmJmpReloc(undefined); |
| 10036 | epilogue_reloc.* = try self.asmJmpReloc(undefined); |
| 10037 | 10037 | self.performReloc(skip_reloc); |
| 10038 | 10038 | |
| 10039 | 10039 | data_off += @intCast(tag_name_len + 1); |
| ... | ... | @@ -10041,7 +10041,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 10041 | 10041 | |
| 10042 | 10042 | try self.asmOpOnly(.{ ._, .ud2 }); |
| 10043 | 10043 | |
| 10044 | | for (exitlude_jump_relocs) |reloc| self.performReloc(reloc); |
| 10044 | for (epilogue_relocs) |reloc| self.performReloc(reloc); |
| 10045 | 10045 | try self.asmOpOnly(.{ ._, .ret }); |
| 10046 | 10046 | }, |
| 10047 | 10047 | else => return self.fail( |
| ... | ... | @@ -20114,7 +20114,7 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 20114 | 20114 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 20115 | 20115 | // which is available if the jump is 127 bytes or less forward. |
| 20116 | 20116 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| 20117 | | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 20117 | try self.epilogue_relocs.append(self.gpa, jmp_reloc); |
| 20118 | 20118 | } |
| 20119 | 20119 | |
| 20120 | 20120 | fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -20134,7 +20134,7 @@ fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 20134 | 20134 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 20135 | 20135 | // which is available if the jump is 127 bytes or less forward. |
| 20136 | 20136 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| 20137 | | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 20137 | try self.epilogue_relocs.append(self.gpa, jmp_reloc); |
| 20138 | 20138 | } |
| 20139 | 20139 | |
| 20140 | 20140 | fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !void { |
| ... | ... | @@ -24486,7 +24486,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 24486 | 24486 | self.register_manager.lockRegAssumeUnused(dst_regs[0]), |
| 24487 | 24487 | self.register_manager.lockRegAssumeUnused(dst_regs[1]), |
| 24488 | 24488 | }, |
| 24489 | | else => .{ null, null }, |
| 24489 | else => @splat(null), |
| 24490 | 24490 | }; |
| 24491 | 24491 | for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 24492 | 24492 | |
| ... | ... | @@ -24625,7 +24625,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 24625 | 24625 | self.register_manager.lockRegAssumeUnused(dst_regs[0]), |
| 24626 | 24626 | self.register_manager.lockReg(dst_regs[1]), |
| 24627 | 24627 | }, |
| 24628 | | else => .{ null, null }, |
| 24628 | else => @splat(null), |
| 24629 | 24629 | }; |
| 24630 | 24630 | for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 24631 | 24631 | |
| ... | ... | @@ -24636,7 +24636,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 24636 | 24636 | self.register_manager.lockRegAssumeUnused(src_regs[0]), |
| 24637 | 24637 | self.register_manager.lockRegAssumeUnused(src_regs[1]), |
| 24638 | 24638 | }, |
| 24639 | | else => .{ null, null }, |
| 24639 | else => @splat(null), |
| 24640 | 24640 | }; |
| 24641 | 24641 | for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 24642 | 24642 | |