@@ -103178,6 +103178,19 @@ fn performReloc(self: *CodeGen, reloc: Mir.Inst.Index) void {
103178
103178
.pseudo_j_z_and_np_inst, .pseudo_j_nz_or_p_inst => {},
103179
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
103194
else => unreachable,
103182
103195
}
103183
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
103474
// for the string, we still use the next u32 for the null terminator.
103462
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
103481
// ok, sure
103466
103482
} else if (std.mem.eql(u8, clobber, "cc") or
103467
103483
std.mem.eql(u8, clobber, "flags") or
@@ -103726,7 +103742,24 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
103726
103742
else
103727
103743
.@"1";
103728
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
103763
.base = if (base_str.len > 0)
103731
103764
.{ .reg = parseRegName(base_str["%%".len..]) orelse
103732
103765
return self.fail("invalid base register: '{s}'", .{base_str}) }
@@ -103770,9 +103803,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
103770
103803
} else if (Label.isValid(.reference, op_str)) {
103771
103804
const anon = std.ascii.isDigit(op_str[0]);
103772
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
103806
if (anon and (op_str[1] == 'b' or op_str[1] == 'B') and !label_gop.found_existing)
103775
103807
return self.fail("undefined label: '{s}'", .{op_str});
103808
+ if (!label_gop.found_existing) label_gop.value_ptr.* = .{};
103776
103809
const pending_relocs = &label_gop.value_ptr.pending_relocs;
103777
103810
if (if (anon)
103778
103811
op_str[1] == 'f' or op_str[1] == 'F'
@@ -105008,7 +105041,7 @@ fn genSetMem(
105008
105041
.none => .{ .immediate = @bitCast(@as(i64, disp)) },
105009
105042
.reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
105010
105043
.frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
105011
- .table => unreachable,
105044
+ .table, .rip_inst => unreachable,
105012
105045
.reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
105013
105046
};
105014
105047
switch (src_mcv) {
@@ -105118,7 +105151,7 @@ fn genSetMem(
105118
105151
.index = frame_index,
105119
105152
.off = disp,
105120
105153
}).compare(.gte, src_align),
105121
- .table => unreachable,
105154
+ .table, .rip_inst => unreachable,
105122
105155
.reloc => false,
105123
105156
})).write(
105124
105157
self,
@@ -105767,7 +105800,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
105767
105800
const ptr_lock = switch (ptr_mem.base) {
105768
105801
.none, .frame, .reloc => null,
105769
105802
.reg => |reg| self.register_manager.lockReg(reg),
105770
- .table => unreachable,
105803
+ .table, .rip_inst => unreachable,
105771
105804
};
105772
105805
defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
105773
105806
@@ -105850,7 +105883,7 @@ fn atomicOp(
105850
105883
const mem_lock = switch (ptr_mem.base) {
105851
105884
.none, .frame, .reloc => null,
105852
105885
.reg => |reg| self.register_manager.lockReg(reg),
105853
- .table => unreachable,
105886
+ .table, .rip_inst => unreachable,
105854
105887
};
105855
105888
defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);
105856
105889
0 commit comments