Skip to content

Commit c559c4a

Browse files
committed
Auto merge of #146224 - tgross35:rollup-1bgjms3, r=tgross35
Rollup of 5 pull requests Successful merges: - #144342 (add exact bitshifts) - #145709 (Fix LoongArch C function ABI when passing/returning structs containing floats) - #146152 (Unify and deduplicate algebraic float tests) - #146207 (std: Implement WASIp2-specific stdio routines) - #146217 (fix ICE when suggesting `::new`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents ad85bc5 + 8ff60a6 commit c559c4a

File tree

21 files changed

+798
-136
lines changed

21 files changed

+798
-136
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,12 +2585,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25852585
.filter(|item| item.is_fn() && !item.is_method())
25862586
.filter_map(|item| {
25872587
// Only assoc fns that return `Self`
2588-
let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
2589-
let ret_ty = fn_sig.output();
2590-
let ret_ty = self.tcx.normalize_erasing_late_bound_regions(
2591-
self.typing_env(self.param_env),
2592-
ret_ty,
2593-
);
2588+
let fn_sig = self
2589+
.tcx
2590+
.fn_sig(item.def_id)
2591+
.instantiate(self.tcx, self.fresh_args_for_item(span, item.def_id));
2592+
let ret_ty = self.tcx.instantiate_bound_regions_with_erased(fn_sig.output());
25942593
if !self.can_eq(self.param_env, ret_ty, adt_ty) {
25952594
return None;
25962595
}

compiler/rustc_target/src/callconv/loongarch.rs

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ use crate::spec::HasTargetSpec;
88

99
#[derive(Copy, Clone)]
1010
enum RegPassKind {
11-
Float(Reg),
12-
Integer(Reg),
11+
Float { offset_from_start: Size, ty: Reg },
12+
Integer { offset_from_start: Size, ty: Reg },
1313
Unknown,
1414
}
1515

1616
#[derive(Copy, Clone)]
1717
enum FloatConv {
18-
FloatPair(Reg, Reg),
18+
FloatPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg },
1919
Float(Reg),
20-
MixedPair(Reg, Reg),
20+
MixedPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg },
2121
}
2222

2323
#[derive(Copy, Clone)]
@@ -37,6 +37,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
3737
flen: u64,
3838
field1_kind: &mut RegPassKind,
3939
field2_kind: &mut RegPassKind,
40+
offset_from_start: Size,
4041
) -> Result<(), CannotUseFpConv>
4142
where
4243
Ty: TyAbiInterface<'a, C> + Copy,
@@ -49,16 +50,16 @@ where
4950
}
5051
match (*field1_kind, *field2_kind) {
5152
(RegPassKind::Unknown, _) => {
52-
*field1_kind = RegPassKind::Integer(Reg {
53-
kind: RegKind::Integer,
54-
size: arg_layout.size,
55-
});
53+
*field1_kind = RegPassKind::Integer {
54+
offset_from_start,
55+
ty: Reg { kind: RegKind::Integer, size: arg_layout.size },
56+
};
5657
}
57-
(RegPassKind::Float(_), RegPassKind::Unknown) => {
58-
*field2_kind = RegPassKind::Integer(Reg {
59-
kind: RegKind::Integer,
60-
size: arg_layout.size,
61-
});
58+
(RegPassKind::Float { .. }, RegPassKind::Unknown) => {
59+
*field2_kind = RegPassKind::Integer {
60+
offset_from_start,
61+
ty: Reg { kind: RegKind::Integer, size: arg_layout.size },
62+
};
6263
}
6364
_ => return Err(CannotUseFpConv),
6465
}
@@ -69,12 +70,16 @@ where
6970
}
7071
match (*field1_kind, *field2_kind) {
7172
(RegPassKind::Unknown, _) => {
72-
*field1_kind =
73-
RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size });
73+
*field1_kind = RegPassKind::Float {
74+
offset_from_start,
75+
ty: Reg { kind: RegKind::Float, size: arg_layout.size },
76+
};
7477
}
7578
(_, RegPassKind::Unknown) => {
76-
*field2_kind =
77-
RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size });
79+
*field2_kind = RegPassKind::Float {
80+
offset_from_start,
81+
ty: Reg { kind: RegKind::Float, size: arg_layout.size },
82+
};
7883
}
7984
_ => return Err(CannotUseFpConv),
8085
}
@@ -96,13 +101,14 @@ where
96101
flen,
97102
field1_kind,
98103
field2_kind,
104+
offset_from_start,
99105
);
100106
}
101107
return Err(CannotUseFpConv);
102108
}
103109
}
104110
FieldsShape::Array { count, .. } => {
105-
for _ in 0..count {
111+
for i in 0..count {
106112
let elem_layout = arg_layout.field(cx, 0);
107113
should_use_fp_conv_helper(
108114
cx,
@@ -111,6 +117,7 @@ where
111117
flen,
112118
field1_kind,
113119
field2_kind,
120+
offset_from_start + elem_layout.size * i,
114121
)?;
115122
}
116123
}
@@ -121,7 +128,15 @@ where
121128
}
122129
for i in arg_layout.fields.index_by_increasing_offset() {
123130
let field = arg_layout.field(cx, i);
124-
should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?;
131+
should_use_fp_conv_helper(
132+
cx,
133+
&field,
134+
xlen,
135+
flen,
136+
field1_kind,
137+
field2_kind,
138+
offset_from_start + arg_layout.fields.offset(i),
139+
)?;
125140
}
126141
}
127142
},
@@ -140,14 +155,52 @@ where
140155
{
141156
let mut field1_kind = RegPassKind::Unknown;
142157
let mut field2_kind = RegPassKind::Unknown;
143-
if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() {
158+
if should_use_fp_conv_helper(
159+
cx,
160+
arg,
161+
xlen,
162+
flen,
163+
&mut field1_kind,
164+
&mut field2_kind,
165+
Size::ZERO,
166+
)
167+
.is_err()
168+
{
144169
return None;
145170
}
146171
match (field1_kind, field2_kind) {
147-
(RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)),
148-
(RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)),
149-
(RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)),
150-
(RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)),
172+
(
173+
RegPassKind::Integer { offset_from_start, .. }
174+
| RegPassKind::Float { offset_from_start, .. },
175+
_,
176+
) if offset_from_start != Size::ZERO => {
177+
panic!("type {:?} has a first field with non-zero offset {offset_from_start:?}", arg.ty)
178+
}
179+
(
180+
RegPassKind::Integer { ty: first_ty, .. },
181+
RegPassKind::Float { offset_from_start, ty: second_ty },
182+
) => Some(FloatConv::MixedPair {
183+
first_ty,
184+
second_ty_offset_from_start: offset_from_start,
185+
second_ty,
186+
}),
187+
(
188+
RegPassKind::Float { ty: first_ty, .. },
189+
RegPassKind::Integer { offset_from_start, ty: second_ty },
190+
) => Some(FloatConv::MixedPair {
191+
first_ty,
192+
second_ty_offset_from_start: offset_from_start,
193+
second_ty,
194+
}),
195+
(
196+
RegPassKind::Float { ty: first_ty, .. },
197+
RegPassKind::Float { offset_from_start, ty: second_ty },
198+
) => Some(FloatConv::FloatPair {
199+
first_ty,
200+
second_ty_offset_from_start: offset_from_start,
201+
second_ty,
202+
}),
203+
(RegPassKind::Float { ty, .. }, RegPassKind::Unknown) => Some(FloatConv::Float(ty)),
151204
_ => None,
152205
}
153206
}
@@ -165,11 +218,19 @@ where
165218
FloatConv::Float(f) => {
166219
arg.cast_to(f);
167220
}
168-
FloatConv::FloatPair(l, r) => {
169-
arg.cast_to(CastTarget::pair(l, r));
221+
FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty } => {
222+
arg.cast_to(CastTarget::offset_pair(
223+
first_ty,
224+
second_ty_offset_from_start,
225+
second_ty,
226+
));
170227
}
171-
FloatConv::MixedPair(l, r) => {
172-
arg.cast_to(CastTarget::pair(l, r));
228+
FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty } => {
229+
arg.cast_to(CastTarget::offset_pair(
230+
first_ty,
231+
second_ty_offset_from_start,
232+
second_ty,
233+
));
173234
}
174235
}
175236
return false;
@@ -233,15 +294,27 @@ fn classify_arg<'a, Ty, C>(
233294
arg.cast_to(f);
234295
return;
235296
}
236-
Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => {
297+
Some(FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty })
298+
if *avail_fprs >= 2 =>
299+
{
237300
*avail_fprs -= 2;
238-
arg.cast_to(CastTarget::pair(l, r));
301+
arg.cast_to(CastTarget::offset_pair(
302+
first_ty,
303+
second_ty_offset_from_start,
304+
second_ty,
305+
));
239306
return;
240307
}
241-
Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => {
308+
Some(FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty })
309+
if *avail_fprs >= 1 && *avail_gprs >= 1 =>
310+
{
242311
*avail_gprs -= 1;
243312
*avail_fprs -= 1;
244-
arg.cast_to(CastTarget::pair(l, r));
313+
arg.cast_to(CastTarget::offset_pair(
314+
first_ty,
315+
second_ty_offset_from_start,
316+
second_ty,
317+
));
245318
return;
246319
}
247320
_ => (),

library/core/src/num/int_macros.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,66 @@ macro_rules! int_impl {
14131413
}
14141414
}
14151415

1416+
/// Exact shift left. Computes `self << rhs` as long as it can be reversed losslessly.
1417+
///
1418+
/// Returns `None` if any bits that would be shifted out differ from the resulting sign bit
1419+
/// or if `rhs` >=
1420+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1421+
/// Otherwise, returns `Some(self << rhs)`.
1422+
///
1423+
/// # Examples
1424+
///
1425+
/// ```
1426+
/// #![feature(exact_bitshifts)]
1427+
///
1428+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(4), Some(0x10));")]
1429+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 2), Some(1 << ", stringify!($SelfT), "::BITS - 2));")]
1430+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
1431+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 2), Some(-0x2 << ", stringify!($SelfT), "::BITS - 2));")]
1432+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
1433+
/// ```
1434+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1435+
#[must_use = "this returns the result of the operation, \
1436+
without modifying the original"]
1437+
#[inline]
1438+
pub const fn exact_shl(self, rhs: u32) -> Option<$SelfT> {
1439+
if rhs < self.leading_zeros() || rhs < self.leading_ones() {
1440+
// SAFETY: rhs is checked above
1441+
Some(unsafe { self.unchecked_shl(rhs) })
1442+
} else {
1443+
None
1444+
}
1445+
}
1446+
1447+
/// Unchecked exact shift left. Computes `self << rhs`, assuming the operation can be
1448+
/// losslessly reversed and `rhs` cannot be larger than
1449+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1450+
///
1451+
/// # Safety
1452+
///
1453+
/// This results in undefined behavior when `rhs >= self.leading_zeros() && rhs >=
1454+
/// self.leading_ones()` i.e. when
1455+
#[doc = concat!("[`", stringify!($SelfT), "::exact_shl`]")]
1456+
/// would return `None`.
1457+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1458+
#[must_use = "this returns the result of the operation, \
1459+
without modifying the original"]
1460+
#[inline]
1461+
pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT {
1462+
assert_unsafe_precondition!(
1463+
check_language_ub,
1464+
concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out non-zero bits"),
1465+
(
1466+
zeros: u32 = self.leading_zeros(),
1467+
ones: u32 = self.leading_ones(),
1468+
rhs: u32 = rhs,
1469+
) => rhs < zeros || rhs < ones,
1470+
);
1471+
1472+
// SAFETY: this is guaranteed to be safe by the caller
1473+
unsafe { self.unchecked_shl(rhs) }
1474+
}
1475+
14161476
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
14171477
/// larger than or equal to the number of bits in `self`.
14181478
///
@@ -1534,6 +1594,63 @@ macro_rules! int_impl {
15341594
}
15351595
}
15361596

1597+
/// Exact shift right. Computes `self >> rhs` as long as it can be reversed losslessly.
1598+
///
1599+
/// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
1600+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1601+
/// Otherwise, returns `Some(self >> rhs)`.
1602+
///
1603+
/// # Examples
1604+
///
1605+
/// ```
1606+
/// #![feature(exact_bitshifts)]
1607+
///
1608+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(4), Some(0x1));")]
1609+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(5), None);")]
1610+
/// ```
1611+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1612+
#[must_use = "this returns the result of the operation, \
1613+
without modifying the original"]
1614+
#[inline]
1615+
pub const fn exact_shr(self, rhs: u32) -> Option<$SelfT> {
1616+
if rhs <= self.trailing_zeros() && rhs < <$SelfT>::BITS {
1617+
// SAFETY: rhs is checked above
1618+
Some(unsafe { self.unchecked_shr(rhs) })
1619+
} else {
1620+
None
1621+
}
1622+
}
1623+
1624+
/// Unchecked exact shift right. Computes `self >> rhs`, assuming the operation can be
1625+
/// losslessly reversed and `rhs` cannot be larger than
1626+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1627+
///
1628+
/// # Safety
1629+
///
1630+
/// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
1631+
#[doc = concat!(stringify!($SelfT), "::BITS`")]
1632+
/// i.e. when
1633+
#[doc = concat!("[`", stringify!($SelfT), "::exact_shr`]")]
1634+
/// would return `None`.
1635+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1636+
#[must_use = "this returns the result of the operation, \
1637+
without modifying the original"]
1638+
#[inline]
1639+
pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT {
1640+
assert_unsafe_precondition!(
1641+
check_language_ub,
1642+
concat!(stringify!($SelfT), "::unchecked_exact_shr cannot shift out non-zero bits"),
1643+
(
1644+
zeros: u32 = self.trailing_zeros(),
1645+
bits: u32 = <$SelfT>::BITS,
1646+
rhs: u32 = rhs,
1647+
) => rhs <= zeros && rhs < bits,
1648+
);
1649+
1650+
// SAFETY: this is guaranteed to be safe by the caller
1651+
unsafe { self.unchecked_shr(rhs) }
1652+
}
1653+
15371654
/// Checked absolute value. Computes `self.abs()`, returning `None` if
15381655
/// `self == MIN`.
15391656
///

0 commit comments

Comments
 (0)