Skip to content

Commit 90d7dad

Browse files
committed
also compare ArgAttributes
1 parent b5c7530 commit 90d7dad

File tree

1 file changed

+38
-29
lines changed

1 file changed

+38
-29
lines changed

Diff for: compiler/rustc_const_eval/src/interpret/terminator.rs

+38-29
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::{
88
ty::{self, Ty},
99
};
1010
use rustc_target::abi;
11-
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
11+
use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode};
1212
use rustc_target::spec::abi::Abi;
1313

1414
use super::{
@@ -199,41 +199,50 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
199199
}
200200
};
201201
// Padding must be fully equal.
202-
let pad_compat = || {
203-
if caller_abi.pad != callee_abi.pad {
204-
trace!(
205-
"check_argument_compat: incompatible pad: {:?} != {:?}",
206-
caller_abi.pad,
207-
callee_abi.pad
208-
);
202+
let pad_compat = || caller_abi.pad == callee_abi.pad;
203+
// When comparing the PassMode, we have to be smart about comparing the attributes.
204+
let arg_attr_compat = |a1: ArgAttributes, a2: ArgAttributes| {
205+
// There's only one regular attribute that matters for the call ABI: InReg.
206+
// Everything else is things like noalias, dereferencable, nonnull, ...
207+
// (This also applies to pointee_size, pointee_align.)
208+
if a1.regular.contains(ArgAttribute::InReg) != a2.regular.contains(ArgAttribute::InReg)
209+
{
210+
return false;
211+
}
212+
// We also compare the sign extension mode -- this could let the callee make assumptions
213+
// about bits that conceptually were not even passed.
214+
if a1.arg_ext != a2.arg_ext {
209215
return false;
210216
}
211217
return true;
212218
};
213-
// For comparing the PassMode, we allow the attributes to differ
214-
// (e.g., it is okay for NonNull to differ between caller and callee).
215-
// FIXME: Are there attributes (`call::ArgAttributes`) that do need to be checked?
216-
let mode_compat = || {
217-
match (caller_abi.mode, callee_abi.mode) {
218-
(PassMode::Ignore, PassMode::Ignore) => return true,
219-
(PassMode::Direct(_), PassMode::Direct(_)) => return true,
220-
(PassMode::Pair(_, _), PassMode::Pair(_, _)) => return true,
221-
(PassMode::Cast(c1), PassMode::Cast(c2)) if c1 == c2 => return true,
222-
(
223-
PassMode::Indirect { attrs: _, extra_attrs: e1, on_stack: s1 },
224-
PassMode::Indirect { attrs: _, extra_attrs: e2, on_stack: s2 },
225-
) if e1.is_some() == e2.is_some() && s1 == s2 => return true,
226-
_ => {}
219+
let mode_compat = || match (caller_abi.mode, callee_abi.mode) {
220+
(PassMode::Ignore, PassMode::Ignore) => true,
221+
(PassMode::Direct(a1), PassMode::Direct(a2)) => arg_attr_compat(a1, a2),
222+
(PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => {
223+
arg_attr_compat(a1, a2) && arg_attr_compat(b1, b2)
227224
}
228-
trace!(
229-
"check_argument_compat: incompatible modes:\ncaller: {:?}\ncallee: {:?}",
230-
caller_abi.mode,
231-
callee_abi.mode
232-
);
233-
return false;
225+
(PassMode::Cast(c1), PassMode::Cast(c2)) => c1 == c2,
226+
(
227+
PassMode::Indirect { attrs: a1, extra_attrs: None, on_stack: s1 },
228+
PassMode::Indirect { attrs: a2, extra_attrs: None, on_stack: s2 },
229+
) => arg_attr_compat(a1, a2) && s1 == s2,
230+
(
231+
PassMode::Indirect { attrs: a1, extra_attrs: Some(e1), on_stack: s1 },
232+
PassMode::Indirect { attrs: a2, extra_attrs: Some(e2), on_stack: s2 },
233+
) => arg_attr_compat(a1, a2) && arg_attr_compat(e1, e2) && s1 == s2,
234+
_ => false,
234235
};
235236

236-
layout_compat() && pad_compat() && mode_compat()
237+
if layout_compat() && pad_compat() && mode_compat() {
238+
return true;
239+
}
240+
trace!(
241+
"check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
242+
caller_abi,
243+
callee_abi
244+
);
245+
return false;
237246
}
238247

239248
/// Initialize a single callee argument, checking the types for compatibility.

0 commit comments

Comments
 (0)