| ... | @@ -961,7 +961,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -961,7 +961,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 961 | .inst_index = undefined, | 961 | .inst_index = undefined, |
| 962 | }; | 962 | }; |
| 963 | air_tag: switch (air.next().?) { | 963 | air_tag: switch (air.next().?) { |
| 964 | else => |air_tag| return isel.fail("unimplemented {s}", .{@tagName(air_tag)}), | 964 | else => |air_tag| return isel.fail("unimplemented {t}", .{air_tag}), |
| 965 | .arg => { | 965 | .arg => { |
| 966 | const arg_vi = isel.live_values.fetchRemove(air.inst_index).?.value; | 966 | const arg_vi = isel.live_values.fetchRemove(air.inst_index).?.value; |
| 967 | defer arg_vi.deref(isel); | 967 | defer arg_vi.deref(isel); |
| ... | @@ -1117,12 +1117,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1117,12 +1117,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1117 | | 1117 | |
| 1118 | const bin_op = air.data(air.inst_index).bin_op; | 1118 | const bin_op = air.data(air.inst_index).bin_op; |
| 1119 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 1119 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 1120 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 1120 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 1121 | const int_info = ty.intInfo(zcu); | 1121 | const int_info = ty.intInfo(zcu); |
| 1122 | switch (int_info.bits) { | 1122 | switch (int_info.bits) { |
| 1123 | 0 => unreachable, | 1123 | 0 => unreachable, |
| 1124 | 32, 64 => |bits| switch (int_info.signedness) { | 1124 | 32, 64 => |bits| switch (int_info.signedness) { |
| 1125 | .signed => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1125 | .signed => return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1126 | .unsigned => { | 1126 | .unsigned => { |
| 1127 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 1127 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| 1128 | const lhs_vi = try isel.use(bin_op.lhs); | 1128 | const lhs_vi = try isel.use(bin_op.lhs); |
| ... | @@ -1160,7 +1160,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1160,7 +1160,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1160 | try lhs_mat.finish(isel); | 1160 | try lhs_mat.finish(isel); |
| 1161 | }, | 1161 | }, |
| 1162 | }, | 1162 | }, |
| 1163 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1163 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1164 | } | 1164 | } |
| 1165 | } | 1165 | } |
| 1166 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 1166 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -1172,7 +1172,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1172,7 +1172,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1172 | const bin_op = air.data(air.inst_index).bin_op; | 1172 | const bin_op = air.data(air.inst_index).bin_op; |
| 1173 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 1173 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 1174 | if (!ty.isRuntimeFloat()) { | 1174 | if (!ty.isRuntimeFloat()) { |
| 1175 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 1175 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 1176 | const int_info = ty.intInfo(zcu); | 1176 | const int_info = ty.intInfo(zcu); |
| 1177 | switch (int_info.bits) { | 1177 | switch (int_info.bits) { |
| 1178 | 0 => unreachable, | 1178 | 0 => unreachable, |
| ... | @@ -1318,7 +1318,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1318,7 +1318,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1318 | try rhs_lo64_mat.finish(isel); | 1318 | try rhs_lo64_mat.finish(isel); |
| 1319 | try lhs_lo64_mat.finish(isel); | 1319 | try lhs_lo64_mat.finish(isel); |
| 1320 | }, | 1320 | }, |
| 1321 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1321 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1322 | } | 1322 | } |
| 1323 | } else switch (ty.floatBits(isel.target)) { | 1323 | } else switch (ty.floatBits(isel.target)) { |
| 1324 | else => unreachable, | 1324 | else => unreachable, |
| ... | @@ -1421,7 +1421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1421,7 +1421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1421 | | 1421 | |
| 1422 | const bin_op = air.data(air.inst_index).bin_op; | 1422 | const bin_op = air.data(air.inst_index).bin_op; |
| 1423 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 1423 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 1424 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 1424 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 1425 | const int_info = ty.intInfo(zcu); | 1425 | const int_info = ty.intInfo(zcu); |
| 1426 | switch (int_info.signedness) { | 1426 | switch (int_info.signedness) { |
| 1427 | .signed => switch (int_info.bits) { | 1427 | .signed => switch (int_info.bits) { |
| ... | @@ -1443,7 +1443,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1443,7 +1443,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1443 | try rhs_mat.finish(isel); | 1443 | try rhs_mat.finish(isel); |
| 1444 | try lhs_mat.finish(isel); | 1444 | try lhs_mat.finish(isel); |
| 1445 | }, | 1445 | }, |
| 1446 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1446 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1447 | }, | 1447 | }, |
| 1448 | .unsigned => switch (int_info.bits) { | 1448 | .unsigned => switch (int_info.bits) { |
| 1449 | 0 => unreachable, | 1449 | 0 => unreachable, |
| ... | @@ -1545,8 +1545,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1545,8 +1545,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1545 | try rhs_mat.finish(isel); | 1545 | try rhs_mat.finish(isel); |
| 1546 | try lhs_mat.finish(isel); | 1546 | try lhs_mat.finish(isel); |
| 1547 | }, | 1547 | }, |
| 1548 | 65...128 => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1548 | 65...128 => return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1549 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1549 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1550 | }, | 1550 | }, |
| 1551 | } | 1551 | } |
| 1552 | } | 1552 | } |
| ... | @@ -1558,7 +1558,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1558,7 +1558,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1558 | | 1558 | |
| 1559 | const bin_op = air.data(air.inst_index).bin_op; | 1559 | const bin_op = air.data(air.inst_index).bin_op; |
| 1560 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 1560 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 1561 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 1561 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 1562 | const int_info = ty.intInfo(zcu); | 1562 | const int_info = ty.intInfo(zcu); |
| 1563 | switch (int_info.bits) { | 1563 | switch (int_info.bits) { |
| 1564 | 0 => unreachable, | 1564 | 0 => unreachable, |
| ... | @@ -1784,7 +1784,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1784,7 +1784,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1784 | try rhs_mat.finish(isel); | 1784 | try rhs_mat.finish(isel); |
| 1785 | try lhs_mat.finish(isel); | 1785 | try lhs_mat.finish(isel); |
| 1786 | }, | 1786 | }, |
| 1787 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 1787 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 1788 | } | 1788 | } |
| 1789 | } | 1789 | } |
| 1790 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 1790 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -1897,7 +1897,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1897,7 +1897,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1897 | const bin_op = air.data(air.inst_index).bin_op; | 1897 | const bin_op = air.data(air.inst_index).bin_op; |
| 1898 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 1898 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 1899 | if (!ty.isRuntimeFloat()) { | 1899 | if (!ty.isRuntimeFloat()) { |
| 1900 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 1900 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 1901 | const int_info = ty.intInfo(zcu); | 1901 | const int_info = ty.intInfo(zcu); |
| 1902 | switch (int_info.bits) { | 1902 | switch (int_info.bits) { |
| 1903 | 0 => unreachable, | 1903 | 0 => unreachable, |
| ... | @@ -1970,7 +1970,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -1970,7 +1970,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 1970 | else => unreachable, | 1970 | else => unreachable, |
| 1971 | .div_trunc, .div_exact => {}, | 1971 | .div_trunc, .div_exact => {}, |
| 1972 | .div_floor => switch (int_info.signedness) { | 1972 | .div_floor => switch (int_info.signedness) { |
| 1973 | .signed => return isel.fail("unimplemented {s}", .{@tagName(air_tag)}), | 1973 | .signed => return isel.fail("unimplemented {t}", .{air_tag}), |
| 1974 | .unsigned => {}, | 1974 | .unsigned => {}, |
| 1975 | }, | 1975 | }, |
| 1976 | } | 1976 | } |
| ... | @@ -2012,7 +2012,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -2012,7 +2012,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2012 | try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0); | 2012 | try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0); |
| 2013 | try call.finishParams(isel); | 2013 | try call.finishParams(isel); |
| 2014 | }, | 2014 | }, |
| 2015 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 2015 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 2016 | } | 2016 | } |
| 2017 | } else switch (ty.floatBits(isel.target)) { | 2017 | } else switch (ty.floatBits(isel.target)) { |
| 2018 | else => unreachable, | 2018 | else => unreachable, |
| ... | @@ -2169,9 +2169,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -2169,9 +2169,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2169 | const bin_op = air.data(air.inst_index).bin_op; | 2169 | const bin_op = air.data(air.inst_index).bin_op; |
| 2170 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 2170 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 2171 | if (!ty.isRuntimeFloat()) { | 2171 | if (!ty.isRuntimeFloat()) { |
| 2172 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2172 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2173 | const int_info = ty.intInfo(zcu); | 2173 | const int_info = ty.intInfo(zcu); |
| 2174 | if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2174 | if (int_info.bits > 64) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2175 | | 2175 | |
| 2176 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 2176 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| 2177 | const lhs_vi = try isel.use(bin_op.lhs); | 2177 | const lhs_vi = try isel.use(bin_op.lhs); |
| ... | @@ -2494,9 +2494,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -2494,9 +2494,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2494 | const bin_op = air.data(air.inst_index).bin_op; | 2494 | const bin_op = air.data(air.inst_index).bin_op; |
| 2495 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 2495 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 2496 | if (!ty.isRuntimeFloat()) { | 2496 | if (!ty.isRuntimeFloat()) { |
| 2497 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2497 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2498 | const int_info = ty.intInfo(zcu); | 2498 | const int_info = ty.intInfo(zcu); |
| 2499 | if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2499 | if (int_info.bits > 64) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2500 | | 2500 | |
| 2501 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 2501 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| 2502 | const lhs_vi = try isel.use(bin_op.lhs); | 2502 | const lhs_vi = try isel.use(bin_op.lhs); |
| ... | @@ -2920,8 +2920,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -2920,8 +2920,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2920 | else if (ty.isAbiInt(zcu)) | 2920 | else if (ty.isAbiInt(zcu)) |
| 2921 | ty.intInfo(zcu) | 2921 | ty.intInfo(zcu) |
| 2922 | else | 2922 | else |
| 2923 | return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2923 | return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2924 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2924 | if (int_info.bits > 128) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2925 | | 2925 | |
| 2926 | const lhs_vi = try isel.use(bin_op.lhs); | 2926 | const lhs_vi = try isel.use(bin_op.lhs); |
| 2927 | const rhs_vi = try isel.use(bin_op.rhs); | 2927 | const rhs_vi = try isel.use(bin_op.rhs); |
| ... | @@ -2968,7 +2968,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -2968,7 +2968,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2968 | | 2968 | |
| 2969 | const bin_op = air.data(air.inst_index).bin_op; | 2969 | const bin_op = air.data(air.inst_index).bin_op; |
| 2970 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 2970 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 2971 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 2971 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 2972 | const int_info = ty.intInfo(zcu); | 2972 | const int_info = ty.intInfo(zcu); |
| 2973 | switch (int_info.bits) { | 2973 | switch (int_info.bits) { |
| 2974 | 0 => unreachable, | 2974 | 0 => unreachable, |
| ... | @@ -3161,7 +3161,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3161,7 +3161,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3161 | try lhs_hi64_mat.finish(isel); | 3161 | try lhs_hi64_mat.finish(isel); |
| 3162 | break :unused; | 3162 | break :unused; |
| 3163 | }, | 3163 | }, |
| 3164 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 3164 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 3165 | } | 3165 | } |
| 3166 | } | 3166 | } |
| 3167 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3167 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -3174,10 +3174,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3174,10 +3174,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3174 | const ty = ty_op.ty.toType(); | 3174 | const ty = ty_op.ty.toType(); |
| 3175 | const int_info: std.builtin.Type.Int = int_info: { | 3175 | const int_info: std.builtin.Type.Int = int_info: { |
| 3176 | if (ty_op.ty == .bool_type) break :int_info .{ .signedness = .unsigned, .bits = 1 }; | 3176 | if (ty_op.ty == .bool_type) break :int_info .{ .signedness = .unsigned, .bits = 1 }; |
| 3177 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3177 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3178 | break :int_info ty.intInfo(zcu); | 3178 | break :int_info ty.intInfo(zcu); |
| 3179 | }; | 3179 | }; |
| 3180 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3180 | if (int_info.bits > 128) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3181 | | 3181 | |
| 3182 | const src_vi = try isel.use(ty_op.operand); | 3182 | const src_vi = try isel.use(ty_op.operand); |
| 3183 | var offset = res_vi.value.size(isel); | 3183 | var offset = res_vi.value.size(isel); |
| ... | @@ -3302,7 +3302,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3302,7 +3302,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3302 | } | 3302 | } |
| 3303 | }, | 3303 | }, |
| 3304 | 128 => try dst_vi.value.move(isel, ty_op.operand), | 3304 | 128 => try dst_vi.value.move(isel, ty_op.operand), |
| 3305 | else => return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }), | 3305 | else => return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }), |
| 3306 | } | 3306 | } |
| 3307 | } else if ((dst_ty.isPtrAtRuntime(zcu) or dst_ty.isAbiInt(zcu)) and (src_ty.isPtrAtRuntime(zcu) or src_ty.isAbiInt(zcu))) { | 3307 | } else if ((dst_ty.isPtrAtRuntime(zcu) or dst_ty.isAbiInt(zcu)) and (src_ty.isPtrAtRuntime(zcu) or src_ty.isAbiInt(zcu))) { |
| 3308 | try dst_vi.value.move(isel, ty_op.operand); | 3308 | try dst_vi.value.move(isel, ty_op.operand); |
| ... | @@ -3313,7 +3313,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3313,7 +3313,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3313 | src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu)); | 3313 | src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu)); |
| 3314 | if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) { | 3314 | if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) { |
| 3315 | try dst_vi.value.move(isel, ty_op.operand); | 3315 | try dst_vi.value.move(isel, ty_op.operand); |
| 3316 | } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 3316 | } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 3317 | } else if (dst_tag == .float and src_tag == .float) { | 3317 | } else if (dst_tag == .float and src_tag == .float) { |
| 3318 | assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); | 3318 | assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); |
| 3319 | try dst_vi.value.move(isel, ty_op.operand); | 3319 | try dst_vi.value.move(isel, ty_op.operand); |
| ... | @@ -3483,7 +3483,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3483,7 +3483,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3483 | try call.paramAddress(isel, src_vi, .r1); | 3483 | try call.paramAddress(isel, src_vi, .r1); |
| 3484 | try call.paramAddress(isel, dst_vi.value, .r0); | 3484 | try call.paramAddress(isel, dst_vi.value, .r0); |
| 3485 | try call.finishParams(isel); | 3485 | try call.finishParams(isel); |
| 3486 | } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 3486 | } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 3487 | } else if (dst_tag == .array and dst_ty.childType(zcu).isAbiInt(zcu) and src_ty.isAbiInt(zcu)) { | 3487 | } else if (dst_tag == .array and dst_ty.childType(zcu).isAbiInt(zcu) and src_ty.isAbiInt(zcu)) { |
| 3488 | const dst_child_int_info = dst_ty.childType(zcu).intInfo(zcu); | 3488 | const dst_child_int_info = dst_ty.childType(zcu).intInfo(zcu); |
| 3489 | const src_int_info = src_ty.intInfo(zcu); | 3489 | const src_int_info = src_ty.intInfo(zcu); |
| ... | @@ -3510,8 +3510,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3510,8 +3510,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3510 | try call.paramAddress(isel, src_vi, .r1); | 3510 | try call.paramAddress(isel, src_vi, .r1); |
| 3511 | try call.paramAddress(isel, dst_vi.value, .r0); | 3511 | try call.paramAddress(isel, dst_vi.value, .r0); |
| 3512 | try call.finishParams(isel); | 3512 | try call.finishParams(isel); |
| 3513 | } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 3513 | } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 3514 | } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 3514 | } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 3515 | } | 3515 | } |
| 3516 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3516 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3517 | }, | 3517 | }, |
| ... | @@ -3737,7 +3737,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3737,7 +3737,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3737 | | 3737 | |
| 3738 | const ty_op = air.data(air.inst_index).ty_op; | 3738 | const ty_op = air.data(air.inst_index).ty_op; |
| 3739 | const ty = isel.air.typeOf(ty_op.operand, ip); | 3739 | const ty = isel.air.typeOf(ty_op.operand, ip); |
| 3740 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3740 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3741 | const int_info = ty.intInfo(zcu); | 3741 | const int_info = ty.intInfo(zcu); |
| 3742 | switch (int_info.bits) { | 3742 | switch (int_info.bits) { |
| 3743 | 0 => unreachable, | 3743 | 0 => unreachable, |
| ... | @@ -3769,7 +3769,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3769,7 +3769,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3769 | try src_hi64_mat.finish(isel); | 3769 | try src_hi64_mat.finish(isel); |
| 3770 | try src_lo64_mat.finish(isel); | 3770 | try src_lo64_mat.finish(isel); |
| 3771 | }, | 3771 | }, |
| 3772 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 3772 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 3773 | } | 3773 | } |
| 3774 | } | 3774 | } |
| 3775 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3775 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -3780,7 +3780,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3780,7 +3780,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3780 | | 3780 | |
| 3781 | const ty_op = air.data(air.inst_index).ty_op; | 3781 | const ty_op = air.data(air.inst_index).ty_op; |
| 3782 | const ty = isel.air.typeOf(ty_op.operand, ip); | 3782 | const ty = isel.air.typeOf(ty_op.operand, ip); |
| 3783 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3783 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3784 | const int_info = ty.intInfo(zcu); | 3784 | const int_info = ty.intInfo(zcu); |
| 3785 | switch (int_info.bits) { | 3785 | switch (int_info.bits) { |
| 3786 | 0 => unreachable, | 3786 | 0 => unreachable, |
| ... | @@ -3812,7 +3812,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3812,7 +3812,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3812 | try src_hi64_mat.finish(isel); | 3812 | try src_hi64_mat.finish(isel); |
| 3813 | try src_lo64_mat.finish(isel); | 3813 | try src_lo64_mat.finish(isel); |
| 3814 | }, | 3814 | }, |
| 3815 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 3815 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 3816 | } | 3816 | } |
| 3817 | } | 3817 | } |
| 3818 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3818 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -3823,9 +3823,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3823,9 +3823,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3823 | | 3823 | |
| 3824 | const ty_op = air.data(air.inst_index).ty_op; | 3824 | const ty_op = air.data(air.inst_index).ty_op; |
| 3825 | const ty = isel.air.typeOf(ty_op.operand, ip); | 3825 | const ty = isel.air.typeOf(ty_op.operand, ip); |
| 3826 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3826 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3827 | const int_info = ty.intInfo(zcu); | 3827 | const int_info = ty.intInfo(zcu); |
| 3828 | if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3828 | if (int_info.bits > 64) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3829 | | 3829 | |
| 3830 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 3830 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| 3831 | const src_vi = try isel.use(ty_op.operand); | 3831 | const src_vi = try isel.use(ty_op.operand); |
| ... | @@ -3877,9 +3877,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3877,9 +3877,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3877 | | 3877 | |
| 3878 | const ty_op = air.data(air.inst_index).ty_op; | 3878 | const ty_op = air.data(air.inst_index).ty_op; |
| 3879 | const ty = ty_op.ty.toType(); | 3879 | const ty = ty_op.ty.toType(); |
| 3880 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3880 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3881 | const int_info = ty.intInfo(zcu); | 3881 | const int_info = ty.intInfo(zcu); |
| 3882 | if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3882 | if (int_info.bits > 64) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3883 | | 3883 | |
| 3884 | if (int_info.bits == 8) break :unused try res_vi.value.move(isel, ty_op.operand); | 3884 | if (int_info.bits == 8) break :unused try res_vi.value.move(isel, ty_op.operand); |
| 3885 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 3885 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| ... | @@ -3941,9 +3941,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3941,9 +3941,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3941 | | 3941 | |
| 3942 | const ty_op = air.data(air.inst_index).ty_op; | 3942 | const ty_op = air.data(air.inst_index).ty_op; |
| 3943 | const ty = ty_op.ty.toType(); | 3943 | const ty = ty_op.ty.toType(); |
| 3944 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3944 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3945 | const int_info = ty.intInfo(zcu); | 3945 | const int_info = ty.intInfo(zcu); |
| 3946 | if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 3946 | if (int_info.bits > 64) return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 3947 | | 3947 | |
| 3948 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 3948 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| 3949 | const src_vi = try isel.use(ty_op.operand); | 3949 | const src_vi = try isel.use(ty_op.operand); |
| ... | @@ -4244,7 +4244,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -4244,7 +4244,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4244 | const ty_op = air.data(air.inst_index).ty_op; | 4244 | const ty_op = air.data(air.inst_index).ty_op; |
| 4245 | const ty = ty_op.ty.toType(); | 4245 | const ty = ty_op.ty.toType(); |
| 4246 | if (!ty.isRuntimeFloat()) { | 4246 | if (!ty.isRuntimeFloat()) { |
| 4247 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | 4247 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| 4248 | switch (ty.intInfo(zcu).bits) { | 4248 | switch (ty.intInfo(zcu).bits) { |
| 4249 | 0 => unreachable, | 4249 | 0 => unreachable, |
| 4250 | 1...32 => { | 4250 | 1...32 => { |
| ... | @@ -4306,7 +4306,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -4306,7 +4306,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4306 | try src_lo64_mat.finish(isel); | 4306 | try src_lo64_mat.finish(isel); |
| 4307 | try src_hi64_mat.finish(isel); | 4307 | try src_hi64_mat.finish(isel); |
| 4308 | }, | 4308 | }, |
| 4309 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | 4309 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), |
| 4310 | } | 4310 | } |
| 4311 | } else switch (ty.floatBits(isel.target)) { | 4311 | } else switch (ty.floatBits(isel.target)) { |
| 4312 | else => unreachable, | 4312 | else => unreachable, |
| ... | @@ -4465,216 +4465,61 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -4465,216 +4465,61 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4465 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | 4465 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 4466 | defer res_vi.value.deref(isel); | 4466 | defer res_vi.value.deref(isel); |
| 4467 | | 4467 | |
| 4468 | var bin_op = air.data(air.inst_index).bin_op; | 4468 | const bin_op = air.data(air.inst_index).bin_op; |
| 4469 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 4469 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 4470 | if (!ty.isRuntimeFloat()) { | 4470 | switch (ip.indexToKey(ty.toIntern())) { |
| 4471 | const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type) | 4471 | else => {}, |
| 4472 | .{ .signedness = .unsigned, .bits = 1 } | 4472 | .opt_type => |payload_ty| switch (air_tag) { |
| 4473 | else if (ty.isAbiInt(zcu)) | | |
| 4474 | ty.intInfo(zcu) | | |
| 4475 | else if (ty.isPtrAtRuntime(zcu)) | | |
| 4476 | .{ .signedness = .unsigned, .bits = 64 } | | |
| 4477 | else | | |
| 4478 | return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | | |
| 4479 | if (int_info.bits > 256) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | | |
| 4480 | | | |
| 4481 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | | |
| 4482 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (air_tag) { | | |
| 4483 | else => unreachable, | 4473 | else => unreachable, |
| 4484 | .cmp_lt => switch (int_info.signedness) { | 4474 | .cmp_eq, .cmp_neq => if (!ty.optionalReprIsPayload(zcu)) { |
| 4485 | .signed => .lt, | 4475 | const lhs_vi = try isel.use(bin_op.lhs); |
| 4486 | .unsigned => .lo, | 4476 | const rhs_vi = try isel.use(bin_op.rhs); |
| 4487 | }, | 4477 | const payload_size = ZigType.abiSize(.fromInterned(payload_ty), zcu); |
| 4488 | .cmp_lte => switch (int_info.bits) { | 4478 | var lhs_payload_part_it = lhs_vi.field(ty, 0, payload_size); |
| 4489 | else => unreachable, | 4479 | const lhs_payload_part_vi = try lhs_payload_part_it.only(isel); |
| 4490 | 1...64 => switch (int_info.signedness) { | 4480 | var rhs_payload_part_it = rhs_vi.field(ty, 0, payload_size); |
| 4491 | .signed => .le, | 4481 | const rhs_payload_part_vi = try rhs_payload_part_it.only(isel); |
| 4492 | .unsigned => .ls, | 4482 | const cmp_info = try isel.cmp( |
| 4493 | }, | 4483 | try res_vi.value.defReg(isel) orelse break :unused, |
| 4494 | 65...128 => { | 4484 | .fromInterned(payload_ty), |
| 4495 | std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs); | 4485 | lhs_payload_part_vi.?, |
| 4496 | continue :cond .cmp_gte; | 4486 | air_tag.toCmpOp().?, |
| 4497 | }, | 4487 | rhs_payload_part_vi.?, |
| 4498 | }, | 4488 | ); |
| 4499 | .cmp_eq => .eq, | 4489 | try isel.emit(.@"b."( |
| 4500 | .cmp_gte => switch (int_info.signedness) { | 4490 | .vc, |
| 4501 | .signed => .ge, | 4491 | @intCast((isel.instructions.items.len + 1 - cmp_info.cset_label) << 2), |
| 4502 | .unsigned => .hs, | 4492 | )); |
| 4503 | }, | 4493 | var lhs_has_value_part_it = lhs_vi.field(ty, payload_size, 1); |
| 4504 | .cmp_gt => switch (int_info.bits) { | 4494 | const lhs_has_value_part_vi = try lhs_has_value_part_it.only(isel); |
| 4505 | else => unreachable, | 4495 | const lhs_has_value_part_mat = try lhs_has_value_part_vi.?.matReg(isel); |
| 4506 | 1...64 => switch (int_info.signedness) { | 4496 | var rhs_has_value_part_it = rhs_vi.field(ty, payload_size, 1); |
| 4507 | .signed => .gt, | 4497 | const rhs_has_value_part_vi = try rhs_has_value_part_it.only(isel); |
| 4508 | .unsigned => .hi, | 4498 | const rhs_has_value_part_mat = try rhs_has_value_part_vi.?.matReg(isel); |
| 4509 | }, | 4499 | try isel.emit(.ccmp( |
| 4510 | 65...128 => { | 4500 | lhs_has_value_part_mat.ra.w(), |
| 4511 | std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs); | 4501 | .{ .register = rhs_has_value_part_mat.ra.w() }, |
| 4512 | continue :cond .cmp_lt; | 4502 | .{ .n = false, .z = false, .c = false, .v = true }, |
| 4513 | }, | 4503 | .eq, |
| | 4504 | )); |
| | 4505 | try isel.emit(.ands( |
| | 4506 | .wzr, |
| | 4507 | lhs_has_value_part_mat.ra.w(), |
| | 4508 | .{ .register = rhs_has_value_part_mat.ra.w() }, |
| | 4509 | )); |
| | 4510 | try rhs_has_value_part_mat.finish(isel); |
| | 4511 | try lhs_has_value_part_mat.finish(isel); |
| | 4512 | break :unused; |
| 4514 | }, | 4513 | }, |
| 4515 | .cmp_neq => .ne, | | |
| 4516 | }))); | | |
| 4517 | | | |
| 4518 | const lhs_vi = try isel.use(bin_op.lhs); | | |
| 4519 | const rhs_vi = try isel.use(bin_op.rhs); | | |
| 4520 | var part_offset = lhs_vi.size(isel); | | |
| 4521 | while (part_offset > 0) { | | |
| 4522 | const part_size = @min(part_offset, 8); | | |
| 4523 | part_offset -= part_size; | | |
| 4524 | var lhs_part_it = lhs_vi.field(ty, part_offset, part_size); | | |
| 4525 | const lhs_part_vi = try lhs_part_it.only(isel); | | |
| 4526 | const lhs_part_mat = try lhs_part_vi.?.matReg(isel); | | |
| 4527 | var rhs_part_it = rhs_vi.field(ty, part_offset, part_size); | | |
| 4528 | const rhs_part_vi = try rhs_part_it.only(isel); | | |
| 4529 | const rhs_part_mat = try rhs_part_vi.?.matReg(isel); | | |
| 4530 | try isel.emit(switch (part_size) { | | |
| 4531 | else => unreachable, | | |
| 4532 | 1...4 => switch (part_offset) { | | |
| 4533 | 0 => .subs(.wzr, lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }), | | |
| 4534 | else => switch (air_tag) { | | |
| 4535 | else => unreachable, | | |
| 4536 | .cmp_lt, .cmp_lte, .cmp_gte, .cmp_gt => .sbcs( | | |
| 4537 | .wzr, | | |
| 4538 | lhs_part_mat.ra.w(), | | |
| 4539 | rhs_part_mat.ra.w(), | | |
| 4540 | ), | | |
| 4541 | .cmp_eq, .cmp_neq => .ccmp( | | |
| 4542 | lhs_part_mat.ra.w(), | | |
| 4543 | .{ .register = rhs_part_mat.ra.w() }, | | |
| 4544 | .{ .n = false, .z = false, .c = false, .v = false }, | | |
| 4545 | .eq, | | |
| 4546 | ), | | |
| 4547 | }, | | |
| 4548 | }, | | |
| 4549 | 5...8 => switch (part_offset) { | | |
| 4550 | 0 => .subs(.xzr, lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }), | | |
| 4551 | else => switch (air_tag) { | | |
| 4552 | else => unreachable, | | |
| 4553 | .cmp_lt, .cmp_lte, .cmp_gte, .cmp_gt => .sbcs( | | |
| 4554 | .xzr, | | |
| 4555 | lhs_part_mat.ra.x(), | | |
| 4556 | rhs_part_mat.ra.x(), | | |
| 4557 | ), | | |
| 4558 | .cmp_eq, .cmp_neq => .ccmp( | | |
| 4559 | lhs_part_mat.ra.x(), | | |
| 4560 | .{ .register = rhs_part_mat.ra.x() }, | | |
| 4561 | .{ .n = false, .z = false, .c = false, .v = false }, | | |
| 4562 | .eq, | | |
| 4563 | ), | | |
| 4564 | }, | | |
| 4565 | }, | | |
| 4566 | }); | | |
| 4567 | try rhs_part_mat.finish(isel); | | |
| 4568 | try lhs_part_mat.finish(isel); | | |
| 4569 | } | | |
| 4570 | } else switch (ty.floatBits(isel.target)) { | | |
| 4571 | else => unreachable, | | |
| 4572 | 16, 32, 64 => |bits| { | | |
| 4573 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | | |
| 4574 | const need_fcvt = switch (bits) { | | |
| 4575 | else => unreachable, | | |
| 4576 | 16 => !isel.target.cpu.has(.aarch64, .fullfp16), | | |
| 4577 | 32, 64 => false, | | |
| 4578 | }; | | |
| 4579 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(switch (air_tag) { | | |
| 4580 | else => unreachable, | | |
| 4581 | .cmp_lt => .lo, | | |
| 4582 | .cmp_lte => .ls, | | |
| 4583 | .cmp_eq => .eq, | | |
| 4584 | .cmp_gte => .ge, | | |
| 4585 | .cmp_gt => .gt, | | |
| 4586 | .cmp_neq => .ne, | | |
| 4587 | }))); | | |
| 4588 | | | |
| 4589 | const lhs_vi = try isel.use(bin_op.lhs); | | |
| 4590 | const rhs_vi = try isel.use(bin_op.rhs); | | |
| 4591 | const lhs_mat = try lhs_vi.matReg(isel); | | |
| 4592 | const rhs_mat = try rhs_vi.matReg(isel); | | |
| 4593 | const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra; | | |
| 4594 | defer if (need_fcvt) isel.freeReg(lhs_ra); | | |
| 4595 | const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra; | | |
| 4596 | defer if (need_fcvt) isel.freeReg(rhs_ra); | | |
| 4597 | try isel.emit(bits: switch (bits) { | | |
| 4598 | else => unreachable, | | |
| 4599 | 16 => if (need_fcvt) | | |
| 4600 | continue :bits 32 | | |
| 4601 | else | | |
| 4602 | .fcmp(lhs_ra.h(), .{ .register = rhs_ra.h() }), | | |
| 4603 | 32 => .fcmp(lhs_ra.s(), .{ .register = rhs_ra.s() }), | | |
| 4604 | 64 => .fcmp(lhs_ra.d(), .{ .register = rhs_ra.d() }), | | |
| 4605 | }); | | |
| 4606 | if (need_fcvt) { | | |
| 4607 | try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h())); | | |
| 4608 | try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h())); | | |
| 4609 | } | | |
| 4610 | try rhs_mat.finish(isel); | | |
| 4611 | try lhs_mat.finish(isel); | | |
| 4612 | }, | | |
| 4613 | 80, 128 => |bits| { | | |
| 4614 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | | |
| 4615 | | | |
| 4616 | try call.prepareReturn(isel); | | |
| 4617 | try call.returnFill(isel, .r0); | | |
| 4618 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (air_tag) { | | |
| 4619 | else => unreachable, | | |
| 4620 | .cmp_lt => .lt, | | |
| 4621 | .cmp_lte => .le, | | |
| 4622 | .cmp_eq => .eq, | | |
| 4623 | .cmp_gte => { | | |
| 4624 | std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs); | | |
| 4625 | continue :cond .cmp_lte; | | |
| 4626 | }, | | |
| 4627 | .cmp_gt => { | | |
| 4628 | std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs); | | |
| 4629 | continue :cond .cmp_lt; | | |
| 4630 | }, | | |
| 4631 | .cmp_neq => .ne, | | |
| 4632 | }))); | | |
| 4633 | try isel.emit(.subs(.wzr, .w0, .{ .immediate = 0 })); | | |
| 4634 | try call.finishReturn(isel); | | |
| 4635 | | | |
| 4636 | try call.prepareCallee(isel); | | |
| 4637 | try isel.global_relocs.append(gpa, .{ | | |
| 4638 | .name = switch (bits) { | | |
| 4639 | else => unreachable, | | |
| 4640 | 16 => "__cmphf2", | | |
| 4641 | 32 => "__cmpsf2", | | |
| 4642 | 64 => "__cmpdf2", | | |
| 4643 | 80 => "__cmpxf2", | | |
| 4644 | 128 => "__cmptf2", | | |
| 4645 | }, | | |
| 4646 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | | |
| 4647 | }); | | |
| 4648 | try isel.emit(.bl(0)); | | |
| 4649 | try call.finishCallee(isel); | | |
| 4650 | | | |
| 4651 | try call.prepareParams(isel); | | |
| 4652 | const lhs_vi = try isel.use(bin_op.lhs); | | |
| 4653 | const rhs_vi = try isel.use(bin_op.rhs); | | |
| 4654 | switch (bits) { | | |
| 4655 | else => unreachable, | | |
| 4656 | 16, 32, 64, 128 => { | | |
| 4657 | try call.paramLiveOut(isel, rhs_vi, .v1); | | |
| 4658 | try call.paramLiveOut(isel, lhs_vi, .v0); | | |
| 4659 | }, | | |
| 4660 | 80 => { | | |
| 4661 | var rhs_hi16_it = rhs_vi.field(ty, 8, 8); | | |
| 4662 | const rhs_hi16_vi = try rhs_hi16_it.only(isel); | | |
| 4663 | try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3); | | |
| 4664 | var rhs_lo64_it = rhs_vi.field(ty, 0, 8); | | |
| 4665 | const rhs_lo64_vi = try rhs_lo64_it.only(isel); | | |
| 4666 | try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2); | | |
| 4667 | var lhs_hi16_it = lhs_vi.field(ty, 8, 8); | | |
| 4668 | const lhs_hi16_vi = try lhs_hi16_it.only(isel); | | |
| 4669 | try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1); | | |
| 4670 | var lhs_lo64_it = lhs_vi.field(ty, 0, 8); | | |
| 4671 | const lhs_lo64_vi = try lhs_lo64_it.only(isel); | | |
| 4672 | try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0); | | |
| 4673 | }, | | |
| 4674 | } | | |
| 4675 | try call.finishParams(isel); | | |
| 4676 | }, | 4514 | }, |
| 4677 | } | 4515 | } |
| | 4516 | _ = try isel.cmp( |
| | 4517 | try res_vi.value.defReg(isel) orelse break :unused, |
| | 4518 | ty, |
| | 4519 | try isel.use(bin_op.lhs), |
| | 4520 | air_tag.toCmpOp().?, |
| | 4521 | try isel.use(bin_op.rhs), |
| | 4522 | ); |
| 4678 | } | 4523 | } |
| 4679 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 4524 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4680 | }, | 4525 | }, |
| ... | @@ -5497,7 +5342,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -5497,7 +5342,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 5497 | try src_mat.finish(isel); | 5342 | try src_mat.finish(isel); |
| 5498 | }, | 5343 | }, |
| 5499 | }; | 5344 | }; |
| 5500 | } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 5345 | } else return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 5501 | } | 5346 | } |
| 5502 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 5347 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 5503 | }, | 5348 | }, |
| ... | @@ -5517,7 +5362,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -5517,7 +5362,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 5517 | .int => .integer_out_of_bounds, | 5362 | .int => .integer_out_of_bounds, |
| 5518 | .@"enum" => { | 5363 | .@"enum" => { |
| 5519 | if (!dst_ty.isNonexhaustiveEnum(zcu)) { | 5364 | if (!dst_ty.isNonexhaustiveEnum(zcu)) { |
| 5520 | return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 5365 | return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 5521 | } | 5366 | } |
| 5522 | break :panic_id .invalid_enum_value; | 5367 | break :panic_id .invalid_enum_value; |
| 5523 | }, | 5368 | }, |
| ... | @@ -5599,7 +5444,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -5599,7 +5444,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 5599 | try src_mat.finish(isel); | 5444 | try src_mat.finish(isel); |
| 5600 | } | 5445 | } |
| 5601 | } | 5446 | } |
| 5602 | } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 5447 | } else return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 5603 | } | 5448 | } |
| 5604 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 5449 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 5605 | }, | 5450 | }, |
| ... | @@ -5610,7 +5455,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -5610,7 +5455,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 5610 | const ty_op = air.data(air.inst_index).ty_op; | 5455 | const ty_op = air.data(air.inst_index).ty_op; |
| 5611 | const dst_ty = ty_op.ty.toType(); | 5456 | const dst_ty = ty_op.ty.toType(); |
| 5612 | const src_ty = isel.air.typeOf(ty_op.operand, ip); | 5457 | const src_ty = isel.air.typeOf(ty_op.operand, ip); |
| 5613 | if (!dst_ty.isAbiInt(zcu) or !src_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 5458 | if (!dst_ty.isAbiInt(zcu) or !src_ty.isAbiInt(zcu)) return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 5614 | const dst_int_info = dst_ty.intInfo(zcu); | 5459 | const dst_int_info = dst_ty.intInfo(zcu); |
| 5615 | switch (dst_int_info.bits) { | 5460 | switch (dst_int_info.bits) { |
| 5616 | 0 => unreachable, | 5461 | 0 => unreachable, |
| ... | @@ -5683,9 +5528,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -5683,9 +5528,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 5683 | try src_lo64_vi.?.liveOut(isel, dst_lo64_ra); | 5528 | try src_lo64_vi.?.liveOut(isel, dst_lo64_ra); |
| 5684 | } | 5529 | } |
| 5685 | }, | 5530 | }, |
| 5686 | else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }), | 5531 | else => return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }), |
| 5687 | }, | 5532 | }, |
| 5688 | else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }), | 5533 | else => return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }), |
| 5689 | } | 5534 | } |
| 5690 | } | 5535 | } |
| 5691 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 5536 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -6487,7 +6332,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -6487,7 +6332,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6487 | const ty_op = air.data(air.inst_index).ty_op; | 6332 | const ty_op = air.data(air.inst_index).ty_op; |
| 6488 | const dst_ty = ty_op.ty.toType(); | 6333 | const dst_ty = ty_op.ty.toType(); |
| 6489 | const src_ty = isel.air.typeOf(ty_op.operand, ip); | 6334 | const src_ty = isel.air.typeOf(ty_op.operand, ip); |
| 6490 | if (!dst_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 6335 | if (!dst_ty.isAbiInt(zcu)) return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 6491 | const dst_int_info = dst_ty.intInfo(zcu); | 6336 | const dst_int_info = dst_ty.intInfo(zcu); |
| 6492 | const src_bits = src_ty.floatBits(isel.target); | 6337 | const src_bits = src_ty.floatBits(isel.target); |
| 6493 | switch (@max(dst_int_info.bits, src_bits)) { | 6338 | switch (@max(dst_int_info.bits, src_bits)) { |
| ... | @@ -6617,7 +6462,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -6617,7 +6462,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6617 | } | 6462 | } |
| 6618 | try call.finishParams(isel); | 6463 | try call.finishParams(isel); |
| 6619 | }, | 6464 | }, |
| 6620 | else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }), | 6465 | else => return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }), |
| 6621 | } | 6466 | } |
| 6622 | } | 6467 | } |
| 6623 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6468 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -6630,7 +6475,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -6630,7 +6475,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6630 | const dst_ty = ty_op.ty.toType(); | 6475 | const dst_ty = ty_op.ty.toType(); |
| 6631 | const src_ty = isel.air.typeOf(ty_op.operand, ip); | 6476 | const src_ty = isel.air.typeOf(ty_op.operand, ip); |
| 6632 | const dst_bits = dst_ty.floatBits(isel.target); | 6477 | const dst_bits = dst_ty.floatBits(isel.target); |
| 6633 | if (!src_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | 6478 | if (!src_ty.isAbiInt(zcu)) return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| 6634 | const src_int_info = src_ty.intInfo(zcu); | 6479 | const src_int_info = src_ty.intInfo(zcu); |
| 6635 | switch (@max(dst_bits, src_int_info.bits)) { | 6480 | switch (@max(dst_bits, src_int_info.bits)) { |
| 6636 | 0 => unreachable, | 6481 | 0 => unreachable, |
| ... | @@ -6757,7 +6602,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -6757,7 +6602,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6757 | } | 6602 | } |
| 6758 | try call.finishParams(isel); | 6603 | try call.finishParams(isel); |
| 6759 | }, | 6604 | }, |
| 6760 | else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }), | 6605 | else => return isel.fail("too big {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }), |
| 6761 | } | 6606 | } |
| 6762 | } | 6607 | } |
| 6763 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6608 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| ... | @@ -6836,7 +6681,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -6836,7 +6681,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6836 | | 6681 | |
| 6837 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6682 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6838 | }, | 6683 | }, |
| 6839 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }), | 6684 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(dst_ty) }), |
| 6840 | } | 6685 | } |
| 6841 | }; | 6686 | }; |
| 6842 | | 6687 | |
| ... | @@ -7157,7 +7002,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -7157,7 +7002,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 7157 | else => unreachable, | 7002 | else => unreachable, |
| 7158 | }, | 7003 | }, |
| 7159 | }), | 7004 | }), |
| 7160 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(union_ty) }), | 7005 | else => return isel.fail("too big {t} {f}", .{ air_tag, isel.fmtType(union_ty) }), |
| 7161 | } | 7006 | } |
| 7162 | } | 7007 | } |
| 7163 | var payload_it = union_vi.value.field(union_ty, union_layout.payloadOffset(), union_layout.payload_size); | 7008 | var payload_it = union_vi.value.field(union_ty, union_layout.payloadOffset(), union_layout.payload_size); |
| ... | @@ -8499,6 +8344,217 @@ fn ctzLimb( | ... | @@ -8499,6 +8344,217 @@ fn ctzLimb( |
| 8499 | } | 8344 | } |
| 8500 | } | 8345 | } |
| 8501 | | 8346 | |
| | 8347 | fn cmp( |
| | 8348 | isel: *Select, |
| | 8349 | res_ra: Register.Alias, |
| | 8350 | ty: ZigType, |
| | 8351 | orig_lhs_vi: Value.Index, |
| | 8352 | op: std.math.CompareOperator, |
| | 8353 | orig_rhs_vi: Value.Index, |
| | 8354 | ) !struct { cset_label: usize } { |
| | 8355 | var lhs_vi = orig_lhs_vi; |
| | 8356 | var rhs_vi = orig_rhs_vi; |
| | 8357 | if (!ty.isRuntimeFloat()) { |
| | 8358 | const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type) |
| | 8359 | .{ .signedness = .unsigned, .bits = 1 } |
| | 8360 | else if (ty.isAbiInt(isel.pt.zcu)) |
| | 8361 | ty.intInfo(isel.pt.zcu) |
| | 8362 | else if (ty.isPtrAtRuntime(isel.pt.zcu)) |
| | 8363 | .{ .signedness = .unsigned, .bits = 64 } |
| | 8364 | else |
| | 8365 | return isel.fail("bad cmp_{t} {f}", .{ op, isel.fmtType(ty) }); |
| | 8366 | if (int_info.bits > 256) return isel.fail("too big cmp_{t} {f}", .{ op, isel.fmtType(ty) }); |
| | 8367 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (op) { |
| | 8368 | .lt => switch (int_info.signedness) { |
| | 8369 | .signed => .lt, |
| | 8370 | .unsigned => .lo, |
| | 8371 | }, |
| | 8372 | .lte => switch (int_info.bits) { |
| | 8373 | else => unreachable, |
| | 8374 | 1...64 => switch (int_info.signedness) { |
| | 8375 | .signed => .le, |
| | 8376 | .unsigned => .ls, |
| | 8377 | }, |
| | 8378 | 65...128 => { |
| | 8379 | std.mem.swap(Value.Index, &lhs_vi, &rhs_vi); |
| | 8380 | continue :cond .gte; |
| | 8381 | }, |
| | 8382 | }, |
| | 8383 | .eq => .eq, |
| | 8384 | .gte => switch (int_info.signedness) { |
| | 8385 | .signed => .ge, |
| | 8386 | .unsigned => .hs, |
| | 8387 | }, |
| | 8388 | .gt => switch (int_info.bits) { |
| | 8389 | else => unreachable, |
| | 8390 | 1...64 => switch (int_info.signedness) { |
| | 8391 | .signed => .gt, |
| | 8392 | .unsigned => .hi, |
| | 8393 | }, |
| | 8394 | 65...128 => { |
| | 8395 | std.mem.swap(Value.Index, &lhs_vi, &rhs_vi); |
| | 8396 | continue :cond .lt; |
| | 8397 | }, |
| | 8398 | }, |
| | 8399 | .neq => .ne, |
| | 8400 | }))); |
| | 8401 | const cset_label = isel.instructions.items.len; |
| | 8402 | |
| | 8403 | var part_offset = lhs_vi.size(isel); |
| | 8404 | while (part_offset > 0) { |
| | 8405 | const part_size = @min(part_offset, 8); |
| | 8406 | part_offset -= part_size; |
| | 8407 | var lhs_part_it = lhs_vi.field(ty, part_offset, part_size); |
| | 8408 | const lhs_part_vi = try lhs_part_it.only(isel); |
| | 8409 | const lhs_part_mat = try lhs_part_vi.?.matReg(isel); |
| | 8410 | var rhs_part_it = rhs_vi.field(ty, part_offset, part_size); |
| | 8411 | const rhs_part_vi = try rhs_part_it.only(isel); |
| | 8412 | const rhs_part_mat = try rhs_part_vi.?.matReg(isel); |
| | 8413 | try isel.emit(switch (part_size) { |
| | 8414 | else => unreachable, |
| | 8415 | 1...4 => switch (part_offset) { |
| | 8416 | 0 => .subs(.wzr, lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }), |
| | 8417 | else => switch (op) { |
| | 8418 | .lt, .lte, .gte, .gt => .sbcs( |
| | 8419 | .wzr, |
| | 8420 | lhs_part_mat.ra.w(), |
| | 8421 | rhs_part_mat.ra.w(), |
| | 8422 | ), |
| | 8423 | .eq, .neq => .ccmp( |
| | 8424 | lhs_part_mat.ra.w(), |
| | 8425 | .{ .register = rhs_part_mat.ra.w() }, |
| | 8426 | .{ .n = false, .z = false, .c = false, .v = false }, |
| | 8427 | .eq, |
| | 8428 | ), |
| | 8429 | }, |
| | 8430 | }, |
| | 8431 | 5...8 => switch (part_offset) { |
| | 8432 | 0 => .subs(.xzr, lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }), |
| | 8433 | else => switch (op) { |
| | 8434 | .lt, .lte, .gte, .gt => .sbcs( |
| | 8435 | .xzr, |
| | 8436 | lhs_part_mat.ra.x(), |
| | 8437 | rhs_part_mat.ra.x(), |
| | 8438 | ), |
| | 8439 | .eq, .neq => .ccmp( |
| | 8440 | lhs_part_mat.ra.x(), |
| | 8441 | .{ .register = rhs_part_mat.ra.x() }, |
| | 8442 | .{ .n = false, .z = false, .c = false, .v = false }, |
| | 8443 | .eq, |
| | 8444 | ), |
| | 8445 | }, |
| | 8446 | }, |
| | 8447 | }); |
| | 8448 | try rhs_part_mat.finish(isel); |
| | 8449 | try lhs_part_mat.finish(isel); |
| | 8450 | } |
| | 8451 | return .{ .cset_label = cset_label }; |
| | 8452 | } |
| | 8453 | switch (ty.floatBits(isel.target)) { |
| | 8454 | else => unreachable, |
| | 8455 | 16, 32, 64 => |bits| { |
| | 8456 | const need_fcvt = switch (bits) { |
| | 8457 | else => unreachable, |
| | 8458 | 16 => !isel.target.cpu.has(.aarch64, .fullfp16), |
| | 8459 | 32, 64 => false, |
| | 8460 | }; |
| | 8461 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(switch (op) { |
| | 8462 | .lt => .lo, |
| | 8463 | .lte => .ls, |
| | 8464 | .eq => .eq, |
| | 8465 | .gte => .ge, |
| | 8466 | .gt => .gt, |
| | 8467 | .neq => .ne, |
| | 8468 | }))); |
| | 8469 | const cset_label = isel.instructions.items.len; |
| | 8470 | |
| | 8471 | const lhs_mat = try lhs_vi.matReg(isel); |
| | 8472 | const rhs_mat = try rhs_vi.matReg(isel); |
| | 8473 | const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra; |
| | 8474 | defer if (need_fcvt) isel.freeReg(lhs_ra); |
| | 8475 | const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra; |
| | 8476 | defer if (need_fcvt) isel.freeReg(rhs_ra); |
| | 8477 | try isel.emit(bits: switch (bits) { |
| | 8478 | else => unreachable, |
| | 8479 | 16 => if (need_fcvt) |
| | 8480 | continue :bits 32 |
| | 8481 | else |
| | 8482 | .fcmp(lhs_ra.h(), .{ .register = rhs_ra.h() }), |
| | 8483 | 32 => .fcmp(lhs_ra.s(), .{ .register = rhs_ra.s() }), |
| | 8484 | 64 => .fcmp(lhs_ra.d(), .{ .register = rhs_ra.d() }), |
| | 8485 | }); |
| | 8486 | if (need_fcvt) { |
| | 8487 | try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h())); |
| | 8488 | try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h())); |
| | 8489 | } |
| | 8490 | try rhs_mat.finish(isel); |
| | 8491 | try lhs_mat.finish(isel); |
| | 8492 | return .{ .cset_label = cset_label }; |
| | 8493 | }, |
| | 8494 | 80, 128 => |bits| { |
| | 8495 | try call.prepareReturn(isel); |
| | 8496 | try call.returnFill(isel, .r0); |
| | 8497 | try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (op) { |
| | 8498 | .lt => .lt, |
| | 8499 | .lte => .le, |
| | 8500 | .eq => .eq, |
| | 8501 | .gte => { |
| | 8502 | std.mem.swap(Value.Index, &lhs_vi, &rhs_vi); |
| | 8503 | continue :cond .lte; |
| | 8504 | }, |
| | 8505 | .gt => { |
| | 8506 | std.mem.swap(Value.Index, &lhs_vi, &rhs_vi); |
| | 8507 | continue :cond .lt; |
| | 8508 | }, |
| | 8509 | .neq => .ne, |
| | 8510 | }))); |
| | 8511 | const cset_label = isel.instructions.items.len; |
| | 8512 | try isel.emit(.subs(.wzr, .w0, .{ .immediate = 0 })); |
| | 8513 | try call.finishReturn(isel); |
| | 8514 | |
| | 8515 | try call.prepareCallee(isel); |
| | 8516 | try isel.global_relocs.append(isel.pt.zcu.gpa, .{ |
| | 8517 | .name = switch (bits) { |
| | 8518 | else => unreachable, |
| | 8519 | 16 => "__cmphf2", |
| | 8520 | 32 => "__cmpsf2", |
| | 8521 | 64 => "__cmpdf2", |
| | 8522 | 80 => "__cmpxf2", |
| | 8523 | 128 => "__cmptf2", |
| | 8524 | }, |
| | 8525 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| | 8526 | }); |
| | 8527 | try isel.emit(.bl(0)); |
| | 8528 | try call.finishCallee(isel); |
| | 8529 | |
| | 8530 | try call.prepareParams(isel); |
| | 8531 | switch (bits) { |
| | 8532 | else => unreachable, |
| | 8533 | 16, 32, 64, 128 => { |
| | 8534 | try call.paramLiveOut(isel, rhs_vi, .v1); |
| | 8535 | try call.paramLiveOut(isel, lhs_vi, .v0); |
| | 8536 | }, |
| | 8537 | 80 => { |
| | 8538 | var rhs_hi16_it = rhs_vi.field(ty, 8, 8); |
| | 8539 | const rhs_hi16_vi = try rhs_hi16_it.only(isel); |
| | 8540 | try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3); |
| | 8541 | var rhs_lo64_it = rhs_vi.field(ty, 0, 8); |
| | 8542 | const rhs_lo64_vi = try rhs_lo64_it.only(isel); |
| | 8543 | try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2); |
| | 8544 | var lhs_hi16_it = lhs_vi.field(ty, 8, 8); |
| | 8545 | const lhs_hi16_vi = try lhs_hi16_it.only(isel); |
| | 8546 | try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1); |
| | 8547 | var lhs_lo64_it = lhs_vi.field(ty, 0, 8); |
| | 8548 | const lhs_lo64_vi = try lhs_lo64_it.only(isel); |
| | 8549 | try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0); |
| | 8550 | }, |
| | 8551 | } |
| | 8552 | try call.finishParams(isel); |
| | 8553 | return .{ .cset_label = cset_label }; |
| | 8554 | }, |
| | 8555 | } |
| | 8556 | } |
| | 8557 | |
| 8502 | fn loadReg( | 8558 | fn loadReg( |
| 8503 | isel: *Select, | 8559 | isel: *Select, |
| 8504 | ra: Register.Alias, | 8560 | ra: Register.Alias, |
| ... | @@ -9272,9 +9328,9 @@ pub const Value = struct { | ... | @@ -9272,9 +9328,9 @@ pub const Value = struct { |
| 9272 | opts: AddOrSubtractOptions, | 9328 | opts: AddOrSubtractOptions, |
| 9273 | ) !void { | 9329 | ) !void { |
| 9274 | const zcu = isel.pt.zcu; | 9330 | const zcu = isel.pt.zcu; |
| 9275 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); | 9331 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {t} {f}", .{ op, isel.fmtType(ty) }); |
| 9276 | const int_info = ty.intInfo(zcu); | 9332 | const int_info = ty.intInfo(zcu); |
| 9277 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); | 9333 | if (int_info.bits > 128) return isel.fail("too big {t} {f}", .{ op, isel.fmtType(ty) }); |
| 9278 | var part_offset = res_vi.size(isel); | 9334 | var part_offset = res_vi.size(isel); |
| 9279 | var need_wrap = switch (opts.overflow) { | 9335 | var need_wrap = switch (opts.overflow) { |
| 9280 | .@"unreachable" => false, | 9336 | .@"unreachable" => false, |
| ... | @@ -10783,7 +10839,7 @@ pub const Value = struct { | ... | @@ -10783,7 +10839,7 @@ pub const Value = struct { |
| 10783 | .err_name => continue :constant_key .{ .undef = error_union_type.payload_type }, | 10839 | .err_name => continue :constant_key .{ .undef = error_union_type.payload_type }, |
| 10784 | .payload => |payload| { | 10840 | .payload => |payload| { |
| 10785 | constant = payload; | 10841 | constant = payload; |
| 10786 | constant_key = ip.indexToKey(payload); | 10842 | constant_key = ip.indexToKey(constant); |
| 10787 | continue :constant_key constant_key; | 10843 | continue :constant_key constant_key; |
| 10788 | }, | 10844 | }, |
| 10789 | } | 10845 | } |
| ... | @@ -11017,7 +11073,7 @@ pub const Value = struct { | ... | @@ -11017,7 +11073,7 @@ pub const Value = struct { |
| 11017 | } } else .{ .undef = child_ty }, | 11073 | } } else .{ .undef = child_ty }, |
| 11018 | else => |child| { | 11074 | else => |child| { |
| 11019 | constant = child; | 11075 | constant = child; |
| 11020 | constant_key = ip.indexToKey(child); | 11076 | constant_key = ip.indexToKey(constant); |
| 11021 | continue :constant_key constant_key; | 11077 | continue :constant_key constant_key; |
| 11022 | }, | 11078 | }, |
| 11023 | }; | 11079 | }; |
| ... | @@ -11040,7 +11096,7 @@ pub const Value = struct { | ... | @@ -11040,7 +11096,7 @@ pub const Value = struct { |
| 11040 | }, | 11096 | }, |
| 11041 | .repeated_elem => |repeated_elem| { | 11097 | .repeated_elem => |repeated_elem| { |
| 11042 | constant = repeated_elem; | 11098 | constant = repeated_elem; |
| 11043 | constant_key = ip.indexToKey(repeated_elem); | 11099 | constant_key = ip.indexToKey(constant); |
| 11044 | continue :constant_key constant_key; | 11100 | continue :constant_key constant_key; |
| 11045 | }, | 11101 | }, |
| 11046 | }; | 11102 | }; |
| ... | @@ -11099,6 +11155,28 @@ pub const Value = struct { | ... | @@ -11099,6 +11155,28 @@ pub const Value = struct { |
| 11099 | } | 11155 | } |
| 11100 | }, | 11156 | }, |
| 11101 | }, | 11157 | }, |
| | 11158 | .un => |un| { |
| | 11159 | const loaded_union = ip.loadUnionType(un.ty); |
| | 11160 | const union_layout = ZigType.getUnionLayout(loaded_union, zcu); |
| | 11161 | if (loaded_union.hasTag(ip)) { |
| | 11162 | const tag_offset = union_layout.tagOffset(); |
| | 11163 | if (offset >= tag_offset and offset + size <= tag_offset + union_layout.tag_size) { |
| | 11164 | offset -= tag_offset; |
| | 11165 | continue :constant_key switch (ip.indexToKey(un.tag)) { |
| | 11166 | else => unreachable, |
| | 11167 | .int => |int| .{ .int = int }, |
| | 11168 | .enum_tag => |enum_tag| .{ .enum_tag = enum_tag }, |
| | 11169 | }; |
| | 11170 | } |
| | 11171 | } |
| | 11172 | const payload_offset = union_layout.payloadOffset(); |
| | 11173 | if (offset >= payload_offset and offset + size <= payload_offset + union_layout.payload_size) { |
| | 11174 | offset -= payload_offset; |
| | 11175 | constant = un.val; |
| | 11176 | constant_key = ip.indexToKey(constant); |
| | 11177 | continue :constant_key constant_key; |
| | 11178 | } |
| | 11179 | }, |
| 11102 | else => {}, | 11180 | else => {}, |
| 11103 | } | 11181 | } |
| 11104 | var buffer: [16]u8 = @splat(0); | 11182 | var buffer: [16]u8 = @splat(0); |
| ... | @@ -11259,7 +11337,7 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { | ... | @@ -11259,7 +11337,7 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { |
| 11259 | first = false; | 11337 | first = false; |
| 11260 | }; | 11338 | }; |
| 11261 | if (reverse_live_registers.get(vi)) |ra| { | 11339 | if (reverse_live_registers.get(vi)) |ra| { |
| 11262 | try stderr.print("{s}{s}", .{ if (first) " <- " else ", ", @tagName(ra) }); | 11340 | try stderr.print("{s}{t}", .{ if (first) " <- " else ", ", ra }); |
| 11263 | first = false; | 11341 | first = false; |
| 11264 | } | 11342 | } |
| 11265 | } | 11343 | } |
| ... | @@ -11267,8 +11345,8 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { | ... | @@ -11267,8 +11345,8 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { |
| 11267 | switch (value.flags.parent_tag) { | 11345 | switch (value.flags.parent_tag) { |
| 11268 | .unallocated => if (value.offset_from_parent != 0) try stderr.print(" +0x{x}", .{value.offset_from_parent}), | 11346 | .unallocated => if (value.offset_from_parent != 0) try stderr.print(" +0x{x}", .{value.offset_from_parent}), |
| 11269 | .stack_slot => { | 11347 | .stack_slot => { |
| 11270 | try stderr.print(" [{s}, #{s}0x{x}", .{ | 11348 | try stderr.print(" [{t}, #{s}0x{x}", .{ |
| 11271 | @tagName(value.parent_payload.stack_slot.base), | 11349 | value.parent_payload.stack_slot.base, |
| 11272 | if (value.parent_payload.stack_slot.offset < 0) "-" else "", | 11350 | if (value.parent_payload.stack_slot.offset < 0) "-" else "", |
| 11273 | @abs(value.parent_payload.stack_slot.offset), | 11351 | @abs(value.parent_payload.stack_slot.offset), |
| 11274 | }); | 11352 | }); |
| ... | @@ -11282,7 +11360,7 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { | ... | @@ -11282,7 +11360,7 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { |
| 11282 | isel.fmtConstant(value.parent_payload.constant), | 11360 | isel.fmtConstant(value.parent_payload.constant), |
| 11283 | }), | 11361 | }), |
| 11284 | } | 11362 | } |
| 11285 | try stderr.print(" align({s})", .{@tagName(value.flags.alignment)}); | 11363 | try stderr.print(" align({t})", .{value.flags.alignment}); |
| 11286 | switch (value.flags.location_tag) { | 11364 | switch (value.flags.location_tag) { |
| 11287 | .large => try stderr.print(" size=0x{x} large", .{value.location_payload.large.size}), | 11365 | .large => try stderr.print(" size=0x{x} large", .{value.location_payload.large.size}), |
| 11288 | .small => { | 11366 | .small => { |
| ... | @@ -11292,8 +11370,8 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { | ... | @@ -11292,8 +11370,8 @@ pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void { |
| 11292 | .unsigned => {}, | 11370 | .unsigned => {}, |
| 11293 | .signed => try stderr.writeAll(" signed"), | 11371 | .signed => try stderr.writeAll(" signed"), |
| 11294 | } | 11372 | } |
| 11295 | if (loc.hint != .zr) try stderr.print(" hint={s}", .{@tagName(loc.hint)}); | 11373 | if (loc.hint != .zr) try stderr.print(" hint={t}", .{loc.hint}); |
| 11296 | if (loc.register != .zr) try stderr.print(" loc={s}", .{@tagName(loc.register)}); | 11374 | if (loc.register != .zr) try stderr.print(" loc={t}", .{loc.register}); |
| 11297 | }, | 11375 | }, |
| 11298 | } | 11376 | } |
| 11299 | try stderr.print(" refs={d}\n", .{value.refs}); | 11377 | try stderr.print(" refs={d}\n", .{value.refs}); |