Implement trait objects (cc #14)
This commit is contained in:
parent
62a0203a5a
commit
6196146ac4
9 changed files with 243 additions and 177 deletions
|
@ -1,137 +0,0 @@
|
|||
From 307aba455c6ee3227d7c522c07761cda19dc716c Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Wed, 29 Aug 2018 14:29:05 +0200
|
||||
Subject: [PATCH] Disable all trait object unsizing
|
||||
|
||||
---
|
||||
src/libcore/alloc.rs | 2 +-
|
||||
src/libcore/fmt/builders.rs | 13 ++++++++-----
|
||||
src/libcore/fmt/mod.rs | 3 ++-
|
||||
src/libcore/panic.rs | 5 +++--
|
||||
src/libcore/slice/mod.rs | 2 +-
|
||||
5 files changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
|
||||
index 35e4eea..28b6e2f 100644
|
||||
--- a/src/libcore/alloc.rs
|
||||
+++ b/src/libcore/alloc.rs
|
||||
@@ -144,7 +144,7 @@ impl Layout {
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn for_value<T: ?Sized>(t: &T) -> Self {
|
||||
- let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
||||
+ let (size, align) = panic!(); //(mem::size_of_val(t), mem::align_of_val(t));
|
||||
// See rationale in `new` for why this us using an unsafe variant below
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
unsafe {
|
||||
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
|
||||
index 3c5f934..1427ab3 100644
|
||||
--- a/src/libcore/fmt/builders.rs
|
||||
+++ b/src/libcore/fmt/builders.rs
|
||||
@@ -18,6 +18,7 @@ struct PadAdapter<'a> {
|
||||
impl<'a> PadAdapter<'a> {
|
||||
fn wrap<'b, 'c: 'a+'b>(fmt: &'c mut fmt::Formatter, slot: &'b mut Option<Self>)
|
||||
-> fmt::Formatter<'b> {
|
||||
+ /*
|
||||
fmt.wrap_buf(move |buf| {
|
||||
*slot = Some(PadAdapter {
|
||||
buf,
|
||||
@@ -25,6 +26,8 @@ impl<'a> PadAdapter<'a> {
|
||||
});
|
||||
slot.as_mut().unwrap()
|
||||
})
|
||||
+ */
|
||||
+ panic!();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +110,7 @@ pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
|
||||
impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
/// Adds a new field to the generated struct output.
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
- pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<'a, 'b> {
|
||||
+ pub fn field(&mut self, name: &str, value: &impl fmt::Debug) -> &mut DebugStruct<'a, 'b> {
|
||||
self.result = self.result.and_then(|_| {
|
||||
let prefix = if self.has_fields {
|
||||
","
|
||||
@@ -204,7 +207,7 @@ pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> D
|
||||
impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
/// Adds a new field to the generated tuple struct output.
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
- pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut DebugTuple<'a, 'b> {
|
||||
+ pub fn field(&mut self, value: &impl fmt::Debug) -> &mut DebugTuple<'a, 'b> {
|
||||
self.result = self.result.and_then(|_| {
|
||||
let (prefix, space) = if self.fields > 0 {
|
||||
(",", " ")
|
||||
@@ -258,7 +261,7 @@ struct DebugInner<'a, 'b: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugInner<'a, 'b> {
|
||||
- fn entry(&mut self, entry: &dyn fmt::Debug) {
|
||||
+ fn entry(&mut self, entry: &impl fmt::Debug) {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
let mut slot = None;
|
||||
@@ -340,7 +343,7 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b
|
||||
impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
||||
/// Adds a new entry to the set output.
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
- pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugSet<'a, 'b> {
|
||||
+ pub fn entry(&mut self, entry: &impl fmt::Debug) -> &mut DebugSet<'a, 'b> {
|
||||
self.inner.entry(entry);
|
||||
self
|
||||
}
|
||||
@@ -411,7 +414,7 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a,
|
||||
impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
||||
/// Adds a new entry to the list output.
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
- pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut DebugList<'a, 'b> {
|
||||
+ pub fn entry(&mut self, entry: &impl fmt::Debug) -> &mut DebugList<'a, 'b> {
|
||||
self.inner.entry(entry);
|
||||
self
|
||||
}
|
||||
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
|
||||
index 928f95e..ad33906 100644
|
||||
--- a/src/libcore/fmt/mod.rs
|
||||
+++ b/src/libcore/fmt/mod.rs
|
||||
@@ -224,7 +224,8 @@ pub trait Write {
|
||||
}
|
||||
}
|
||||
|
||||
- write(&mut Adapter(self), args)
|
||||
+ //write(&mut Adapter(self), args)
|
||||
+ panic!()
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
|
||||
index 17cac5a..27b7dde 100644
|
||||
--- a/src/libcore/panic.rs
|
||||
+++ b/src/libcore/panic.rs
|
||||
@@ -58,8 +58,9 @@ impl<'a> PanicInfo<'a> {
|
||||
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
|
||||
location: Location<'a>)
|
||||
-> Self {
|
||||
- struct NoPayload;
|
||||
- PanicInfo { payload: &NoPayload, location, message }
|
||||
+ //struct NoPayload;
|
||||
+ //PanicInfo { payload: &NoPayload, location, message }
|
||||
+ panic!();
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
|
||||
index 88fdd76..8537f0e 100644
|
||||
--- a/src/libcore/slice/mod.rs
|
||||
+++ b/src/libcore/slice/mod.rs
|
||||
@@ -4003,7 +4003,7 @@ impl<A> SlicePartialEq<A> for [A]
|
||||
return true;
|
||||
}
|
||||
unsafe {
|
||||
- let size = mem::size_of_val(self);
|
||||
+ let size = panic!(); //mem::size_of_val(self);
|
||||
memcmp(self.as_ptr() as *const u8,
|
||||
other.as_ptr() as *const u8, size) == 0
|
||||
}
|
||||
--
|
||||
2.11.0
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -416,6 +416,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"ar 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift 0.21.0 (git+https://github.com/CraneStation/cranelift.git)",
|
||||
"cranelift-faerie 0.21.0 (git+https://github.com/CraneStation/cranelift.git)",
|
||||
"cranelift-module 0.21.0 (git+https://github.com/CraneStation/cranelift.git)",
|
||||
|
|
|
@ -24,6 +24,7 @@ target-lexicon = "0.0.3"
|
|||
faerie = "0.5.0"
|
||||
ar = "0.6.0"
|
||||
bitflags = "1.0.3"
|
||||
byteorder = "1.2.6"
|
||||
|
||||
# Uncomment to use local checkout of cranelift
|
||||
#[patch."https://github.com/CraneStation/cranelift.git"]
|
||||
|
|
|
@ -31,6 +31,18 @@ impl Termination for () {
|
|||
}
|
||||
}
|
||||
|
||||
trait SomeTrait {
|
||||
fn object_safe(&self);
|
||||
}
|
||||
|
||||
impl SomeTrait for &'static str {
|
||||
fn object_safe(&self) {
|
||||
unsafe {
|
||||
puts(*self as *const str as *const u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "start"]
|
||||
fn start<T: Termination + 'static>(
|
||||
main: fn() -> T,
|
||||
|
@ -45,15 +57,28 @@ static NUM_REF: &'static u8 = unsafe { &NUM };
|
|||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let slice: &[u8] = b"Hello\0" as &[u8; 6];
|
||||
if intrinsics::size_of_val(slice) as u8 != 6 {
|
||||
panic(&("eji", "frjio", 0, 0));
|
||||
};
|
||||
let ptr: *const u8 = slice as *const [u8] as *const u8;
|
||||
let world = box "World!\0";
|
||||
let hello: &[u8] = b"Hello\0" as &[u8; 6];
|
||||
let ptr: *const u8 = hello as *const [u8] as *const u8;
|
||||
puts(ptr);
|
||||
|
||||
let world = box "World!\0";
|
||||
puts(*world as *const str as *const u8);
|
||||
|
||||
if intrinsics::size_of_val(hello) as u8 != 6 {
|
||||
panic(&("", "", 0, 0));
|
||||
};
|
||||
|
||||
let chars = &['C', 'h', 'a', 'r', 's'];
|
||||
let chars = chars as &[char];
|
||||
if intrinsics::size_of_val(chars) as u8 != 4 * 5 {
|
||||
panic(&("", "", 0, 0));
|
||||
}
|
||||
|
||||
//panic(&("panic msg", "abc.rs", 0, 43));
|
||||
let a: &dyn SomeTrait = &"abc\0";
|
||||
a.object_safe();
|
||||
|
||||
if intrinsics::size_of_val(a) as u8 != 16 {
|
||||
panic(&("", "", 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
85
src/abi.rs
85
src/abi.rs
|
@ -50,6 +50,18 @@ fn get_pass_mode<'a, 'tcx: 'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn adjust_arg_for_abi<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
sig: FnSig<'tcx>,
|
||||
arg: CValue<'tcx>,
|
||||
) -> Value {
|
||||
match get_pass_mode(fx.tcx, sig.abi, arg.layout().ty, false) {
|
||||
PassMode::NoPass => unimplemented!("pass mode nopass"),
|
||||
PassMode::ByVal(_) => arg.load_value(fx),
|
||||
PassMode::ByRef => arg.force_stack(fx),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cton_sig_from_fn_ty<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn_ty: Ty<'tcx>,
|
||||
|
@ -164,12 +176,16 @@ pub fn get_function_name_and_sig<'a, 'tcx>(
|
|||
|
||||
impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
|
||||
/// Instance must be monomorphized
|
||||
pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
|
||||
pub fn get_function_id(&mut self, inst: Instance<'tcx>) -> FuncId {
|
||||
let (name, sig) = get_function_name_and_sig(self.tcx, inst);
|
||||
let func_id = self
|
||||
.module
|
||||
self.module
|
||||
.declare_function(&name, Linkage::Import, &sig)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Instance must be monomorphized
|
||||
pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
|
||||
let func_id = self.get_function_id(inst);
|
||||
self.module
|
||||
.declare_func_in_func(func_id, &mut self.bcx.func)
|
||||
}
|
||||
|
@ -468,29 +484,51 @@ pub fn codegen_call<'a, 'tcx: 'a>(
|
|||
PassMode::ByVal(_) => None,
|
||||
};
|
||||
|
||||
let instance = match fn_ty.sty {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
Some(Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs).unwrap())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let func_ref: Option<Value>; // Indirect call target
|
||||
|
||||
let first_arg = {
|
||||
if let Some(Instance {
|
||||
def: InstanceDef::Virtual(_, idx),
|
||||
..
|
||||
}) = instance
|
||||
{
|
||||
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx);
|
||||
func_ref = Some(method);
|
||||
Some(ptr)
|
||||
} else {
|
||||
func_ref = if instance.is_none() {
|
||||
let func = trans_operand(fx, func);
|
||||
Some(func.load_value(fx))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
args.get(0).map(|arg| adjust_arg_for_abi(fx, sig, *arg))
|
||||
}.into_iter()
|
||||
};
|
||||
|
||||
let call_args: Vec<Value> = return_ptr
|
||||
.into_iter()
|
||||
.chain(args.into_iter().map(|arg| {
|
||||
match get_pass_mode(fx.tcx, sig.abi, arg.layout().ty, false) {
|
||||
PassMode::NoPass => unimplemented!("pass mode nopass"),
|
||||
PassMode::ByVal(_) => arg.load_value(fx),
|
||||
PassMode::ByRef => arg.force_stack(fx),
|
||||
}
|
||||
})).collect::<Vec<_>>();
|
||||
.chain(first_arg)
|
||||
.chain(
|
||||
args.into_iter()
|
||||
.skip(1)
|
||||
.map(|arg| adjust_arg_for_abi(fx, sig, arg)),
|
||||
).collect::<Vec<_>>();
|
||||
|
||||
let call_inst = match fn_ty.sty {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
let inst = Instance::resolve(fx.tcx, ParamEnv::reveal_all(), def_id, substs).unwrap();
|
||||
let func_ref = fx.get_function_ref(inst);
|
||||
fx.bcx.ins().call(func_ref, &call_args)
|
||||
}
|
||||
ty::FnPtr(_) => {
|
||||
let func = trans_operand(fx, func);
|
||||
let func = func.load_value(fx);
|
||||
let sig = fx.bcx.import_signature(cton_sig_from_fn_ty(fx.tcx, fn_ty));
|
||||
fx.bcx.ins().call_indirect(sig, func, &call_args)
|
||||
}
|
||||
_ => bug!("{:?}", fn_ty),
|
||||
let call_inst = if let Some(func_ref) = func_ref {
|
||||
fx.bcx.ins().call_indirect(sig, func_ref, &call_args)
|
||||
} else {
|
||||
let func_ref = fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type"));
|
||||
fx.bcx.ins().call(func_ref, &call_args)
|
||||
};
|
||||
|
||||
match output_pass_mode {
|
||||
|
@ -610,6 +648,7 @@ fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
|||
let elem_size = fx.layout_of(elem).size.bytes();
|
||||
fx.bcx.ins().imul_imm(len, elem_size as i64)
|
||||
}
|
||||
ty::Dynamic(..) => crate::vtable::size_of_obj(fx, args[0]),
|
||||
ty => unimplemented!("size_of_val for {:?}", ty),
|
||||
};
|
||||
ret.write_cvalue(fx, CValue::ByVal(size, usize_layout));
|
||||
|
|
|
@ -12,7 +12,7 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
|
|||
pub fn trans_mono_item<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
module: &mut Module<impl Backend>,
|
||||
caches: &mut Caches,
|
||||
caches: &mut Caches<'tcx>,
|
||||
ccx: &mut crate::constant::ConstantCx,
|
||||
mono_item: MonoItem<'tcx>,
|
||||
) {
|
||||
|
@ -59,7 +59,7 @@ fn trans_fn<'a, 'tcx: 'a>(
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
module: &mut Module<impl Backend>,
|
||||
constants: &mut crate::constant::ConstantCx,
|
||||
caches: &mut Caches,
|
||||
caches: &mut Caches<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
) {
|
||||
// Step 1. Get mir
|
||||
|
|
|
@ -236,9 +236,13 @@ impl<'tcx> CValue<'tcx> {
|
|||
}
|
||||
_ => bug!("unsize non array {:?} to slice", ty),
|
||||
},
|
||||
ty::Dynamic(_, _) => match ty.sty {
|
||||
ty::Dynamic(data, _) => match ty.sty {
|
||||
ty::Dynamic(_, _) => self.load_value_pair(fx),
|
||||
_ => unimpl!("unsize of type ... to {:?}", dest.layout().ty),
|
||||
_ => {
|
||||
let ptr = self.load_value(fx);
|
||||
let vtable = crate::vtable::get_vtable(fx, ty, data.principal());
|
||||
(ptr, vtable)
|
||||
}
|
||||
},
|
||||
_ => bug!(
|
||||
"unsize of type {:?} to {:?}",
|
||||
|
@ -556,7 +560,7 @@ pub struct FunctionCx<'a, 'tcx: 'a, B: Backend + 'a> {
|
|||
pub local_map: HashMap<Local, CPlace<'tcx>>,
|
||||
pub comments: HashMap<Inst, String>,
|
||||
pub constants: &'a mut crate::constant::ConstantCx,
|
||||
pub caches: &'a mut Caches,
|
||||
pub caches: &'a mut Caches<'tcx>,
|
||||
|
||||
/// add_global_comment inserts a comment here
|
||||
pub top_nop: Option<Inst>,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(rustc_private, macro_at_most_once_rep)]
|
||||
#![allow(intra_doc_link_resolution_failure)]
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate syntax;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
|
@ -53,6 +54,7 @@ mod common;
|
|||
mod constant;
|
||||
mod metadata;
|
||||
mod pretty_clif;
|
||||
mod vtable;
|
||||
|
||||
mod prelude {
|
||||
pub use std::any::Any;
|
||||
|
@ -100,14 +102,16 @@ mod prelude {
|
|||
use crate::constant::ConstantCx;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Caches {
|
||||
pub struct Caches<'tcx> {
|
||||
pub context: Context,
|
||||
pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
|
||||
}
|
||||
|
||||
impl Caches {
|
||||
impl<'tcx> Caches<'tcx> {
|
||||
fn new() -> Self {
|
||||
Caches {
|
||||
context: Context::new(),
|
||||
vtables: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
129
src/vtable.rs
Normal file
129
src/vtable.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
//! See librustc_codegen_llvm/meth.rs for reference
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
const DROP_FN_INDEX: usize = 0;
|
||||
const SIZE_INDEX: usize = 1;
|
||||
const ALIGN_INDEX: usize = 2;
|
||||
|
||||
pub fn size_of_obj<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
val: CValue<'tcx>,
|
||||
) -> Value {
|
||||
let (_ptr, vtable) = val.load_value_pair(fx);
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
fx.bcx.ins().load(
|
||||
pointer_ty(fx.tcx),
|
||||
MemFlags::new(),
|
||||
vtable,
|
||||
(SIZE_INDEX * usize_size) as i32,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
arg: CValue<'tcx>,
|
||||
idx: usize,
|
||||
) -> (Value, Value) {
|
||||
let (ptr, vtable) = arg.load_value_pair(fx);
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
|
||||
let func_ref = fx.bcx.ins().load(
|
||||
pointer_ty(fx.tcx),
|
||||
MemFlags::new(),
|
||||
vtable,
|
||||
((idx + 3) * usize_size as usize) as i32,
|
||||
);
|
||||
(ptr, func_ref)
|
||||
}
|
||||
|
||||
pub fn get_vtable<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
) -> Value {
|
||||
let data_id = if let Some(data_id) = fx.caches.vtables.get(&(ty, trait_ref)) {
|
||||
*data_id
|
||||
} else {
|
||||
let data_id = build_vtable(fx, ty, trait_ref);
|
||||
fx.caches.vtables.insert((ty, trait_ref), data_id);
|
||||
data_id
|
||||
};
|
||||
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
fx.bcx
|
||||
.ins()
|
||||
.global_value(fx.module.pointer_type(), local_data_id)
|
||||
}
|
||||
|
||||
fn build_vtable<'a, 'tcx: 'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
) -> DataId {
|
||||
let tcx = fx.tcx;
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
|
||||
let (size, align) = tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(ty))
|
||||
.unwrap()
|
||||
.size_and_align();
|
||||
let drop_in_place_fn =
|
||||
fx.get_function_id(::rustc_mir::monomorphize::resolve_drop_in_place(tcx, ty));
|
||||
|
||||
let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];
|
||||
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
let trait_ref = trait_ref.with_self_ty(tcx, ty);
|
||||
let methods = tcx.vtable_methods(trait_ref);
|
||||
let methods = methods.iter().cloned().map(|opt_mth| {
|
||||
opt_mth.map_or(None, |(def_id, substs)| {
|
||||
Some(fx.get_function_id(
|
||||
Instance::resolve(tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
|
||||
))
|
||||
})
|
||||
});
|
||||
components.extend(methods);
|
||||
}
|
||||
|
||||
let mut data_ctx = DataContext::new();
|
||||
let mut data = ::std::iter::repeat(0u8)
|
||||
.take(components.len() * usize_size)
|
||||
.collect::<Vec<u8>>()
|
||||
.into_boxed_slice();
|
||||
write_usize(fx.tcx, &mut data, SIZE_INDEX, size.bytes());
|
||||
write_usize(fx.tcx, &mut data, ALIGN_INDEX, align.abi());
|
||||
data_ctx.define(data);
|
||||
|
||||
for (i, component) in components.into_iter().enumerate() {
|
||||
if let Some(func_id) = component {
|
||||
let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
|
||||
data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
|
||||
}
|
||||
}
|
||||
|
||||
let data_id = fx
|
||||
.module
|
||||
.declare_data(
|
||||
&format!("vtable.{:?}.for.{:?}", trait_ref, ty),
|
||||
Linkage::Local,
|
||||
false,
|
||||
).unwrap();
|
||||
fx.module.define_data(data_id, &data_ctx).unwrap();
|
||||
data_id
|
||||
}
|
||||
|
||||
fn write_usize(tcx: TyCtxt, buf: &mut [u8], idx: usize, num: u64) {
|
||||
use byteorder::{BigEndian, LittleEndian, WriteBytesExt};
|
||||
|
||||
let usize_size = tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(tcx.types.usize))
|
||||
.unwrap()
|
||||
.size
|
||||
.bytes() as usize;
|
||||
let mut target = &mut buf[idx * usize_size..(idx + 1) * usize_size];
|
||||
|
||||
match tcx.data_layout.endian {
|
||||
layout::Endian::Little => target.write_uint::<LittleEndian>(num, usize_size),
|
||||
layout::Endian::Big => target.write_uint::<BigEndian>(num, usize_size),
|
||||
}.unwrap()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue