| ... | @@ -103178,6 +103178,19 @@ fn performReloc(self: *CodeGen, reloc: Mir.Inst.Index) void { | ... | @@ -103178,6 +103178,19 @@ fn performReloc(self: *CodeGen, reloc: Mir.Inst.Index) void { |
| 103178 | .pseudo_j_z_and_np_inst, .pseudo_j_nz_or_p_inst => {}, | 103178 | .pseudo_j_z_and_np_inst, .pseudo_j_nz_or_p_inst => {}, |
| 103179 | else => unreachable, | 103179 | else => unreachable, |
| 103180 | }, | 103180 | }, |
| | 103181 | .lea => switch (self.mir_instructions.items(.ops)[reloc]) { |
| | 103182 | .rm => { |
| | 103183 | const rx = self.mir_instructions.items(.data)[reloc].rx; |
| | 103184 | assert(rx.fixes == ._); |
| | 103185 | const mem_info: Mir.Memory.Info = @bitCast( |
| | 103186 | self.mir_extra.items[rx.payload + std.meta.fieldIndex(Mir.Memory, "info").?], |
| | 103187 | ); |
| | 103188 | assert(mem_info.base == .rip_inst); |
| | 103189 | self.mir_extra.items[rx.payload + std.meta.fieldIndex(Mir.Memory, "base").?] = next_inst; |
| | 103190 | return; |
| | 103191 | }, |
| | 103192 | else => unreachable, |
| | 103193 | }, |
| 103181 | else => unreachable, | 103194 | else => unreachable, |
| 103182 | } | 103195 | } |
| 103183 | self.mir_instructions.items(.data)[reloc].inst.inst = next_inst; | 103196 | self.mir_instructions.items(.data)[reloc].inst.inst = next_inst; |
| ... | @@ -103461,7 +103474,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -103461,7 +103474,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 103461 | // for the string, we still use the next u32 for the null terminator. | 103474 | // for the string, we still use the next u32 for the null terminator. |
| 103462 | extra_i += clobber.len / 4 + 1; | 103475 | extra_i += clobber.len / 4 + 1; |
| 103463 | | 103476 | |
| 103464 | if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) { | 103477 | if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory") or |
| | 103478 | std.mem.eql(u8, clobber, "fpsr") or std.mem.eql(u8, clobber, "fpcr") or |
| | 103479 | std.mem.eql(u8, clobber, "mxcsr") or std.mem.eql(u8, clobber, "dirflag")) |
| | 103480 | { |
| 103465 | // ok, sure | 103481 | // ok, sure |
| 103466 | } else if (std.mem.eql(u8, clobber, "cc") or | 103482 | } else if (std.mem.eql(u8, clobber, "cc") or |
| 103467 | std.mem.eql(u8, clobber, "flags") or | 103483 | std.mem.eql(u8, clobber, "flags") or |
| ... | @@ -103726,7 +103742,24 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -103726,7 +103742,24 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 103726 | else | 103742 | else |
| 103727 | .@"1"; | 103743 | .@"1"; |
| 103728 | if (sib_it.next()) |_| return self.fail("invalid memory operand: '{s}'", .{op_str}); | 103744 | if (sib_it.next()) |_| return self.fail("invalid memory operand: '{s}'", .{op_str}); |
| 103729 | op.* = if (std.mem.eql(u8, base_str, "%%dx") and index_str.len == 0) .{ .reg = .dx } else .{ .mem = .{ | 103745 | op.* = if (std.mem.eql(u8, base_str, "%%dx") and index_str.len == 0) |
| | 103746 | .{ .reg = .dx } |
| | 103747 | else if (std.mem.eql(u8, base_str, "%%rip") and index_str.len == 0 and |
| | 103748 | Label.isValid(.reference, op_str[0..open])) |
| | 103749 | op: { |
| | 103750 | const anon = std.ascii.isDigit(op_str[0]); |
| | 103751 | const label_gop = try labels.getOrPut(self.gpa, op_str[0..if (anon) 1 else open]); |
| | 103752 | if (anon and (op_str[1] == 'b' or op_str[1] == 'B') and !label_gop.found_existing) |
| | 103753 | return self.fail("undefined label: '{s}'", .{op_str}); |
| | 103754 | if (!label_gop.found_existing) label_gop.value_ptr.* = .{}; |
| | 103755 | const pending_relocs = &label_gop.value_ptr.pending_relocs; |
| | 103756 | if (if (anon) |
| | 103757 | op_str[1] == 'f' or op_str[1] == 'F' |
| | 103758 | else |
| | 103759 | !label_gop.found_existing or pending_relocs.items.len > 0) |
| | 103760 | try pending_relocs.append(self.gpa, @intCast(self.mir_instructions.len)); |
| | 103761 | break :op .{ .mem = .{ .base = .{ .rip_inst = label_gop.value_ptr.target } } }; |
| | 103762 | } else .{ .mem = .{ |
| 103730 | .base = if (base_str.len > 0) | 103763 | .base = if (base_str.len > 0) |
| 103731 | .{ .reg = parseRegName(base_str["%%".len..]) orelse | 103764 | .{ .reg = parseRegName(base_str["%%".len..]) orelse |
| 103732 | return self.fail("invalid base register: '{s}'", .{base_str}) } | 103765 | return self.fail("invalid base register: '{s}'", .{base_str}) } |
| ... | @@ -103770,9 +103803,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -103770,9 +103803,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 103770 | } else if (Label.isValid(.reference, op_str)) { | 103803 | } else if (Label.isValid(.reference, op_str)) { |
| 103771 | const anon = std.ascii.isDigit(op_str[0]); | 103804 | const anon = std.ascii.isDigit(op_str[0]); |
| 103772 | const label_gop = try labels.getOrPut(self.gpa, op_str[0..if (anon) 1 else op_str.len]); | 103805 | const label_gop = try labels.getOrPut(self.gpa, op_str[0..if (anon) 1 else op_str.len]); |
| 103773 | if (!label_gop.found_existing) label_gop.value_ptr.* = .{}; | | |
| 103774 | if (anon and (op_str[1] == 'b' or op_str[1] == 'B') and !label_gop.found_existing) | 103806 | if (anon and (op_str[1] == 'b' or op_str[1] == 'B') and !label_gop.found_existing) |
| 103775 | return self.fail("undefined label: '{s}'", .{op_str}); | 103807 | return self.fail("undefined label: '{s}'", .{op_str}); |
| | 103808 | if (!label_gop.found_existing) label_gop.value_ptr.* = .{}; |
| 103776 | const pending_relocs = &label_gop.value_ptr.pending_relocs; | 103809 | const pending_relocs = &label_gop.value_ptr.pending_relocs; |
| 103777 | if (if (anon) | 103810 | if (if (anon) |
| 103778 | op_str[1] == 'f' or op_str[1] == 'F' | 103811 | op_str[1] == 'f' or op_str[1] == 'F' |
| ... | @@ -105008,7 +105041,7 @@ fn genSetMem( | ... | @@ -105008,7 +105041,7 @@ fn genSetMem( |
| 105008 | .none => .{ .immediate = @bitCast(@as(i64, disp)) }, | 105041 | .none => .{ .immediate = @bitCast(@as(i64, disp)) }, |
| 105009 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, | 105042 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, |
| 105010 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, | 105043 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, |
| 105011 | .table => unreachable, | 105044 | .table, .rip_inst => unreachable, |
| 105012 | .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } }, | 105045 | .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } }, |
| 105013 | }; | 105046 | }; |
| 105014 | switch (src_mcv) { | 105047 | switch (src_mcv) { |
| ... | @@ -105118,7 +105151,7 @@ fn genSetMem( | ... | @@ -105118,7 +105151,7 @@ fn genSetMem( |
| 105118 | .index = frame_index, | 105151 | .index = frame_index, |
| 105119 | .off = disp, | 105152 | .off = disp, |
| 105120 | }).compare(.gte, src_align), | 105153 | }).compare(.gte, src_align), |
| 105121 | .table => unreachable, | 105154 | .table, .rip_inst => unreachable, |
| 105122 | .reloc => false, | 105155 | .reloc => false, |
| 105123 | })).write( | 105156 | })).write( |
| 105124 | self, | 105157 | self, |
| ... | @@ -105767,7 +105800,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -105767,7 +105800,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 105767 | const ptr_lock = switch (ptr_mem.base) { | 105800 | const ptr_lock = switch (ptr_mem.base) { |
| 105768 | .none, .frame, .reloc => null, | 105801 | .none, .frame, .reloc => null, |
| 105769 | .reg => |reg| self.register_manager.lockReg(reg), | 105802 | .reg => |reg| self.register_manager.lockReg(reg), |
| 105770 | .table => unreachable, | 105803 | .table, .rip_inst => unreachable, |
| 105771 | }; | 105804 | }; |
| 105772 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | 105805 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 105773 | | 105806 | |
| ... | @@ -105850,7 +105883,7 @@ fn atomicOp( | ... | @@ -105850,7 +105883,7 @@ fn atomicOp( |
| 105850 | const mem_lock = switch (ptr_mem.base) { | 105883 | const mem_lock = switch (ptr_mem.base) { |
| 105851 | .none, .frame, .reloc => null, | 105884 | .none, .frame, .reloc => null, |
| 105852 | .reg => |reg| self.register_manager.lockReg(reg), | 105885 | .reg => |reg| self.register_manager.lockReg(reg), |
| 105853 | .table => unreachable, | 105886 | .table, .rip_inst => unreachable, |
| 105854 | }; | 105887 | }; |
| 105855 | defer if (mem_lock) |lock| self.register_manager.unlockReg(lock); | 105888 | defer if (mem_lock) |lock| self.register_manager.unlockReg(lock); |
| 105856 | | 105889 | |