1use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt};
2use rustc_session::config::Lto;
3use rustc_span::bug;
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]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for VirtualIndex {
}
#[automatically_derived]impl ::core::clone::Clone for VirtualIndex {
#[inline]
fn clone(&self) -> Self {
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_struct_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 load_field<Bx: BuilderMethods<'a, 'tcx>>(
20 self,
21 bx: &mut Bx,
22 llvtable: Bx::Value,
23 llty: Bx::Type,
24 nonnull: bool,
25 ) -> Bx::Value {
26 let ptr_size = bx.data_layout().pointer_size();
27 let vtable_byte_offset = self.0 * ptr_size.bytes();
28
29 let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
30 let ptr_align = bx.data_layout().pointer_align();
31 let ptr = bx.load(llty, gep, ptr_align);
32
33 bx.set_invariant_load(ptr);
35
36 if nonnull {
37 bx.nonnull_metadata(ptr);
38 }
39
40 ptr
41 }
42
43 fn get_fn_inner<Bx: BuilderMethods<'a, 'tcx>>(
44 self,
45 bx: &mut Bx,
46 llvtable: Bx::Value,
47 ty: Ty<'tcx>,
48 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
49 nonnull: bool,
50 ) -> Bx::Value {
51 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs:52",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(52u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("get_fn({0:?}, {1:?}, {2:?})",
llvtable, ty, self) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
53
54 let llty = bx.fn_ptr_backend_type(fn_abi);
55 let ptr_size = bx.data_layout().pointer_size();
56 let vtable_byte_offset = self.0 * ptr_size.bytes();
57
58 if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
59 && bx.cx().sess().lto() == Lto::Fat
60 {
61 if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
62 let typeid = typeid_for_trait_ref(bx.tcx(), trait_ref);
63 let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid.as_bytes());
64 return func;
65 } else if nonnull {
66 ::rustc_span::macros::bug_impl(None,
format_args!("load nonnull value from a vtable without a principal trait"),
Location::caller())bug!("load nonnull value from a vtable without a principal trait")
67 }
68 }
69
70 self.load_field(bx, llvtable, llty, nonnull)
71 }
72
73 pub(crate) fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>(
74 self,
75 bx: &mut Bx,
76 llvtable: Bx::Value,
77 ty: Ty<'tcx>,
78 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
79 ) -> Bx::Value {
80 self.get_fn_inner(bx, llvtable, ty, fn_abi, false)
81 }
82
83 pub(crate) fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
84 self,
85 bx: &mut Bx,
86 llvtable: Bx::Value,
87 ty: Ty<'tcx>,
88 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
89 ) -> Bx::Value {
90 self.get_fn_inner(bx, llvtable, ty, fn_abi, true)
91 }
92
93 pub(crate) fn get_data_ptr<Bx: BuilderMethods<'a, 'tcx>>(
95 self,
96 bx: &mut Bx,
97 llvtable: Bx::Value,
98 nonnull: bool,
99 ) -> Bx::Value {
100 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs:100",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(100u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("get_data_ptr({0:?}, {1:?})",
llvtable, self) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("get_data_ptr({:?}, {:?})", llvtable, self);
101 self.load_field(bx, llvtable, bx.type_ptr(), nonnull)
102 }
103
104 pub(crate) fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
105 self,
106 bx: &mut Bx,
107 llvtable: Bx::Value,
108 ) -> Bx::Value {
109 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs:109",
"rustc_codegen_ssa::meth", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(109u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("get_usize({0:?}, {1:?})",
llvtable, self) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("get_usize({:?}, {:?})", llvtable, self);
110 self.load_field(bx, llvtable, bx.type_isize(), false)
111 }
112}
113
114fn dyn_trait_in_self<'tcx>(
117 tcx: TyCtxt<'tcx>,
118 ty: Ty<'tcx>,
119) -> Option<ty::ExistentialTraitRef<'tcx>> {
120 for arg in ty.peel_refs().walk() {
121 if let GenericArgKind::Type(ty) = arg.kind()
122 && let ty::Dynamic(data, _) = ty.kind()
123 {
124 return data
127 .principal()
128 .map(|principal| tcx.instantiate_bound_regions_with_erased(principal));
129 }
130 }
131
132 ::rustc_span::macros::bug_impl(None,
format_args!("expected a `dyn Trait` ty, found {0:?}", ty),
Location::caller())bug!("expected a `dyn Trait` ty, found {ty:?}")
133}
134
135{}
#[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("/rustc-dev/249c1e4e31111b54ad2483cfd4cea06c7020c653/compiler/rustc_codegen_ssa/src/meth.rs"),
::tracing_core::__macro_support::Option::Some(143u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::meth"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_ref")
}> =
::tracing::__macro_support::FieldName::new("trait_ref");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_ref)
as &dyn ::tracing::field::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 = cx.static_addr_of(vtable_allocation, 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))]
144pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
145 cx: &Cx,
146 ty: Ty<'tcx>,
147 trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
148) -> Cx::Value {
149 let tcx = cx.tcx();
150
151 if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
153 return val;
154 }
155
156 let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
157 let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
158 let vtable = cx.static_addr_of(vtable_allocation, Some("vtable"));
159
160 cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
161 cx.create_vtable_debuginfo(ty, trait_ref, vtable);
162 cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
163 vtable
164}