Add a field borrow_offset
to the type descriptor indicating
what amount a T* pointer must be adjusted to reach the contents of the box. For `~T` types, this requires knowing the type `T`, which is not known in the case of objects.
This commit is contained in:
parent
3aefb9649d
commit
6fe59bf877
@ -46,7 +46,8 @@ pub static tydesc_field_take_glue: uint = 2u;
|
||||
pub static tydesc_field_drop_glue: uint = 3u;
|
||||
pub static tydesc_field_free_glue: uint = 4u;
|
||||
pub static tydesc_field_visit_glue: uint = 5u;
|
||||
pub static n_tydesc_fields: uint = 6u;
|
||||
pub static tydesc_field_borrow_offset: uint = 6u;
|
||||
pub static n_tydesc_fields: uint = 7u;
|
||||
|
||||
// The two halves of a closure: code and environment.
|
||||
pub static fn_field_code: uint = 0u;
|
||||
|
@ -54,6 +54,7 @@ pub struct tydesc_info {
|
||||
tydesc: ValueRef,
|
||||
size: ValueRef,
|
||||
align: ValueRef,
|
||||
borrow_offset: ValueRef,
|
||||
take_glue: Option<ValueRef>,
|
||||
drop_glue: Option<ValueRef>,
|
||||
free_glue: Option<ValueRef>,
|
||||
|
@ -236,6 +236,36 @@ impl CrateContext {
|
||||
pub fn builder(@mut self) -> Builder {
|
||||
Builder::new(self)
|
||||
}
|
||||
|
||||
pub fn const_inbounds_gepi(&self,
|
||||
pointer: ValueRef,
|
||||
indices: &[uint]) -> ValueRef {
|
||||
debug!("const_inbounds_gepi: pointer=%s indices=%?",
|
||||
self.tn.val_to_str(pointer), indices);
|
||||
let v: ~[ValueRef] =
|
||||
indices.iter().transform(|i| C_i32(*i as i32)).collect();
|
||||
unsafe {
|
||||
llvm::LLVMConstInBoundsGEP(pointer,
|
||||
vec::raw::to_ptr(v),
|
||||
indices.len() as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offsetof_gep(&self,
|
||||
llptr_ty: Type,
|
||||
indices: &[uint]) -> ValueRef {
|
||||
/*!
|
||||
* Returns the offset of applying the given GEP indices
|
||||
* to an instance of `llptr_ty`. Similar to `offsetof` in C,
|
||||
* except that `llptr_ty` must be a pointer type.
|
||||
*/
|
||||
|
||||
unsafe {
|
||||
let null = C_null(llptr_ty);
|
||||
llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
|
||||
self.int_type.to_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
|
@ -655,6 +655,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
ppaux::ty_to_str(ccx.tcx, t));
|
||||
}
|
||||
|
||||
let has_header = match ty::get(t).sty {
|
||||
ty::ty_box(*) => true,
|
||||
ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(),
|
||||
_ => false
|
||||
};
|
||||
|
||||
let borrow_offset = if has_header {
|
||||
ccx.offsetof_gep(llty, [0u, abi::box_field_body])
|
||||
} else {
|
||||
C_uint(ccx, 0)
|
||||
};
|
||||
|
||||
let llsize = llsize_of(ccx, llty);
|
||||
let llalign = llalign_of(ccx, llty);
|
||||
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
|
||||
@ -670,6 +682,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
tydesc: gvar,
|
||||
size: llsize,
|
||||
align: llalign,
|
||||
borrow_offset: borrow_offset,
|
||||
take_glue: None,
|
||||
drop_glue: None,
|
||||
free_glue: None,
|
||||
@ -785,13 +798,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
}
|
||||
};
|
||||
|
||||
debug!("ti.borrow_offset: %s",
|
||||
ccx.tn.val_to_str(ti.borrow_offset));
|
||||
|
||||
let tydesc = C_named_struct(ccx.tydesc_type,
|
||||
[ti.size, // size
|
||||
ti.align, // align
|
||||
take_glue, // take_glue
|
||||
drop_glue, // drop_glue
|
||||
free_glue, // free_glue
|
||||
visit_glue]); // visit_glue
|
||||
ti.align, // align
|
||||
take_glue, // take_glue
|
||||
drop_glue, // drop_glue
|
||||
free_glue, // free_glue
|
||||
visit_glue, // visit_glue
|
||||
ti.borrow_offset]); // borrow_offset
|
||||
|
||||
unsafe {
|
||||
let gvar = ti.tydesc;
|
||||
|
@ -205,10 +205,18 @@ impl Type {
|
||||
|
||||
let int_ty = Type::int(arch);
|
||||
|
||||
let elems = [
|
||||
int_ty, int_ty,
|
||||
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
|
||||
];
|
||||
// Must mirror:
|
||||
//
|
||||
// std::unstable::intrinsics::TyDesc
|
||||
// type_desc in rt
|
||||
|
||||
let elems = [int_ty, // size
|
||||
int_ty, // align
|
||||
glue_fn_ty, // take
|
||||
glue_fn_ty, // drop
|
||||
glue_fn_ty, // free
|
||||
glue_fn_ty, // visit
|
||||
int_ty]; // borrow_offset
|
||||
|
||||
tydesc.set_struct_body(elems, false);
|
||||
|
||||
@ -249,8 +257,12 @@ impl Type {
|
||||
Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
|
||||
}
|
||||
|
||||
pub fn opaque() -> Type {
|
||||
Type::i8()
|
||||
}
|
||||
|
||||
pub fn opaque_box(ctx: &CrateContext) -> Type {
|
||||
Type::box(ctx, &Type::i8())
|
||||
Type::box(ctx, &Type::opaque())
|
||||
}
|
||||
|
||||
pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
|
||||
|
@ -226,10 +226,7 @@ pub enum AutoRef {
|
||||
AutoBorrowFn(Region),
|
||||
|
||||
/// Convert from T to *T
|
||||
AutoUnsafe(ast::mutability),
|
||||
|
||||
/// Convert from @Trait/~Trait/&Trait to &Trait
|
||||
AutoBorrowObj(Region, ast::mutability),
|
||||
AutoUnsafe(ast::mutability)
|
||||
}
|
||||
|
||||
pub type ctxt = @ctxt_;
|
||||
|
@ -38,16 +38,34 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
|
||||
|
||||
pub type GlueFn = extern "Rust" fn(*i8);
|
||||
|
||||
// NB: this has to be kept in sync with the Rust ABI.
|
||||
// NB: this has to be kept in sync with `type_desc` in `rt`
|
||||
#[lang="ty_desc"]
|
||||
#[cfg(not(test))]
|
||||
pub struct TyDesc {
|
||||
// sizeof(T)
|
||||
size: uint,
|
||||
|
||||
// alignof(T)
|
||||
align: uint,
|
||||
|
||||
// Called on a copy of a value of type `T` *after* memcpy
|
||||
take_glue: GlueFn,
|
||||
|
||||
// Called when a value of type `T` is no longer needed
|
||||
drop_glue: GlueFn,
|
||||
|
||||
// Called by drop glue when a value of type `T` can be freed
|
||||
free_glue: GlueFn,
|
||||
|
||||
// Called by reflection visitor to visit a value of type `T`
|
||||
visit_glue: GlueFn,
|
||||
|
||||
// If T represents a box pointer (`@U` or `~U`), then
|
||||
// `borrow_offset` is the amount that the pointer must be adjusted
|
||||
// to find the payload. This is always derivable from the type
|
||||
// `U`, but in the case of `@Trait` or `~Trait` objects, the type
|
||||
// `U` is unknown.
|
||||
borrow_offset: uint,
|
||||
}
|
||||
|
||||
#[lang="opaque"]
|
||||
|
@ -58,6 +58,7 @@ struct type_desc {
|
||||
glue_fn *drop_glue;
|
||||
glue_fn *free_glue;
|
||||
glue_fn *visit_glue;
|
||||
size_t borrow_offset;
|
||||
};
|
||||
|
||||
extern "C" type_desc *rust_clone_type_desc(type_desc*);
|
||||
|
@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
|
||||
NULL, // drop_glue
|
||||
NULL, // free_glue
|
||||
NULL, // visit_glue
|
||||
0, // borrow_offset
|
||||
};
|
||||
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user