]>
git.proxmox.com Git - rustc.git/blob - src/librustc_trans/meth.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
20 use rustc
::ty
::{self, Ty}
;
23 #[derive(Copy, Clone, Debug)]
24 pub struct VirtualIndex(usize);
26 pub const DESTRUCTOR
: VirtualIndex
= VirtualIndex(0);
27 pub const SIZE
: VirtualIndex
= VirtualIndex(1);
28 pub const ALIGN
: VirtualIndex
= VirtualIndex(2);
30 impl<'a
, 'tcx
> VirtualIndex
{
31 pub fn from_index(index
: usize) -> Self {
32 VirtualIndex(index
+ 3)
35 pub fn get_fn(self, bcx
: &Builder
<'a
, 'tcx
>, llvtable
: ValueRef
) -> ValueRef
{
36 // Load the data pointer from the object.
37 debug
!("get_fn({:?}, {:?})", Value(llvtable
), self);
39 let ptr
= bcx
.load_nonnull(bcx
.gepi(llvtable
, &[self.0]), None
);
40 // Vtable loads are invariant
41 bcx
.set_invariant_load(ptr
);
45 pub fn get_usize(self, bcx
: &Builder
<'a
, 'tcx
>, llvtable
: ValueRef
) -> ValueRef
{
46 // Load the data pointer from the object.
47 debug
!("get_int({:?}, {:?})", Value(llvtable
), self);
49 let llvtable
= bcx
.pointercast(llvtable
, Type
::isize(bcx
.ccx
).ptr_to());
50 let ptr
= bcx
.load(bcx
.gepi(llvtable
, &[self.0]), None
);
51 // Vtable loads are invariant
52 bcx
.set_invariant_load(ptr
);
57 /// Creates a dynamic vtable for the given type and vtable origin.
58 /// This is used only for objects.
60 /// The vtables are cached instead of created on every call.
62 /// The `trait_ref` encodes the erased self type. Hence if we are
63 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
64 /// `trait_ref` would map `T:Trait`.
65 pub fn get_vtable
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
67 trait_ref
: Option
<ty
::PolyExistentialTraitRef
<'tcx
>>)
72 debug
!("get_vtable(ty={:?}, trait_ref={:?})", ty
, trait_ref
);
75 if let Some(&val
) = ccx
.vtables().borrow().get(&(ty
, trait_ref
)) {
79 // Not in the cache. Build it.
80 let nullptr
= C_null(Type
::nil(ccx
).ptr_to());
82 let mut components
: Vec
<_
> = [
83 callee
::get_fn(ccx
, monomorphize
::resolve_drop_in_place(ccx
.tcx(), ty
)),
84 C_usize(ccx
, ccx
.size_of(ty
)),
85 C_usize(ccx
, ccx
.align_of(ty
) as u64)
86 ].iter().cloned().collect();
88 if let Some(trait_ref
) = trait_ref
{
89 let trait_ref
= trait_ref
.with_self_ty(tcx
, ty
);
90 let methods
= tcx
.vtable_methods(trait_ref
);
91 let methods
= methods
.iter().cloned().map(|opt_mth
| {
92 opt_mth
.map_or(nullptr
, |(def_id
, substs
)| {
93 callee
::resolve_and_get_fn(ccx
, def_id
, substs
)
96 components
.extend(methods
);
99 let vtable_const
= C_struct(ccx
, &components
, false);
100 let align
= machine
::llalign_of_pref(ccx
, val_ty(vtable_const
));
101 let vtable
= consts
::addr_of(ccx
, vtable_const
, align
, "vtable");
103 debuginfo
::create_vtable_metadata(ccx
, ty
, vtable
);
105 ccx
.vtables().borrow_mut().insert((ty
, trait_ref
), vtable
);