Auto merge of #135525 - jhpratt:rollup-4gu2wpm, r=jhpratt
Rollup of 7 pull requests Successful merges: - #132397 (Make missing_abi lint warn-by-default.) - #133807 (ci: Enable opt-dist for dist-aarch64-linux builds) - #134143 (Convert `struct FromBytesWithNulError` into enum) - #134338 (Use a C-safe return type for `__rust_[ui]128_*` overflowing intrinsics) - #134678 (Update `ReadDir::next` in `std::sys::pal::unix::fs` to use `&raw const (*p).field` instead of `p.byte_offset().cast()`) - #135424 (Detect unstable lint docs that dont enable their feature) - #135520 (Make sure we actually use the right trivial lifetime substs when eagerly monomorphizing drop for ADTs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2776bdfe42
81 changed files with 429 additions and 315 deletions
|
@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644
|
|||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
-compiler_builtins = { version = "=0.1.141", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.141", features = ['rustc-dep-of-std', 'no-f16-f128'] }
|
||||
-compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std', 'no-f16-f128'] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
|
||||
|
|
|
@ -76,20 +76,22 @@ pub(crate) fn maybe_codegen_mul_checked<'tcx>(
|
|||
}
|
||||
|
||||
let is_signed = type_sign(lhs.layout().ty);
|
||||
|
||||
let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
|
||||
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
|
||||
let oflow_out_place = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
|
||||
let param_types = vec![
|
||||
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
|
||||
AbiParam::new(types::I128),
|
||||
AbiParam::new(types::I128),
|
||||
AbiParam::special(fx.pointer_type, ArgumentPurpose::Normal),
|
||||
];
|
||||
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
|
||||
fx.lib_call(
|
||||
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx), oflow_out_place.to_ptr().get_addr(fx)];
|
||||
let ret = fx.lib_call(
|
||||
if is_signed { "__rust_i128_mulo" } else { "__rust_u128_mulo" },
|
||||
param_types,
|
||||
vec![],
|
||||
vec![AbiParam::new(types::I128)],
|
||||
&args,
|
||||
);
|
||||
Some(out_place.to_cvalue(fx))
|
||||
let mul = ret[0];
|
||||
let oflow = oflow_out_place.to_cvalue(fx).load_scalar(fx);
|
||||
let oflow = clif_intcast(fx, oflow, types::I8, false);
|
||||
let layout = fx.layout_of(Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]));
|
||||
Some(CValue::by_val_pair(mul, oflow, layout))
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ builtin_functions! {
|
|||
fn __divti3(n: i128, d: i128) -> i128;
|
||||
fn __umodti3(n: u128, d: u128) -> u128;
|
||||
fn __modti3(n: i128, d: i128) -> i128;
|
||||
fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool);
|
||||
fn __rust_u128_mulo(a: u128, b: u128, oflow: &mut i32) -> u128;
|
||||
|
||||
// floats
|
||||
fn __floattisf(i: i128) -> f32;
|
||||
|
|
|
@ -689,7 +689,7 @@ impl<T> Index<usize> for [T] {
|
|||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type VaListImpl;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,13 +258,13 @@ fn main() {
|
|||
|
||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
||||
{
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#![allow(internal_features)]
|
||||
|
||||
#[link(name = "c")]
|
||||
extern {}
|
||||
extern "C" {}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::arch::x86_64::*;
|
|||
use std::io::Write;
|
||||
use std::ops::Coroutine;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
|
||||
|
|
|
@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
},
|
||||
}
|
||||
} else {
|
||||
match new_kind {
|
||||
Int(I128) | Uint(U128) => {
|
||||
let func_name = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => "__rust_i128_addo",
|
||||
Uint(U128) => "__rust_u128_addo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => "__rust_i128_subo",
|
||||
Uint(U128) => "__rust_u128_subo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => "__rust_u128_mulo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs);
|
||||
}
|
||||
_ => match oop {
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => "__mulosi4",
|
||||
Int(I64) => "__mulodi4",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unimplemented!("overflow operation for {:?}", new_kind),
|
||||
let (func_name, width) = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => ("__rust_i128_addo", 128),
|
||||
Uint(U128) => ("__rust_u128_addo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => ("__rust_i128_subo", 128),
|
||||
Uint(U128) => ("__rust_u128_subo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => ("__mulosi4", 32),
|
||||
Int(I64) => ("__mulodi4", 64),
|
||||
Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => ("__rust_u128_mulo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
};
|
||||
|
||||
let intrinsic = self.context.get_builtin_function(name);
|
||||
|
@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
(res.dereference(self.location).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
/// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
|
||||
pub fn operation_with_overflow(
|
||||
&self,
|
||||
func_name: &str,
|
||||
lhs: RValue<'gcc>,
|
||||
rhs: RValue<'gcc>,
|
||||
width: u64,
|
||||
) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
debug_assert!(a_type.dyncast_array().is_some());
|
||||
debug_assert!(b_type.dyncast_array().is_some());
|
||||
let overflow_type = self.i32_type;
|
||||
let overflow_param_type = overflow_type.make_pointer();
|
||||
let res_type = a_type;
|
||||
|
||||
let overflow_value =
|
||||
self.current_func().new_local(self.location, overflow_type, "overflow");
|
||||
let overflow_addr = overflow_value.get_address(self.location);
|
||||
|
||||
let param_a = self.context.new_parameter(self.location, a_type, "a");
|
||||
let param_b = self.context.new_parameter(self.location, b_type, "b");
|
||||
let result_field = self.context.new_field(self.location, a_type, "result");
|
||||
let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
|
||||
let param_overflow =
|
||||
self.context.new_parameter(self.location, overflow_param_type, "overflow");
|
||||
|
||||
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
|
||||
let a_elem_type = a_type.dyncast_array().expect("non-array a value");
|
||||
debug_assert!(a_elem_type.is_integral());
|
||||
let res_ty = match width {
|
||||
32 => self.tcx.types.i32,
|
||||
64 => self.tcx.types.i64,
|
||||
128 => self.tcx.types.i128,
|
||||
_ => unreachable!("unexpected integer size"),
|
||||
};
|
||||
let layout = self
|
||||
.tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
|
||||
.unwrap();
|
||||
|
||||
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
|
||||
let mut fn_abi = FnAbi {
|
||||
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
ret: arg_abi,
|
||||
c_variadic: false,
|
||||
fixed_count: 2,
|
||||
fixed_count: 3,
|
||||
conv: Conv::C,
|
||||
can_unwind: false,
|
||||
};
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap();
|
||||
|
||||
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let result = if ret_indirect {
|
||||
let res_value = self.current_func().new_local(self.location, res_type, "result_value");
|
||||
let res_addr = res_value.get_address(self.location);
|
||||
let res_param_type = res_type.make_pointer();
|
||||
let param_res = self.context.new_parameter(self.location, res_param_type, "result");
|
||||
|
||||
let return_type = self
|
||||
.context
|
||||
.new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]);
|
||||
let result = if indirect {
|
||||
let return_value =
|
||||
self.current_func().new_local(self.location, return_type.as_type(), "return_value");
|
||||
let return_param_type = return_type.as_type().make_pointer();
|
||||
let return_param =
|
||||
self.context.new_parameter(self.location, return_param_type, "return_value");
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
self.type_void(),
|
||||
&[return_param, param_a, param_b],
|
||||
&[param_res, param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.llbb().add_eval(
|
||||
self.location,
|
||||
self.context.new_call(self.location, func, &[
|
||||
return_value.get_address(self.location),
|
||||
lhs,
|
||||
rhs,
|
||||
]),
|
||||
);
|
||||
return_value.to_rvalue()
|
||||
let _void =
|
||||
self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]);
|
||||
res_value.to_rvalue()
|
||||
} else {
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
return_type.as_type(),
|
||||
&[param_a, param_b],
|
||||
res_type,
|
||||
&[param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.context.new_call(self.location, func, &[lhs, rhs])
|
||||
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
|
||||
};
|
||||
let overflow = result.access_field(self.location, overflow_field);
|
||||
let int_result = result.access_field(self.location, result_field);
|
||||
(int_result, overflow)
|
||||
|
||||
(result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue())
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(
|
||||
|
|
|
@ -1001,7 +1001,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_addo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
@ -1071,7 +1072,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_subo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
|
|
@ -3597,7 +3597,7 @@ declare_lint! {
|
|||
///
|
||||
/// [Other ABIs]: https://doc.rust-lang.org/reference/items/external-blocks.html#abi
|
||||
pub MISSING_ABI,
|
||||
Allow,
|
||||
Warn,
|
||||
"No declared ABI for extern declaration"
|
||||
}
|
||||
|
||||
|
|
|
@ -1410,19 +1410,33 @@ impl<'v> RootCollector<'_, 'v> {
|
|||
&& !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx)
|
||||
{
|
||||
debug!("RootCollector: ADT drop-glue for `{id:?}`",);
|
||||
let id_args =
|
||||
ty::GenericArgs::for_item(self.tcx, id.owner_id.to_def_id(), |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
self.tcx.lifetimes.re_erased.into()
|
||||
}
|
||||
GenericParamDefKind::Type { .. }
|
||||
| GenericParamDefKind::Const { .. } => {
|
||||
unreachable!(
|
||||
"`own_requires_monomorphization` check means that \
|
||||
we should have no type/const params"
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This type is impossible to instantiate, so we should not try to
|
||||
// generate a `drop_in_place` instance for it.
|
||||
if self.tcx.instantiate_and_check_impossible_predicates((
|
||||
id.owner_id.to_def_id(),
|
||||
ty::List::empty(),
|
||||
id_args,
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty = self.tcx.erase_regions(
|
||||
self.tcx.type_of(id.owner_id.to_def_id()).instantiate_identity(),
|
||||
);
|
||||
let ty =
|
||||
self.tcx.type_of(id.owner_id.to_def_id()).instantiate(self.tcx, id_args);
|
||||
assert!(!ty.has_non_region_param());
|
||||
visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
|
||||
}
|
||||
|
|
|
@ -804,7 +804,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> {
|
|||
#[inline(never)]
|
||||
fn region_param_out_of_range(&self, ebr: I::EarlyParamRegion, r: I::Region) -> ! {
|
||||
panic!(
|
||||
"const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
|
||||
"region parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
|
||||
ebr,
|
||||
r,
|
||||
ebr.index(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue