| ... | ... | @@ -983,7 +983,14 @@ pub const Value = struct { |
| 983 | 983 | while (part_it.next()) |part_vi| { |
| 984 | 984 | const part_offset, const part_size = part_vi.positionInParent(isel); |
| 985 | 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 | 994 | try part_mat.finish(isel); |
| 988 | 995 | if (reextend_parts) |
| 989 | 996 | try part_vi.reextend(isel, def_ext); |
| ... | ... | @@ -1003,7 +1010,7 @@ pub const Value = struct { |
| 1003 | 1010 | const def_loc = def_vi.takeLocationMarkWritten(isel) orelse return; |
| 1004 | 1011 | const def_offset, const def_size = def_vi.positionInParent(isel); |
| 1005 | 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 | 1014 | try parent_mat.finish(isel); |
| 1008 | 1015 | } |
| 1009 | 1016 | |
| ... | ... | @@ -1104,9 +1111,10 @@ pub const Value = struct { |
| 1104 | 1111 | ) !bool { |
| 1105 | 1112 | try vi.reextendToPcs(isel); |
| 1106 | 1113 | try vi.collectDefs(isel); |
| 1114 | if (opts.@"volatile") |
| 1115 | try (try vi.mat(isel, .{})).finish(isel); |
| 1107 | 1116 | const loc = vi.takeLocationMarkWritten(isel) orelse return false; |
| 1108 | 1117 | wip_mir_log.debug(" | # load {f} <- [${t}, #{d}] ({d}B)", .{ vi, base_reg, offset, vi.size(isel) }); |
| 1109 | | _ = opts; |
| 1110 | 1118 | |
| 1111 | 1119 | try isel.moveLoc( |
| 1112 | 1120 | loc, |
| ... | ... | @@ -1114,7 +1122,7 @@ pub const Value = struct { |
| 1114 | 1122 | .{ .stack_slot = .{ .base = base_reg, .offset = 0 } }, |
| 1115 | 1123 | offset, |
| 1116 | 1124 | vi.size(isel), |
| 1117 | | .none, |
| 1125 | .{ .atomic = opts.atomic }, |
| 1118 | 1126 | ); |
| 1119 | 1127 | return true; |
| 1120 | 1128 | } |
| ... | ... | @@ -1166,7 +1174,7 @@ pub const Value = struct { |
| 1166 | 1174 | const src_loc = src_mat.loc(); |
| 1167 | 1175 | if (!std.meta.eql(loc, src_loc)) { |
| 1168 | 1176 | loc.markRegWritten(isel); |
| 1169 | | try isel.moveLoc(loc, 0, src_mat.loc(), 0, copy_size, .none); |
| 1177 | try isel.moveLoc(loc, 0, src_mat.loc(), 0, copy_size, .{}); |
| 1170 | 1178 | } |
| 1171 | 1179 | try src_mat.finish(isel); |
| 1172 | 1180 | } |
| ... | ... | @@ -1270,15 +1278,23 @@ pub const Value = struct { |
| 1270 | 1278 | _ = try isel.fillReg(src_reg); |
| 1271 | 1279 | } |
| 1272 | 1280 | // TODO: replace reextending def_part_vi to .zero_ext with moveLoc .wipe when applicable |
| 1273 | | 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 | ); |
| 1274 | 1289 | } |
| 1275 | 1290 | } |
| 1276 | 1291 | if (maybe_def_addr_mat) |def_addr_mat| try def_addr_mat.finish(isel); |
| 1277 | 1292 | } |
| 1278 | 1293 | |
| 1279 | 1294 | const MemoryAccessOptions = struct { |
| 1280 | | // TODO unimplemented, remove? |
| 1281 | 1295 | @"volatile": bool = false, |
| 1296 | // Atomicity. This is unrelated to ordering and visibility. |
| 1297 | atomic: bool = false, |
| 1282 | 1298 | }; |
| 1283 | 1299 | |
| 1284 | 1300 | const MatOptions = struct { |
| ... | ... | @@ -1308,7 +1324,7 @@ pub const Value = struct { |
| 1308 | 1324 | }; |
| 1309 | 1325 | |
| 1310 | 1326 | /// Materializes a value |
| 1311 | | fn mat(vi: Value.Index, isel: *Select, opts: MatOptions) Mat.Error!Mat { |
| 1327 | fn mat(vi: Value.Index, isel: *Select, opts: MatOptions) codegen.Error!Mat { |
| 1312 | 1328 | // try vi.split(isel, true); |
| 1313 | 1329 | const mat_size = @min(opts.size, @as(u32, @intCast(vi.size(isel) - opts.offset))); |
| 1314 | 1330 | const loc_pref = if (opts.extension == .garbage) |
| ... | ... | @@ -1478,7 +1494,6 @@ pub const Value = struct { |
| 1478 | 1494 | opts: MemoryAccessOptions, |
| 1479 | 1495 | ) !void { |
| 1480 | 1496 | wip_mir_log.debug(" | # store {f} -> [${t}, #{d}]", .{ vi, base_reg, offset }); |
| 1481 | | _ = opts; |
| 1482 | 1497 | |
| 1483 | 1498 | const hint_stack: Indirect = if (std.math.cast(@FieldType(Indirect, "offset"), offset)) |stack_off| |
| 1484 | 1499 | .{ .base = base_reg, .offset = stack_off } |
| ... | ... | @@ -1491,7 +1506,7 @@ pub const Value = struct { |
| 1491 | 1506 | value_mat.loc(), |
| 1492 | 1507 | 0, |
| 1493 | 1508 | vi.size(isel), |
| 1494 | | .none, |
| 1509 | .{ .atomic = opts.atomic }, |
| 1495 | 1510 | ); |
| 1496 | 1511 | try value_mat.finish(isel); |
| 1497 | 1512 | } |
| ... | ... | @@ -1543,7 +1558,7 @@ pub const Value = struct { |
| 1543 | 1558 | .size = @intCast(part_size), |
| 1544 | 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 | 1562 | try value_mat.finish(isel); |
| 1548 | 1563 | } |
| 1549 | 1564 | |
| ... | ... | @@ -1558,7 +1573,7 @@ pub const Value = struct { |
| 1558 | 1573 | .size = @intCast(part_size), |
| 1559 | 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 | 1577 | try value_mat.finish(isel); |
| 1563 | 1578 | } |
| 1564 | 1579 | } |
| ... | ... | @@ -1569,7 +1584,7 @@ pub const Value = struct { |
| 1569 | 1584 | if (src_loc.asRegister()) |src_reg| _ = try isel.fillReg(src_reg); |
| 1570 | 1585 | tracking_log.debug("{f} -> {f} (move to)", .{ vi, src_loc }); |
| 1571 | 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 | 1588 | if (vi.isSmall(isel)) { |
| 1574 | 1589 | vi.setSmallLocation(isel, src_loc); |
| 1575 | 1590 | if (src_loc.asRegister()) |src_reg| { |
| ... | ... | @@ -2046,8 +2061,6 @@ pub const Value = struct { |
| 2046 | 2061 | if (!std.debug.runtime_safety) assert(@sizeOf(Mat) <= 32); |
| 2047 | 2062 | } |
| 2048 | 2063 | |
| 2049 | | const Error = codegen.Error; |
| 2050 | | |
| 2051 | 2064 | pub fn ra(mat: Value.Mat) Register.Alias { |
| 2052 | 2065 | return mat.location.register; |
| 2053 | 2066 | } |
| ... | ... | @@ -2066,7 +2079,7 @@ pub const Value = struct { |
| 2066 | 2079 | }; |
| 2067 | 2080 | } |
| 2068 | 2081 | |
| 2069 | | fn finish(mat: Value.Mat, isel: *Select) Mat.Error!void { |
| 2082 | fn finish(mat: Value.Mat, isel: *Select) codegen.Error!void { |
| 2070 | 2083 | const vi = mat.vi; |
| 2071 | 2084 | const value = vi.get(isel); |
| 2072 | 2085 | tracking_log.debug("{f}[{d}..{d}] <- {f} (mat finish)", .{ vi, mat.offset, mat.offset + mat.size - 1, mat.loc() }); |
| ... | ... | @@ -2132,7 +2145,7 @@ pub const Value = struct { |
| 2132 | 2145 | vi_loc, |
| 2133 | 2146 | mat.offset, |
| 2134 | 2147 | mat.size, |
| 2135 | | .preserved, |
| 2148 | .{ .dst_prot = .preserved }, |
| 2136 | 2149 | ); |
| 2137 | 2150 | if (maybe_loc_reg) |loc_reg| { |
| 2138 | 2151 | const loc_live = isel.live_registers.getPtr(loc_reg); |
| ... | ... | @@ -2192,7 +2205,7 @@ pub const Value = struct { |
| 2192 | 2205 | .{ .stack_slot = .{ .base = addr_mat.reg(), .offset = 0 } }, |
| 2193 | 2206 | offset_from_root + mat.offset, |
| 2194 | 2207 | mat.size, |
| 2195 | | .none, |
| 2208 | .{}, |
| 2196 | 2209 | ); |
| 2197 | 2210 | try addr_mat.finish(isel); |
| 2198 | 2211 | }, |
| ... | ... | @@ -2315,7 +2328,7 @@ fn failUnimplemented(isel: *Select, comptime format: []const u8, args: anytype) |
| 2315 | 2328 | } else return isel.fail(format, args); |
| 2316 | 2329 | } |
| 2317 | 2330 | |
| 2318 | | fn moveDebugString(isel: *Select, reg: Register, msg: [:0]const u8) error{ OutOfMemory, AlreadyReported }!void { |
| 2331 | fn moveDebugString(isel: *Select, reg: Register, msg: [:0]const u8) codegen.Error!void { |
| 2319 | 2332 | @branchHint(.cold); |
| 2320 | 2333 | assert(debug_trap_unimplemented_code); |
| 2321 | 2334 | |
| ... | ... | @@ -3417,7 +3430,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3417 | 3430 | output_loc, |
| 3418 | 3431 | 0, |
| 3419 | 3432 | output_vi.value.size(isel), |
| 3420 | | .none, |
| 3433 | .{}, |
| 3421 | 3434 | ); |
| 3422 | 3435 | } |
| 3423 | 3436 | break :output_reg output_reg; |
| ... | ... | @@ -3546,7 +3559,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3546 | 3559 | const dst_loc: Value.Location = .{ .register = input_ra }; |
| 3547 | 3560 | if (!std.meta.eql(input_val_loc, dst_loc)) { |
| 3548 | 3561 | dst_loc.markRegWritten(isel); |
| 3549 | | 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), .{}); |
| 3550 | 3563 | } |
| 3551 | 3564 | try input_val_mat.finish(isel); |
| 3552 | 3565 | }, |
| ... | ... | @@ -3964,6 +3977,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3964 | 3977 | const ptr_mat = try ptr_vi.matReg(isel); |
| 3965 | 3978 | try src_vi.matStore(isel, ptr_mat.reg(), 0, .{ |
| 3966 | 3979 | .@"volatile" = ptr_info.flags.is_volatile, |
| 3980 | .atomic = (air_tag == .atomic_store_unordered), |
| 3967 | 3981 | }); |
| 3968 | 3982 | try ptr_mat.finish(isel); |
| 3969 | 3983 | }, |
| ... | ... | @@ -3973,7 +3987,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3973 | 3987 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| 3974 | 3988 | if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed load", .{}); |
| 3975 | 3989 | |
| 3976 | | if (ptr_info.flags.is_volatile) _ = try isel.use(air.inst_index.toRef()); |
| 3990 | if (ptr_info.flags.is_volatile) |
| 3991 | _ = try isel.use(air.inst_index.toRef()); |
| 3977 | 3992 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| { |
| 3978 | 3993 | defer dst_vi.value.deref(isel); |
| 3979 | 3994 | |
| ... | ... | @@ -3987,6 +4002,29 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 3987 | 4002 | try ptr_mat.finish(isel); |
| 3988 | 4003 | } |
| 3989 | 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 | }, |
| 3990 | 4028 | .int_cast => if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| { |
| 3991 | 4029 | defer dst_vi.value.deref(isel); |
| 3992 | 4030 | |
| ... | ... | @@ -4709,6 +4747,40 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void |
| 4709 | 4747 | try error_union_ptr_mat.finish(isel); |
| 4710 | 4748 | } |
| 4711 | 4749 | }, |
| 4750 | .runtime_nav_ptr => if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: { |
| 4751 | defer ptr_vi.value.deref(isel); |
| 4752 | const ptr_reg = try ptr_vi.value.defRegMod(isel, .integer) orelse break :unused; |
| 4753 | const ty_nav = air.data(air.inst_index).ty_nav; |
| 4754 | const target_nav = ip.getNav(ty_nav.nav); |
| 4755 | const target_nav_resolved = target_nav.resolved.?; |
| 4756 | |
| 4757 | if (target_nav_resolved.@"threadlocal") { |
| 4758 | // TODO: implement TLS models other than LE |
| 4759 | try isel.emit(switch (isel.gprBits()) { |
| 4760 | 32 => .@"add.w"(ptr_reg, ptr_reg, .tp), |
| 4761 | 64 => .@"add.d"(ptr_reg, ptr_reg, .tp), |
| 4762 | else => unreachable, |
| 4763 | }); |
| 4764 | try isel.nav_relocs.append(zcu.gpa, .{ |
| 4765 | .nav = ty_nav.nav, |
| 4766 | .reloc = .{ |
| 4767 | .label = @intCast(isel.instructions.items.len), |
| 4768 | .addend = 0, |
| 4769 | .type = .TLS_LE_LO12, |
| 4770 | }, |
| 4771 | }); |
| 4772 | try isel.emit(.ori(ptr_reg, ptr_reg, 0)); |
| 4773 | try isel.nav_relocs.append(zcu.gpa, .{ |
| 4774 | .nav = ty_nav.nav, |
| 4775 | .reloc = .{ |
| 4776 | .label = @intCast(isel.instructions.items.len), |
| 4777 | .addend = 0, |
| 4778 | .type = .TLS_LE_HI20, |
| 4779 | }, |
| 4780 | }); |
| 4781 | try isel.emit(.@"lu12i.w"(ptr_reg, 0)); |
| 4782 | } else try isel.failUnimplemented("unimplemented runtime_nav_ptr", .{}); |
| 4783 | }, |
| 4712 | 4784 | } |
| 4713 | 4785 | if (air_tag != .arg) { |
| 4714 | 4786 | var live_reg_it = isel.live_registers.iterator(); |
| ... | ... | @@ -6207,6 +6279,11 @@ fn elemPtr( |
| 6207 | 6279 | try index_mat.finish(isel); |
| 6208 | 6280 | } |
| 6209 | 6281 | |
| 6282 | const MoveLocOptions = struct { |
| 6283 | dst_prot: DestProtection = .none, |
| 6284 | atomic: bool = false, |
| 6285 | }; |
| 6286 | |
| 6210 | 6287 | fn moveLoc( |
| 6211 | 6288 | isel: *Select, |
| 6212 | 6289 | dst_loc: Value.Location, |
| ... | ... | @@ -6214,22 +6291,23 @@ fn moveLoc( |
| 6214 | 6291 | src_loc: Value.Location, |
| 6215 | 6292 | src_off: u64, |
| 6216 | 6293 | size: u64, |
| 6217 | | dst_prot: DestProtection, |
| 6294 | opts: MoveLocOptions, |
| 6218 | 6295 | ) !void { |
| 6219 | 6296 | if (dst_loc.isUnallocated()) return; |
| 6220 | 6297 | if (std.meta.eql(dst_loc, src_loc) and dst_off == src_off) return; |
| 6221 | 6298 | if (size == 0) return; |
| 6222 | 6299 | assert(!src_loc.isUnallocated()); |
| 6223 | | wip_mir_log.debug(" | # move {f}[{d}] <- {f}[{d}], {d}B, dst prot={t}", .{ |
| 6300 | wip_mir_log.debug(" | # move {f}[{d}] <- {f}[{d}], {d}B, dst prot={t}, atomic={}", .{ |
| 6224 | 6301 | dst_loc, |
| 6225 | 6302 | dst_off, |
| 6226 | 6303 | src_loc, |
| 6227 | 6304 | src_off, |
| 6228 | 6305 | size, |
| 6229 | | dst_prot, |
| 6306 | opts.dst_prot, |
| 6307 | opts.atomic, |
| 6230 | 6308 | }); |
| 6231 | 6309 | |
| 6232 | | const dst_lock: RegLock = if (dst_prot != .preserved) .empty else dst_loc.tryLock(isel); |
| 6310 | const dst_lock: RegLock = if (opts.dst_prot != .preserved) .empty else dst_loc.tryLock(isel); |
| 6233 | 6311 | defer dst_lock.unlock(isel); |
| 6234 | 6312 | const src_lock = src_loc.tryLock(isel); |
| 6235 | 6313 | defer src_lock.unlock(isel); |
| ... | ... | @@ -6242,7 +6320,7 @@ fn moveLoc( |
| 6242 | 6320 | src_ra, |
| 6243 | 6321 | @intCast(src_off * 8), |
| 6244 | 6322 | @intCast(size * 8), |
| 6245 | | dst_prot, |
| 6323 | opts.dst_prot, |
| 6246 | 6324 | ), |
| 6247 | 6325 | .stack_slot => |src_stack| { |
| 6248 | 6326 | const tmp_reg = if (dst_ra.mod == .integer and dst_off == 0) |
| ... | ... | @@ -6256,7 +6334,7 @@ fn moveLoc( |
| 6256 | 6334 | .{ .reg = tmp_reg, .mod = .integer }, |
| 6257 | 6335 | 0, |
| 6258 | 6336 | @intCast(size * 8), |
| 6259 | | dst_prot, |
| 6337 | opts.dst_prot, |
| 6260 | 6338 | ); |
| 6261 | 6339 | try isel.loadReg( |
| 6262 | 6340 | tmp_reg, |
| ... | ... | @@ -6268,6 +6346,8 @@ fn moveLoc( |
| 6268 | 6346 | }, |
| 6269 | 6347 | }, |
| 6270 | 6348 | .stack_slot => |dst_stack| { |
| 6349 | if (size > isel.gprSize() and opts.atomic) |
| 6350 | return isel.fail("Memory store of {d} bytes cannot be atomic", .{size}); |
| 6271 | 6351 | if (size > isel.gprSize()) { |
| 6272 | 6352 | // large memory copies, src must be stack_slot |
| 6273 | 6353 | const src_stack = src_loc.stack_slot; |
| ... | ... | @@ -6295,7 +6375,7 @@ fn moveLoc( |
| 6295 | 6375 | if (gen_low_to_high) { |
| 6296 | 6376 | var off: u64 = 0; |
| 6297 | 6377 | for (0..@intCast(steps)) |_| { |
| 6298 | | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, dst_prot); |
| 6378 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, opts); |
| 6299 | 6379 | off += gpr_size; |
| 6300 | 6380 | } |
| 6301 | 6381 | } |
| ... | ... | @@ -6303,7 +6383,7 @@ fn moveLoc( |
| 6303 | 6383 | var off: u64 = steps * gpr_size; |
| 6304 | 6384 | for (0..@intCast(steps)) |_| { |
| 6305 | 6385 | off -= gpr_size; |
| 6306 | | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, dst_prot); |
| 6386 | try isel.moveLoc(dst_loc, dst_off + off, src_loc, src_off + off, gpr_size, opts); |
| 6307 | 6387 | } |
| 6308 | 6388 | } |
| 6309 | 6389 | |
| ... | ... | @@ -6314,7 +6394,9 @@ fn moveLoc( |
| 6314 | 6394 | // If size is not direct mem op size and !kill_dst, old values have to |
| 6315 | 6395 | // be loaded first. |
| 6316 | 6396 | const memop_size = memOpSizeFitting(size); |
| 6317 | | const need_load = memop_size != size; |
| 6397 | const need_load = memop_size != size and opts.dst_prot != .none; |
| 6398 | if (opts.atomic and need_load) |
| 6399 | return isel.fail("Memory store of {d} bytes cannot be atomic without killing other bytes", .{size}); |
| 6318 | 6400 | const tmp_reg, const tmp_allocated = tmp_reg: { |
| 6319 | 6401 | if (src_off == 0 and !need_load) { |
| 6320 | 6402 | switch (src_loc) { |
| ... | ... | @@ -6336,7 +6418,7 @@ fn moveLoc( |
| 6336 | 6418 | src_loc, |
| 6337 | 6419 | src_off, |
| 6338 | 6420 | size, |
| 6339 | | if (need_load) .preserved else .none, |
| 6421 | opts, |
| 6340 | 6422 | ); |
| 6341 | 6423 | if (need_load) |
| 6342 | 6424 | try isel.loadReg(tmp_reg, memop_size, .unsigned, dst_stack.base, dst_stack_off); |
| ... | ... | @@ -6464,7 +6546,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6464 | 6546 | const rd = dst_ra.reg; |
| 6465 | 6547 | defer if (use_tmp_reg) isel.freeReg(rd); |
| 6466 | 6548 | |
| 6467 | | if (use_tmp_reg) try isel.moveLoc(dst, 0, .{ .register = dst_ra }, 0, isel.gprSize(), .none); |
| 6549 | if (use_tmp_reg) try isel.moveLoc(dst, 0, .{ .register = dst_ra }, 0, isel.gprSize(), .{}); |
| 6468 | 6550 | return switch (ptr.base_addr) { |
| 6469 | 6551 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) { |
| 6470 | 6552 | // TODO code model |
| ... | ... | @@ -6725,7 +6807,14 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6725 | 6807 | ), |
| 6726 | 6808 | }; |
| 6727 | 6809 | |
| 6728 | | try isel.moveLoc(dst, part_offset, .{ .register = tmp_ra }, 0, part_size, .preserved); |
| 6810 | try isel.moveLoc( |
| 6811 | dst, |
| 6812 | part_offset, |
| 6813 | .{ .register = tmp_ra }, |
| 6814 | 0, |
| 6815 | part_size, |
| 6816 | .{ .dst_prot = .preserved }, |
| 6817 | ); |
| 6729 | 6818 | try isel.moveIntImm(tmp_reg, @bitCast(part_value)); |
| 6730 | 6819 | |
| 6731 | 6820 | if (part_offset == 0) break else part_offset -= gpr_size; |
| ... | ... | @@ -6756,7 +6845,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6756 | 6845 | .{ .stack_slot = .{ .base = tmp_reg, .offset = 0 } }, |
| 6757 | 6846 | offset, |
| 6758 | 6847 | size, |
| 6759 | | .none, |
| 6848 | .{}, |
| 6760 | 6849 | ); |
| 6761 | 6850 | |
| 6762 | 6851 | // load constant pointer |
| ... | ... | @@ -7238,7 +7327,7 @@ const call = struct { |
| 7238 | 7327 | .{ .register = .{ .mod = .integer, .reg = tmp_reg } }, |
| 7239 | 7328 | 0, |
| 7240 | 7329 | isel.gprSize(), |
| 7241 | | .preserved, |
| 7330 | .{ .dst_prot = .preserved }, |
| 7242 | 7331 | ); |
| 7243 | 7332 | } else unreachable; |
| 7244 | 7333 | } |