1use rustc_middle::bug;
2use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt};
3use rustc_session::config::Lto;
4use rustc_symbol_mangling::typeid_for_trait_ref;
5use rustc_target::callconv::FnAbi;
6use tracing::{debug, instrument};
7
8use crate::traits::*;
9
10#[derive(#[automatically_derived]
impl ::core::marker::Copy for VirtualIndex { }Copy, #[automatically_derived]
impl ::core::clone::Clone for VirtualIndex {
#[inline]
fn clone(&self) -> VirtualIndex {
let _: ::core::clone::AssertParamIsClone<u64>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for VirtualIndex {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "VirtualIndex",
&&self.0)
}
}Debug)]
11pub(crate) struct VirtualIndex(u64);
12
13impl<'a, 'tcx> VirtualIndex {
14 pub(crate) fn from_index(index: usize) -> Self {
15 VirtualIndex(index as u64)
16 }
17
18 fn get_fn_inner<Bx: BuilderMethods<'a, 'tcx>>(
19 self,
20 bx: &mut Bx,
21 llvtable: Bx::Value,
22 ty: Ty<'tcx>,
23 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
24 nonnull: bool,
25 ) -> Bx::Value {
26 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/meth.rs:27",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(27u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::meth"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("get_fn({0:?}, {1:?}, {2:?})",
llvtable, ty, self) as &dyn Value))])
});
} else { ; }
};debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
28
29 let llty = bx.fn_ptr_backend_type(fn_abi);
30 let ptr_size = bx.data_layout().pointer_size();
31 let vtable_byte_offset = self.0 * ptr_size.bytes();
32
33 load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
34 }
35
36 pub(crate) fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>(
37 self,
38 bx: &mut Bx,
39 llvtable: Bx::Value,
40 ty: Ty<'tcx>,
41 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
42 ) -> Bx::Value {
43 self.get_fn_inner(bx, llvtable, ty, fn_abi, false)
44 }
45
46 pub(crate) fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
47 self,
48 bx: &mut Bx,
49 llvtable: Bx::Value,
50 ty: Ty<'tcx>,
51 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
52 ) -> Bx::Value {
53 self.get_fn_inner(bx, llvtable, ty, fn_abi, true)
54 }
55
56 pub(crate) fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
57 self,
58 bx: &mut Bx,
59 llvtable: Bx::Value,
60 ty: Ty<'tcx>,
61 ) -> Bx::Value {
62 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/meth.rs:63",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(63u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::meth"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("get_int({0:?}, {1:?})",
llvtable, self) as &dyn Value))])
});
} else { ; }
};debug!("get_int({:?}, {:?})", llvtable, self);
64
65 let llty = bx.type_isize();
66 let ptr_size = bx.data_layout().pointer_size();
67 let vtable_byte_offset = self.0 * ptr_size.bytes();
68
69 load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false)
70 }
71}
72
73fn dyn_trait_in_self<'tcx>(
76 tcx: TyCtxt<'tcx>,
77 ty: Ty<'tcx>,
78) -> Option<ty::ExistentialTraitRef<'tcx>> {
79 for arg in ty.peel_refs().walk() {
80 if let GenericArgKind::Type(ty) = arg.kind()
81 && let ty::Dynamic(data, _) = ty.kind()
82 {
83 return data
86 .principal()
87 .map(|principal| tcx.instantiate_bound_regions_with_erased(principal));
88 }
89 }
90
91 ::rustc_middle::util::bug::bug_fmt(format_args!("expected a `dyn Trait` ty, found {0:?}",
ty))bug!("expected a `dyn Trait` ty, found {ty:?}")
92}
93
94#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("get_vtable",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(102u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::meth"),
::tracing_core::field::FieldSet::new(&["ty", "trait_ref"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_ref)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Cx::Value = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = cx.tcx();
if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
return val;
}
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
let vtable_allocation =
tcx.global_alloc(vtable_alloc_id).unwrap_memory();
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
let align = cx.data_layout().pointer_align().abi;
let vtable =
cx.static_addr_of(vtable_const, align, Some("vtable"));
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
cx.create_vtable_debuginfo(ty, trait_ref, vtable);
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
vtable
}
}
}#[instrument(level = "debug", skip(cx))]
103pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
104 cx: &Cx,
105 ty: Ty<'tcx>,
106 trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
107) -> Cx::Value {
108 let tcx = cx.tcx();
109
110 if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
112 return val;
113 }
114
115 let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
116 let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
117 let vtable_const = cx.const_data_from_alloc(vtable_allocation);
118 let align = cx.data_layout().pointer_align().abi;
119 let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
120
121 cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
122 cx.create_vtable_debuginfo(ty, trait_ref, vtable);
123 cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
124 vtable
125}
126
127pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
129 bx: &mut Bx,
130 llvtable: Bx::Value,
131 llty: Bx::Type,
132 vtable_byte_offset: u64,
133 ty: Ty<'tcx>,
134 nonnull: bool,
135) -> Bx::Value {
136 let ptr_align = bx.data_layout().pointer_align().abi;
137
138 if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
139 && bx.cx().sess().lto() == Lto::Fat
140 {
141 if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
142 let typeid =
143 bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref).as_bytes()).unwrap();
144 let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
145 return func;
146 } else if nonnull {
147 ::rustc_middle::util::bug::bug_fmt(format_args!("load nonnull value from a vtable without a principal trait"))bug!("load nonnull value from a vtable without a principal trait")
148 }
149 }
150
151 let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
152 let ptr = bx.load(llty, gep, ptr_align);
153 bx.set_invariant_load(ptr);
155 if nonnull {
156 bx.nonnull_metadata(ptr);
157 }
158 ptr
159}