Skip to content

Commit b2af9a5

Browse files
committed
Auto merge of #138190 - cuviper:beta-next, r=cuviper
[beta] backports - Don't infer attributes of virtual calls based on the function body #137669 - Revert "store ScalarPair via memset when one side is undef and the other side can be memset" #137894 - Do not install rustup on Rust for Linux job #137947 r? cuviper
2 parents 61e1603 + 0bd0738 commit b2af9a5

File tree

13 files changed

+164
-164
lines changed

13 files changed

+164
-164
lines changed

compiler/rustc_codegen_gcc/src/common.rs

-5
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
6464
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
6565
}
6666

67-
fn is_undef(&self, _val: RValue<'gcc>) -> bool {
68-
// FIXME: actually check for undef
69-
false
70-
}
71-
7267
fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
7368
let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined");
7469
if typ.is_struct().is_some() {

compiler/rustc_codegen_llvm/src/common.rs

-4
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
126126
unsafe { llvm::LLVMGetUndef(t) }
127127
}
128128

129-
fn is_undef(&self, v: &'ll Value) -> bool {
130-
unsafe { llvm::LLVMIsUndef(v) == True }
131-
}
132-
133129
fn const_poison(&self, t: &'ll Type) -> &'ll Value {
134130
unsafe { llvm::LLVMGetPoison(t) }
135131
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,6 @@ unsafe extern "C" {
10351035
pub(crate) fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
10361036

10371037
// Operations on all values
1038-
pub(crate) fn LLVMIsUndef(Val: &Value) -> Bool;
10391038
pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type;
10401039
pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
10411040
pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);

compiler/rustc_codegen_ssa/src/mir/operand.rs

+22-37
Original file line numberDiff line numberDiff line change
@@ -204,30 +204,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
204204
let alloc_align = alloc.inner().align;
205205
assert!(alloc_align >= layout.align.abi);
206206

207-
// Returns `None` when the value is partially undefined or any byte of it has provenance.
208-
// Otherwise returns the value or (if the entire value is undef) returns an undef.
209207
let read_scalar = |start, size, s: abi::Scalar, ty| {
210-
let range = alloc_range(start, size);
211208
match alloc.0.read_scalar(
212209
bx,
213-
range,
210+
alloc_range(start, size),
214211
/*read_provenance*/ matches!(s.primitive(), abi::Primitive::Pointer(_)),
215212
) {
216-
Ok(val) => Some(bx.scalar_to_backend(val, s, ty)),
217-
Err(_) => {
218-
// We may have failed due to partial provenance or unexpected provenance,
219-
// continue down the normal code path if so.
220-
if alloc.0.provenance().range_empty(range, &bx.tcx())
221-
// Since `read_scalar` failed, but there were no relocations involved, the
222-
// bytes must be partially or fully uninitialized. Thus we can now unwrap the
223-
// information about the range of uninit bytes and check if it's the full range.
224-
&& alloc.0.init_mask().is_range_initialized(range).unwrap_err() == range
225-
{
226-
Some(bx.const_undef(ty))
227-
} else {
228-
None
229-
}
230-
}
213+
Ok(val) => bx.scalar_to_backend(val, s, ty),
214+
Err(_) => bx.const_poison(ty),
231215
}
232216
};
233217

@@ -238,14 +222,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
238222
// check that walks over the type of `mplace` to make sure it is truly correct to treat this
239223
// like a `Scalar` (or `ScalarPair`).
240224
match layout.backend_repr {
241-
BackendRepr::Scalar(s) => {
225+
BackendRepr::Scalar(s @ abi::Scalar::Initialized { .. }) => {
242226
let size = s.size(bx);
243227
assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
244-
if let Some(val) = read_scalar(offset, size, s, bx.immediate_backend_type(layout)) {
245-
return OperandRef { val: OperandValue::Immediate(val), layout };
246-
}
228+
let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout));
229+
OperandRef { val: OperandValue::Immediate(val), layout }
247230
}
248-
BackendRepr::ScalarPair(a, b) => {
231+
BackendRepr::ScalarPair(
232+
a @ abi::Scalar::Initialized { .. },
233+
b @ abi::Scalar::Initialized { .. },
234+
) => {
249235
let (a_size, b_size) = (a.size(bx), b.size(bx));
250236
let b_offset = (offset + a_size).align_to(b.align(bx).abi);
251237
assert!(b_offset.bytes() > 0);
@@ -261,21 +247,20 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
261247
b,
262248
bx.scalar_pair_element_backend_type(layout, 1, true),
263249
);
264-
if let (Some(a_val), Some(b_val)) = (a_val, b_val) {
265-
return OperandRef { val: OperandValue::Pair(a_val, b_val), layout };
266-
}
250+
OperandRef { val: OperandValue::Pair(a_val, b_val), layout }
251+
}
252+
_ if layout.is_zst() => OperandRef::zero_sized(layout),
253+
_ => {
254+
// Neither a scalar nor scalar pair. Load from a place
255+
// FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the
256+
// same `ConstAllocation`?
257+
let init = bx.const_data_from_alloc(alloc);
258+
let base_addr = bx.static_addr_of(init, alloc_align, None);
259+
260+
let llval = bx.const_ptr_byte_offset(base_addr, offset);
261+
bx.load_operand(PlaceRef::new_sized(llval, layout))
267262
}
268-
_ if layout.is_zst() => return OperandRef::zero_sized(layout),
269-
_ => {}
270263
}
271-
// Neither a scalar nor scalar pair. Load from a place
272-
// FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the
273-
// same `ConstAllocation`?
274-
let init = bx.const_data_from_alloc(alloc);
275-
let base_addr = bx.static_addr_of(init, alloc_align, None);
276-
277-
let llval = bx.const_ptr_byte_offset(base_addr, offset);
278-
bx.load_operand(PlaceRef::new_sized(llval, layout))
279264
}
280265

281266
/// Asserts that this operand refers to a scalar and returns

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+2-24
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
88
use rustc_middle::{bug, mir, span_bug};
99
use rustc_session::config::OptLevel;
1010
use rustc_span::{DUMMY_SP, Span};
11-
use tracing::{debug, instrument, trace};
11+
use tracing::{debug, instrument};
1212

1313
use super::operand::{OperandRef, OperandValue};
1414
use super::place::PlaceRef;
@@ -93,8 +93,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9393
return;
9494
}
9595

96-
// If `v` is an integer constant whose value is just a single byte repeated N times,
97-
// emit a `memset` filling the entire `dest` with that byte.
9896
let try_init_all_same = |bx: &mut Bx, v| {
9997
let start = dest.val.llval;
10098
let size = bx.const_usize(dest.layout.size.bytes());
@@ -119,33 +117,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
119117
false
120118
};
121119

122-
trace!(?cg_elem.val);
123120
match cg_elem.val {
124121
OperandValue::Immediate(v) => {
125122
if try_init_all_same(bx, v) {
126123
return;
127124
}
128125
}
129-
OperandValue::Pair(a, b) => {
130-
let a_is_undef = bx.cx().is_undef(a);
131-
match (a_is_undef, bx.cx().is_undef(b)) {
132-
// Can happen for uninit unions
133-
(true, true) => {
134-
// FIXME: can we produce better output here?
135-
}
136-
(false, true) | (true, false) => {
137-
let val = if a_is_undef { b } else { a };
138-
if try_init_all_same(bx, val) {
139-
return;
140-
}
141-
}
142-
(false, false) => {
143-
// FIXME: if both are the same value, use try_init_all_same
144-
}
145-
}
146-
}
147-
OperandValue::ZeroSized => unreachable!("checked above"),
148-
OperandValue::Ref(..) => {}
126+
_ => (),
149127
}
150128

151129
let count = self

compiler/rustc_codegen_ssa/src/traits/consts.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ pub trait ConstCodegenMethods<'tcx>: BackendTypes {
99
/// Generate an uninitialized value (matching uninitialized memory in MIR).
1010
/// Whether memory is initialized or not is tracked byte-for-byte.
1111
fn const_undef(&self, t: Self::Type) -> Self::Value;
12-
fn is_undef(&self, v: Self::Value) -> bool;
1312
/// Generate a fake value. Poison always affects the entire value, even if just a single byte is
1413
/// poison. This can only be used in codepaths that are already UB, i.e., UB-free Rust code
1514
/// (including code that e.g. copies uninit memory with `MaybeUninit`) can never encounter a

compiler/rustc_middle/src/mir/interpret/allocation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl AllocError {
222222
}
223223

224224
/// The information that makes up a memory access: offset and size.
225-
#[derive(Copy, Clone, PartialEq)]
225+
#[derive(Copy, Clone)]
226226
pub struct AllocRange {
227227
pub start: Size,
228228
pub size: Size,

compiler/rustc_middle/src/ty/instance.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@ pub enum InstanceKind<'tcx> {
111111

112112
/// Dynamic dispatch to `<dyn Trait as Trait>::fn`.
113113
///
114-
/// This `InstanceKind` does not have callable MIR. Calls to `Virtual` instances must be
115-
/// codegen'd as virtual calls through the vtable.
114+
/// This `InstanceKind` may have a callable MIR as the default implementation.
115+
/// Calls to `Virtual` instances must be codegen'd as virtual calls through the vtable.
116+
/// *This means we might not know exactly what is being called.*
116117
///
117118
/// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more
118119
/// details on that).

compiler/rustc_ty_utils/src/abi.rs

+38-36
Original file line numberDiff line numberDiff line change
@@ -309,15 +309,11 @@ fn fn_abi_of_fn_ptr<'tcx>(
309309
query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
310310
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
311311
let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query;
312-
313-
let cx = LayoutCx::new(tcx, typing_env);
314312
fn_abi_new_uncached(
315-
&cx,
313+
&LayoutCx::new(tcx, typing_env),
316314
tcx.instantiate_bound_regions_with_erased(sig),
317315
extra_args,
318316
None,
319-
None,
320-
false,
321317
)
322318
}
323319

@@ -326,19 +322,11 @@ fn fn_abi_of_instance<'tcx>(
326322
query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
327323
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
328324
let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query;
329-
330-
let sig = fn_sig_for_fn_abi(tcx, instance, typing_env);
331-
332-
let caller_location =
333-
instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty());
334-
335325
fn_abi_new_uncached(
336326
&LayoutCx::new(tcx, typing_env),
337-
sig,
327+
fn_sig_for_fn_abi(tcx, instance, typing_env),
338328
extra_args,
339-
caller_location,
340-
Some(instance.def_id()),
341-
matches!(instance.def, ty::InstanceKind::Virtual(..)),
329+
Some(instance),
342330
)
343331
}
344332

@@ -549,19 +537,25 @@ fn fn_abi_sanity_check<'tcx>(
549537
fn_arg_sanity_check(cx, fn_abi, spec_abi, &fn_abi.ret);
550538
}
551539

552-
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
553-
// arguments of this method, into a separate `struct`.
554-
#[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))]
540+
#[tracing::instrument(level = "debug", skip(cx, instance))]
555541
fn fn_abi_new_uncached<'tcx>(
556542
cx: &LayoutCx<'tcx>,
557543
sig: ty::FnSig<'tcx>,
558544
extra_args: &[Ty<'tcx>],
559-
caller_location: Option<Ty<'tcx>>,
560-
fn_def_id: Option<DefId>,
561-
// FIXME(eddyb) replace this with something typed, like an `enum`.
562-
force_thin_self_ptr: bool,
545+
instance: Option<ty::Instance<'tcx>>,
563546
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
564547
let tcx = cx.tcx();
548+
let (caller_location, determined_fn_def_id, is_virtual_call) = if let Some(instance) = instance
549+
{
550+
let is_virtual_call = matches!(instance.def, ty::InstanceKind::Virtual(..));
551+
(
552+
instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()),
553+
if is_virtual_call { None } else { Some(instance.def_id()) },
554+
is_virtual_call,
555+
)
556+
} else {
557+
(None, None, false)
558+
};
565559
let sig = tcx.normalize_erasing_regions(cx.typing_env, sig);
566560

567561
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
@@ -570,16 +564,11 @@ fn fn_abi_new_uncached<'tcx>(
570564
let extra_args = if sig.abi == ExternAbi::RustCall {
571565
assert!(!sig.c_variadic && extra_args.is_empty());
572566

573-
if let Some(input) = sig.inputs().last() {
574-
if let ty::Tuple(tupled_arguments) = input.kind() {
575-
inputs = &sig.inputs()[0..sig.inputs().len() - 1];
576-
tupled_arguments
577-
} else {
578-
bug!(
579-
"argument to function with \"rust-call\" ABI \
580-
is not a tuple"
581-
);
582-
}
567+
if let Some(input) = sig.inputs().last()
568+
&& let ty::Tuple(tupled_arguments) = input.kind()
569+
{
570+
inputs = &sig.inputs()[0..sig.inputs().len() - 1];
571+
tupled_arguments
583572
} else {
584573
bug!(
585574
"argument to function with \"rust-call\" ABI \
@@ -592,7 +581,7 @@ fn fn_abi_new_uncached<'tcx>(
592581
};
593582

594583
let is_drop_in_place =
595-
fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace));
584+
determined_fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace));
596585

597586
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
598587
let span = tracing::debug_span!("arg_of");
@@ -605,7 +594,7 @@ fn fn_abi_new_uncached<'tcx>(
605594
});
606595

607596
let layout = cx.layout_of(ty).map_err(|err| &*tcx.arena.alloc(FnAbiError::Layout(*err)))?;
608-
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
597+
let layout = if is_virtual_call && arg_idx == Some(0) {
609598
// Don't pass the vtable, it's not an argument of the virtual fn.
610599
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
611600
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
@@ -648,9 +637,22 @@ fn fn_abi_new_uncached<'tcx>(
648637
c_variadic: sig.c_variadic,
649638
fixed_count: inputs.len() as u32,
650639
conv,
651-
can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi),
640+
can_unwind: fn_can_unwind(
641+
tcx,
642+
// Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
643+
determined_fn_def_id,
644+
sig.abi,
645+
),
652646
};
653-
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id);
647+
fn_abi_adjust_for_abi(
648+
cx,
649+
&mut fn_abi,
650+
sig.abi,
651+
// If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
652+
// functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by
653+
// visit the function body.
654+
determined_fn_def_id,
655+
);
654656
debug!("fn_abi_new_uncached = {:?}", fn_abi);
655657
fn_abi_sanity_check(cx, &fn_abi, sig.abi);
656658
Ok(tcx.arena.alloc(fn_abi))

src/ci/docker/scripts/rfl-build.sh

+8-10
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,10 @@ LINUX_VERSION=50e57739141b41f731ab31f8380821c7969f9dc4
88
../x.py build --stage 2 library rustdoc clippy rustfmt
99
../x.py build --stage 0 cargo
1010

11-
# Install rustup so that we can use the built toolchain easily, and also
12-
# install bindgen in an easy way.
13-
curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
14-
sh rustup.sh -y --default-toolchain none
11+
BUILD_DIR=$(realpath ./build/x86_64-unknown-linux-gnu)
1512

16-
source /cargo/env
17-
18-
BUILD_DIR=$(realpath ./build)
19-
rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2
20-
rustup default local
13+
# Provide path to rustc, rustdoc, clippy-driver and rustfmt to RfL
14+
export PATH=${PATH}:${BUILD_DIR}/stage2/bin
2115

2216
mkdir -p rfl
2317
cd rfl
@@ -33,10 +27,14 @@ git -C linux fetch --depth 1 origin ${LINUX_VERSION}
3327
git -C linux checkout FETCH_HEAD
3428

3529
# Install bindgen
36-
"${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage0/bin/cargo install \
30+
"${BUILD_DIR}"/stage0/bin/cargo install \
3731
--version $(linux/scripts/min-tool-version.sh bindgen) \
32+
--root ${BUILD_DIR}/bindgen \
3833
bindgen-cli
3934

35+
# Provide path to bindgen to RfL
36+
export PATH=${PATH}:${BUILD_DIR}/bindgen/bin
37+
4038
# Configure Rust for Linux
4139
cat <<EOF > linux/kernel/configs/rfl-for-rust-ci.config
4240
# CONFIG_WERROR is not set

0 commit comments

Comments
 (0)