| ... | @@ -983,7 +983,14 @@ pub const Value = struct { | ... | @@ -983,7 +983,14 @@ pub const Value = struct { |
| 983 | while (part_it.next()) |part_vi| { | 983 | while (part_it.next()) |part_vi| { |
| 984 | const part_offset, const part_size = part_vi.positionInParent(isel); | 984 | const part_offset, const part_size = part_vi.positionInParent(isel); |
| 985 | const part_mat = try part_vi.mat(isel, .{}); | 985 | const part_mat = try part_vi.mat(isel, .{}); |
| 986 | try isel.moveLoc(def_loc, part_offset, part_mat.loc(), 0, part_size, .preserved); | 986 | try isel.moveLoc( |
| | 987 | def_loc, |
| | 988 | part_offset, |
| | 989 | part_mat.loc(), |
| | 990 | 0, |
| | 991 | part_size, |
| | 992 | .{ .dst_prot = .preserved }, |
| | 993 | ); |
| 987 | try part_mat.finish(isel); | 994 | try part_mat.finish(isel); |
| 988 | if (reextend_parts) | 995 | if (reextend_parts) |
| 989 | try part_vi.reextend(isel, def_ext); | 996 | try part_vi.reextend(isel, def_ext); |
| ... | @@ -1003,7 +1010,7 @@ pub const Value = struct { | ... | @@ -1003,7 +1010,7 @@ pub const Value = struct { |
| 1003 | const def_loc = def_vi.takeLocationMarkWritten(isel) orelse return; | 1010 | const def_loc = def_vi.takeLocationMarkWritten(isel) orelse return; |
| 1004 | const def_offset, const def_size = def_vi.positionInParent(isel); | 1011 | const def_offset, const def_size = def_vi.positionInParent(isel); |
| 1005 | const parent_mat = try parent_vi.mat(isel, .{}); | 1012 | const parent_mat = try parent_vi.mat(isel, .{}); |
| 1006 | try isel.moveLoc(def_loc, 0, parent_mat.loc(), def_offset, def_size, .none); | 1013 | try isel.moveLoc(def_loc, 0, parent_mat.loc(), def_offset, def_size, .{}); |
| 1007 | try parent_mat.finish(isel); | 1014 | try parent_mat.finish(isel); |
| 1008 | } | 1015 | } |
| 1009 | | 1016 | |
| ... | @@ -1115,7 +1122,7 @@ pub const Value = struct { | ... | @@ -1115,7 +1122,7 @@ pub const Value = struct { |
| 1115 | .{ .stack_slot = .{ .base = base_reg, .offset = 0 } }, | 1122 | .{ .stack_slot = .{ .base = base_reg, .offset = 0 } }, |
| 1116 | offset, | 1123 | offset, |
| 1117 | vi.size(isel), | 1124 | vi.size(isel), |
| 1118 | .none, | 1125 | .{ .atomic = opts.atomic }, |
| 1119 | ); | 1126 | ); |
| 1120 | return true; | 1127 | return true; |
| 1121 | } | 1128 | } |
| ... | @@ -1167,7 +1174,7 @@ pub const Value = struct { | ... | @@ -1167,7 +1174,7 @@ pub const Value = struct { |
| 1167 | const src_loc = src_mat.loc(); | 1174 | const src_loc = src_mat.loc(); |
| 1168 | if (!std.meta.eql(loc, src_loc)) { | 1175 | if (!std.meta.eql(loc, src_loc)) { |
| 1169 | loc.markRegWritten(isel); | 1176 | loc.markRegWritten(isel); |
| 1170 | try isel.moveLoc(loc, 0, src_mat.loc(), 0, copy_size, .none); | 1177 | try isel.moveLoc(loc, 0, src_mat.loc(), 0, copy_size, .{}); |
| 1171 | } | 1178 | } |
| 1172 | try src_mat.finish(isel); | 1179 | try src_mat.finish(isel); |
| 1173 | } | 1180 | } |
| ... | @@ -1271,7 +1278,14 @@ pub const Value = struct { | ... | @@ -1271,7 +1278,14 @@ pub const Value = struct { |
| 1271 | _ = try isel.fillReg(src_reg); | 1278 | _ = try isel.fillReg(src_reg); |
| 1272 | } | 1279 | } |
| 1273 | // TODO: replace reextending def_part_vi to .zero_ext with moveLoc .wipe when applicable | 1280 | // TODO: replace reextending def_part_vi to .zero_ext with moveLoc .wipe when applicable |
| 1274 | try isel.moveLoc(def_part_loc, dst_offset, src_loc, src_offset, mat_size, .preserved); | 1281 | try isel.moveLoc( |
| | 1282 | def_part_loc, |
| | 1283 | dst_offset, |
| | 1284 | src_loc, |
| | 1285 | src_offset, |
| | 1286 | mat_size, |
| | 1287 | .{ .dst_prot = .preserved }, |
| | 1288 | ); |
| 1275 | } | 1289 | } |
| 1276 | } | 1290 | } |
| 1277 | if (maybe_def_addr_mat) |def_addr_mat| try def_addr_mat.finish(isel); | 1291 | if (maybe_def_addr_mat) |def_addr_mat| try def_addr_mat.finish(isel); |
| ... | @@ -1279,6 +1293,8 @@ pub const Value = struct { | ... | @@ -1279,6 +1293,8 @@ pub const Value = struct { |
| 1279 | | 1293 | |
| 1280 | const MemoryAccessOptions = struct { | 1294 | const MemoryAccessOptions = struct { |
| 1281 | @"volatile": bool = false, | 1295 | @"volatile": bool = false, |
| | 1296 | // Atomicity. This is unrelated to ordering and visibility. |
| | 1297 | atomic: bool = false, |
| 1282 | }; | 1298 | }; |
| 1283 | | 1299 | |
| 1284 | const MatOptions = struct { | 1300 | const MatOptions = struct { |
| ... | @@ -1478,7 +1494,6 @@ pub const Value = struct { | ... | @@ -1478,7 +1494,6 @@ pub const Value = struct { |
| 1478 | opts: MemoryAccessOptions, | 1494 | opts: MemoryAccessOptions, |
| 1479 | ) !void { | 1495 | ) !void { |
| 1480 | wip_mir_log.debug(" | # store {f} -> [${t}, #{d}]", .{ vi, base_reg, offset }); | 1496 | wip_mir_log.debug(" | # store {f} -> [${t}, #{d}]", .{ vi, base_reg, offset }); |
| 1481 | _ = opts; | | |
| 1482 | | 1497 | |
| 1483 | const hint_stack: Indirect = if (std.math.cast(@FieldType(Indirect, "offset"), offset)) |stack_off| | 1498 | const hint_stack: Indirect = if (std.math.cast(@FieldType(Indirect, "offset"), offset)) |stack_off| |
| 1484 | .{ .base = base_reg, .offset = stack_off } | 1499 | .{ .base = base_reg, .offset = stack_off } |
| ... | @@ -1491,7 +1506,7 @@ pub const Value = struct { | ... | @@ -1491,7 +1506,7 @@ pub const Value = struct { |
| 1491 | value_mat.loc(), | 1506 | value_mat.loc(), |
| 1492 | 0, | 1507 | 0, |
| 1493 | vi.size(isel), | 1508 | vi.size(isel), |
| 1494 | .none, | 1509 | .{ .atomic = opts.atomic }, |
| 1495 | ); | 1510 | ); |
| 1496 | try value_mat.finish(isel); | 1511 | try value_mat.finish(isel); |
| 1497 | } | 1512 | } |
| ... | @@ -1543,7 +1558,7 @@ pub const Value = struct { | ... | @@ -1543,7 +1558,7 @@ pub const Value = struct { |
| 1543 | .size = @intCast(part_size), | 1558 | .size = @intCast(part_size), |
| 1544 | .extension = part_vi.extension(isel), | 1559 | .extension = part_vi.extension(isel), |
| 1545 | }); | 1560 | }); |
| 1546 | try isel.moveLoc(.{ .register = part_ra }, 0, value_mat.loc(), 0, part_size, .none); | 1561 | try isel.moveLoc(.{ .register = part_ra }, 0, value_mat.loc(), 0, part_size, .{}); |
| 1547 | try value_mat.finish(isel); | 1562 | try value_mat.finish(isel); |
| 1548 | } | 1563 | } |
| 1549 | | 1564 | |
| ... | @@ -1558,7 +1573,7 @@ pub const Value = struct { | ... | @@ -1558,7 +1573,7 @@ pub const Value = struct { |
| 1558 | .size = @intCast(part_size), | 1573 | .size = @intCast(part_size), |
| 1559 | .extension = part_vi.extension(isel), | 1574 | .extension = part_vi.extension(isel), |
| 1560 | }); | 1575 | }); |
| 1561 | try isel.moveLoc(.{ .stack_slot = layout_part_stack }, 0, value_mat.loc(), 0, part_size, .none); | 1576 | try isel.moveLoc(.{ .stack_slot = layout_part_stack }, 0, value_mat.loc(), 0, part_size, .{}); |
| 1562 | try value_mat.finish(isel); | 1577 | try value_mat.finish(isel); |
| 1563 | } | 1578 | } |
| 1564 | } | 1579 | } |
| ... | @@ -1569,7 +1584,7 @@ pub const Value = struct { | ... | @@ -1569,7 +1584,7 @@ pub const Value = struct { |
| 1569 | if (src_loc.asRegister()) |src_reg| _ = try isel.fillReg(src_reg); | 1584 | if (src_loc.asRegister()) |src_reg| _ = try isel.fillReg(src_reg); |
| 1570 | tracking_log.debug("{f} -> {f} (move to)", .{ vi, src_loc }); | 1585 | tracking_log.debug("{f} -> {f} (move to)", .{ vi, src_loc }); |
| 1571 | if (vi.takeLocationMarkWritten(isel)) |dst_loc| | 1586 | if (vi.takeLocationMarkWritten(isel)) |dst_loc| |
| 1572 | try isel.moveLoc(dst_loc, 0, src_loc, 0, vi.size(isel), .none); | 1587 | try isel.moveLoc(dst_loc, 0, src_loc, 0, vi.size(isel), .{}); |
| 1573 | if (vi.isSmall(isel)) { | 1588 | if (vi.isSmall(isel)) { |
| 1574 | vi.setSmallLocation(isel, src_loc); | 1589 | vi.setSmallLocation(isel, src_loc); |
| 1575 | if (src_loc.asRegister()) |src_reg| { | 1590 | if (src_loc.asRegister()) |src_reg| { |
| ... | @@ -2130,7 +2145,7 @@ pub const Value = struct { | ... | @@ -2130,7 +2145,7 @@ pub const Value = struct { |
| 2130 | vi_loc, | 2145 | vi_loc, |
| 2131 | mat.offset, | 2146 | mat.offset, |
| 2132 | mat.size, | 2147 | mat.size, |
| 2133 | .preserved, | 2148 | .{ .dst_prot = .preserved }, |
| 2134 | ); | 2149 | ); |
| 2135 | if (maybe_loc_reg) |loc_reg| { | 2150 | if (maybe_loc_reg) |loc_reg| { |
| 2136 | const loc_live = isel.live_registers.getPtr(loc_reg); | 2151 | const loc_live = isel.live_registers.getPtr(loc_reg); |
| ... | @@ -2190,7 +2205,7 @@ pub const Value = struct { | ... | @@ -2190,7 +2205,7 @@ pub const Value = struct { |
| 2190 | .{ .stack_slot = .{ .base = addr_mat.reg(), .offset = 0 } }, | 2205 | .{ .stack_slot = .{ .base = addr_mat.reg(), .offset = 0 } }, |
| 2191 | offset_from_root + mat.offset, | 2206 | offset_from_root + mat.offset, |
| 2192 | mat.size, | 2207 | mat.size, |
| 2193 | .none, | 2208 | .{}, |
| 2194 | ); | 2209 | ); |
| 2195 | try addr_mat.finish(isel); | 2210 | try addr_mat.finish(isel); |
| 2196 | }, | 2211 | }, |
| ... | @@ -3415,7 +3430,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void | ... | @@ -3415,7 +3430,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3415 | output_loc, | 3430 | output_loc, |
| 3416 | 0, | 3431 | 0, |
| 3417 | output_vi.value.size(isel), | 3432 | output_vi.value.size(isel), |
| 3418 | .none, | 3433 | .{}, |
| 3419 | ); | 3434 | ); |
| 3420 | } | 3435 | } |
| 3421 | break :output_reg output_reg; | 3436 | break :output_reg output_reg; |
| ... | @@ -3544,7 +3559,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void | ... | @@ -3544,7 +3559,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3544 | const dst_loc: Value.Location = .{ .register = input_ra }; | 3559 | const dst_loc: Value.Location = .{ .register = input_ra }; |
| 3545 | if (!std.meta.eql(input_val_loc, dst_loc)) { | 3560 | if (!std.meta.eql(input_val_loc, dst_loc)) { |
| 3546 | dst_loc.markRegWritten(isel); | 3561 | dst_loc.markRegWritten(isel); |
| 3547 | try isel.moveLoc(dst_loc, 0, input_val_loc, 0, input_ra.mod.byteSize(isel.target), .none); | 3562 | try isel.moveLoc(dst_loc, 0, input_val_loc, 0, input_ra.mod.byteSize(isel.target), .{}); |
| 3548 | } | 3563 | } |
| 3549 | try input_val_mat.finish(isel); | 3564 | try input_val_mat.finish(isel); |
| 3550 | }, | 3565 | }, |
| ... | @@ -3962,6 +3977,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void | ... | @@ -3962,6 +3977,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3962 | const ptr_mat = try ptr_vi.matReg(isel); | 3977 | const ptr_mat = try ptr_vi.matReg(isel); |
| 3963 | try src_vi.matStore(isel, ptr_mat.reg(), 0, .{ | 3978 | try src_vi.matStore(isel, ptr_mat.reg(), 0, .{ |
| 3964 | .@"volatile" = ptr_info.flags.is_volatile, | 3979 | .@"volatile" = ptr_info.flags.is_volatile, |
| | 3980 | .atomic = (air_tag == .atomic_store_unordered), |
| 3965 | }); | 3981 | }); |
| 3966 | try ptr_mat.finish(isel); | 3982 | try ptr_mat.finish(isel); |
| 3967 | }, | 3983 | }, |
| ... | @@ -3986,6 +4002,29 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void | ... | @@ -3986,6 +4002,29 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3986 | try ptr_mat.finish(isel); | 4002 | try ptr_mat.finish(isel); |
| 3987 | } | 4003 | } |
| 3988 | }, | 4004 | }, |
| | 4005 | .atomic_load => { |
| | 4006 | const atomic_load = air.data(air.inst_index).atomic_load; |
| | 4007 | const ptr_ty = isel.air.typeOf(atomic_load.ptr, ip); |
| | 4008 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| | 4009 | if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed atomic load", .{}); |
| | 4010 | |
| | 4011 | if (ptr_info.flags.is_volatile) |
| | 4012 | _ = try isel.use(air.inst_index.toRef()); |
| | 4013 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| { |
| | 4014 | defer dst_vi.value.deref(isel); |
| | 4015 | |
| | 4016 | const ptr_vi = try isel.use(atomic_load.ptr); |
| | 4017 | const ptr_mat = try ptr_vi.matIntRegZeroExt(isel); |
| | 4018 | _ = try dst_vi.value.defLoad(isel, ptr_mat.reg(), 0, .{ |
| | 4019 | .@"volatile" = ptr_info.flags.is_volatile, |
| | 4020 | .atomic = true, |
| | 4021 | }); |
| | 4022 | try ptr_mat.finish(isel); |
| | 4023 | |
| | 4024 | if (atomic_load.order != .unordered) |
| | 4025 | try isel.failUnimplemented("ordered atomic load", .{}); |
| | 4026 | } |
| | 4027 | }, |
| 3989 | .int_cast => if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| { | 4028 | .int_cast => if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| { |
| 3990 | defer dst_vi.value.deref(isel); | 4029 | defer dst_vi.value.deref(isel); |
| 3991 | | 4030 | |
| ... | @@ -6206,6 +6245,11 @@ fn elemPtr( | ... | @@ -6206,6 +6245,11 @@ fn elemPtr( |
| 6206 | try index_mat.finish(isel); | 6245 | try index_mat.finish(isel); |
| 6207 | } | 6246 | } |
| 6208 | | 6247 | |
| | 6248 | const MoveLocOptions = struct { |
| | 6249 | dst_prot: DestProtection = .none, |
| | 6250 | atomic: bool = false, |
| | 6251 | }; |
| | 6252 | |
| 6209 | fn moveLoc( | 6253 | fn moveLoc( |
| 6210 | isel: *Select, | 6254 | isel: *Select, |
| 6211 | dst_loc: Value.Location, | 6255 | dst_loc: Value.Location, |
| ... | @@ -6213,22 +6257,23 @@ fn moveLoc( | ... | @@ -6213,22 +6257,23 @@ fn moveLoc( |
| 6213 | src_loc: Value.Location, | 6257 | src_loc: Value.Location, |
| 6214 | src_off: u64, | 6258 | src_off: u64, |
| 6215 | size: u64, | 6259 | size: u64, |
| 6216 | dst_prot: DestProtection, | 6260 | opts: MoveLocOptions, |
| 6217 | ) !void { | 6261 | ) !void { |
| 6218 | if (dst_loc.isUnallocated()) return; | 6262 | if (dst_loc.isUnallocated()) return; |
| 6219 | if (std.meta.eql(dst_loc, src_loc) and dst_off == src_off) return; | 6263 | if (std.meta.eql(dst_loc, src_loc) and dst_off == src_off) return; |
| 6220 | if (size == 0) return; | 6264 | if (size == 0) return; |
| 6221 | assert(!src_loc.isUnallocated()); | 6265 | assert(!src_loc.isUnallocated()); |
| 6222 | wip_mir_log.debug(" | # move {f}[{d}] <- {f}[{d}], {d}B, dst prot={t}", .{ | 6266 | wip_mir_log.debug(" | # move {f}[{d}] <- {f}[{d}], {d}B, dst prot={t}, atomic={}", .{ |
| 6223 | dst_loc, | 6267 | dst_loc, |
| 6224 | dst_off, | 6268 | dst_off, |
| 6225 | src_loc, | 6269 | src_loc, |
| 6226 | src_off, | 6270 | src_off, |
| 6227 | size, | 6271 | size, |
| 6228 | dst_prot, | 6272 | opts.dst_prot, |
| | 6273 | opts.atomic, |
| 6229 | }); | 6274 | }); |
| 6230 | | 6275 | |
| 6231 | const dst_lock: RegLock = if (dst_prot != .preserved) .empty else dst_loc.tryLock(isel); | 6276 | const dst_lock: RegLock = if (opts.dst_prot != .preserved) .empty else dst_loc.tryLock(isel); |
| 6232 | defer dst_lock.unlock(isel); | 6277 | defer dst_lock.unlock(isel); |
| 6233 | const src_lock = src_loc.tryLock(isel); | 6278 | const src_lock = src_loc.tryLock(isel); |
| 6234 | defer src_lock.unlock(isel); | 6279 | defer src_lock.unlock(isel); |
| ... | @@ -6241,7 +6286,7 @@ fn moveLoc( | ... | @@ -6241,7 +6286,7 @@ fn moveLoc( |
| 6241 | src_ra, | 6286 | src_ra, |
| 6242 | @intCast(src_off * 8), | 6287 | @intCast(src_off * 8), |
| 6243 | @intCast(size * 8), | 6288 | @intCast(size * 8), |
| 6244 | dst_prot, | 6289 | opts.dst_prot, |
| 6245 | ), | 6290 | ), |
| 6246 | .stack_slot => |src_stack| { | 6291 | .stack_slot => |src_stack| { |
| 6247 | const tmp_reg = if (dst_ra.mod == .integer and dst_off == 0) | 6292 | const tmp_reg = if (dst_ra.mod == .integer and dst_off == 0) |
| ... | @@ -6255,7 +6300,7 @@ fn moveLoc( | ... | @@ -6255,7 +6300,7 @@ fn moveLoc( |
| 6255 | .{ .reg = tmp_reg, .mod = .integer }, | 6300 | .{ .reg = tmp_reg, .mod = .integer }, |
| 6256 | 0, | 6301 | 0, |
| 6257 | @intCast(size * 8), | 6302 | @intCast(size * 8), |
| 6258 | dst_prot, | 6303 | opts.dst_prot, |
| 6259 | ); | 6304 | ); |
| 6260 | try isel.loadReg( | 6305 | try isel.loadReg( |
| 6261 | tmp_reg, | 6306 | tmp_reg, |
| ... | @@ -6267,6 +6312,8 @@ fn moveLoc( | ... | @@ -6267,6 +6312,8 @@ fn moveLoc( |
| 6267 | }, | 6312 | }, |
| 6268 | }, | 6313 | }, |
| 6269 | .stack_slot => |dst_stack| { | 6314 | .stack_slot => |dst_stack| { |
| | 6315 | if (size > isel.gprSize() and opts.atomic) |
| | 6316 | return isel.fail("Memory store of {d} bytes cannot be atomic", .{size}); |
| 6270 | if (size > isel.gprSize()) { | 6317 | if (size > isel.gprSize()) { |
| 6271 | // large memory copies, src must be stack_slot | 6318 | // large memory copies, src must be stack_slot |
| 6272 | const src_stack = src_loc.stack_slot; | 6319 | const src_stack = src_loc.stack_slot; |
| ... | @@ -6294,7 +6341,7 @@ fn moveLoc( | ... | @@ -6294,7 +6341,7 @@ fn moveLoc( |
| 6294 | if (gen_low_to_high) { | 6341 | if (gen_low_to_high) { |
| 6295 | var off: u64 = 0; | 6342 | var off: u64 = 0; |
| 6296 | for (0..@intCast(steps)) |_| { | 6343 | for (0..@intCast(steps)) |_| { |
| 6297 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, dst_prot); | 6344 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, opts); |
| 6298 | off += gpr_size; | 6345 | off += gpr_size; |
| 6299 | } | 6346 | } |
| 6300 | } | 6347 | } |
| ... | @@ -6302,7 +6349,7 @@ fn moveLoc( | ... | @@ -6302,7 +6349,7 @@ fn moveLoc( |
| 6302 | var off: u64 = steps * gpr_size; | 6349 | var off: u64 = steps * gpr_size; |
| 6303 | for (0..@intCast(steps)) |_| { | 6350 | for (0..@intCast(steps)) |_| { |
| 6304 | off -= gpr_size; | 6351 | off -= gpr_size; |
| 6305 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, dst_prot); | 6352 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, opts); |
| 6306 | } | 6353 | } |
| 6307 | } | 6354 | } |
| 6308 | | 6355 | |
| ... | @@ -6313,7 +6360,9 @@ fn moveLoc( | ... | @@ -6313,7 +6360,9 @@ fn moveLoc( |
| 6313 | // If size is not direct mem op size and !kill_dst, old values have to | 6360 | // If size is not direct mem op size and !kill_dst, old values have to |
| 6314 | // be loaded first. | 6361 | // be loaded first. |
| 6315 | const memop_size = memOpSizeFitting(size); | 6362 | const memop_size = memOpSizeFitting(size); |
| 6316 | const need_load = memop_size != size; | 6363 | const need_load = memop_size != size and opts.dst_prot != .none; |
| | 6364 | if (opts.atomic and need_load) |
| | 6365 | return isel.fail("Memory store of {d} bytes cannot be atomic without killing other bytes", .{size}); |
| 6317 | const tmp_reg, const tmp_allocated = tmp_reg: { | 6366 | const tmp_reg, const tmp_allocated = tmp_reg: { |
| 6318 | if (src_off == 0 and !need_load) { | 6367 | if (src_off == 0 and !need_load) { |
| 6319 | switch (src_loc) { | 6368 | switch (src_loc) { |
| ... | @@ -6335,7 +6384,7 @@ fn moveLoc( | ... | @@ -6335,7 +6384,7 @@ fn moveLoc( |
| 6335 | src_loc, | 6384 | src_loc, |
| 6336 | src_off, | 6385 | src_off, |
| 6337 | size, | 6386 | size, |
| 6338 | if (need_load) .preserved else .none, | 6387 | opts, |
| 6339 | ); | 6388 | ); |
| 6340 | if (need_load) | 6389 | if (need_load) |
| 6341 | try isel.loadReg(tmp_reg, memop_size, .unsigned, dst_stack.base, dst_stack_off); | 6390 | try isel.loadReg(tmp_reg, memop_size, .unsigned, dst_stack.base, dst_stack_off); |
| ... | @@ -6463,7 +6512,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6463,7 +6512,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6463 | const rd = dst_ra.reg; | 6512 | const rd = dst_ra.reg; |
| 6464 | defer if (use_tmp_reg) isel.freeReg(rd); | 6513 | defer if (use_tmp_reg) isel.freeReg(rd); |
| 6465 | | 6514 | |
| 6466 | if (use_tmp_reg) try isel.moveLoc(dst, 0, .{ .register = dst_ra }, 0, isel.gprSize(), .none); | 6515 | if (use_tmp_reg) try isel.moveLoc(dst, 0, .{ .register = dst_ra }, 0, isel.gprSize(), .{}); |
| 6467 | return switch (ptr.base_addr) { | 6516 | return switch (ptr.base_addr) { |
| 6468 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) { | 6517 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) { |
| 6469 | // TODO code model | 6518 | // TODO code model |
| ... | @@ -6724,7 +6773,14 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6724,7 +6773,14 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6724 | ), | 6773 | ), |
| 6725 | }; | 6774 | }; |
| 6726 | | 6775 | |
| 6727 | try isel.moveLoc(dst, part_offset, .{ .register = tmp_ra }, 0, part_size, .preserved); | 6776 | try isel.moveLoc( |
| | 6777 | dst, |
| | 6778 | part_offset, |
| | 6779 | .{ .register = tmp_ra }, |
| | 6780 | 0, |
| | 6781 | part_size, |
| | 6782 | .{ .dst_prot = .preserved }, |
| | 6783 | ); |
| 6728 | try isel.moveIntImm(tmp_reg, @bitCast(part_value)); | 6784 | try isel.moveIntImm(tmp_reg, @bitCast(part_value)); |
| 6729 | | 6785 | |
| 6730 | if (part_offset == 0) break else part_offset -= gpr_size; | 6786 | if (part_offset == 0) break else part_offset -= gpr_size; |
| ... | @@ -6755,7 +6811,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6755,7 +6811,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6755 | .{ .stack_slot = .{ .base = tmp_reg, .offset = 0 } }, | 6811 | .{ .stack_slot = .{ .base = tmp_reg, .offset = 0 } }, |
| 6756 | offset, | 6812 | offset, |
| 6757 | size, | 6813 | size, |
| 6758 | .none, | 6814 | .{}, |
| 6759 | ); | 6815 | ); |
| 6760 | | 6816 | |
| 6761 | // load constant pointer | 6817 | // load constant pointer |
| ... | @@ -7237,7 +7293,7 @@ const call = struct { | ... | @@ -7237,7 +7293,7 @@ const call = struct { |
| 7237 | .{ .register = .{ .mod = .integer, .reg = tmp_reg } }, | 7293 | .{ .register = .{ .mod = .integer, .reg = tmp_reg } }, |
| 7238 | 0, | 7294 | 0, |
| 7239 | isel.gprSize(), | 7295 | isel.gprSize(), |
| 7240 | .preserved, | 7296 | .{ .dst_prot = .preserved }, |
| 7241 | ); | 7297 | ); |
| 7242 | } else unreachable; | 7298 | } else unreachable; |
| 7243 | } | 7299 | } |