Skip to content

Commit 6fe59bf

Browse files
committed
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.
1 parent 3aefb96 commit 6fe59bf

File tree

9 files changed

+94
-16
lines changed

9 files changed

+94
-16
lines changed

src/librustc/back/abi.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ pub static tydesc_field_take_glue: uint = 2u;
4646
pub static tydesc_field_drop_glue: uint = 3u;
4747
pub static tydesc_field_free_glue: uint = 4u;
4848
pub static tydesc_field_visit_glue: uint = 5u;
49-
pub static n_tydesc_fields: uint = 6u;
49+
pub static tydesc_field_borrow_offset: uint = 6u;
50+
pub static n_tydesc_fields: uint = 7u;
5051

5152
// The two halves of a closure: code and environment.
5253
pub static fn_field_code: uint = 0u;

src/librustc/middle/trans/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub struct tydesc_info {
5454
tydesc: ValueRef,
5555
size: ValueRef,
5656
align: ValueRef,
57+
borrow_offset: ValueRef,
5758
take_glue: Option<ValueRef>,
5859
drop_glue: Option<ValueRef>,
5960
free_glue: Option<ValueRef>,

src/librustc/middle/trans/context.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,36 @@ impl CrateContext {
236236
pub fn builder(@mut self) -> Builder {
237237
Builder::new(self)
238238
}
239+
240+
pub fn const_inbounds_gepi(&self,
241+
pointer: ValueRef,
242+
indices: &[uint]) -> ValueRef {
243+
debug!("const_inbounds_gepi: pointer=%s indices=%?",
244+
self.tn.val_to_str(pointer), indices);
245+
let v: ~[ValueRef] =
246+
indices.iter().transform(|i| C_i32(*i as i32)).collect();
247+
unsafe {
248+
llvm::LLVMConstInBoundsGEP(pointer,
249+
vec::raw::to_ptr(v),
250+
indices.len() as c_uint)
251+
}
252+
}
253+
254+
pub fn offsetof_gep(&self,
255+
llptr_ty: Type,
256+
indices: &[uint]) -> ValueRef {
257+
/*!
258+
* Returns the offset of applying the given GEP indices
259+
* to an instance of `llptr_ty`. Similar to `offsetof` in C,
260+
* except that `llptr_ty` must be a pointer type.
261+
*/
262+
263+
unsafe {
264+
let null = C_null(llptr_ty);
265+
llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
266+
self.int_type.to_ref())
267+
}
268+
}
239269
}
240270

241271
#[unsafe_destructor]

src/librustc/middle/trans/glue.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
655655
ppaux::ty_to_str(ccx.tcx, t));
656656
}
657657

658+
let has_header = match ty::get(t).sty {
659+
ty::ty_box(*) => true,
660+
ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(),
661+
_ => false
662+
};
663+
664+
let borrow_offset = if has_header {
665+
ccx.offsetof_gep(llty, [0u, abi::box_field_body])
666+
} else {
667+
C_uint(ccx, 0)
668+
};
669+
658670
let llsize = llsize_of(ccx, llty);
659671
let llalign = llalign_of(ccx, llty);
660672
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 {
670682
tydesc: gvar,
671683
size: llsize,
672684
align: llalign,
685+
borrow_offset: borrow_offset,
673686
take_glue: None,
674687
drop_glue: None,
675688
free_glue: None,
@@ -785,13 +798,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
785798
}
786799
};
787800

801+
debug!("ti.borrow_offset: %s",
802+
ccx.tn.val_to_str(ti.borrow_offset));
803+
788804
let tydesc = C_named_struct(ccx.tydesc_type,
789805
[ti.size, // size
790-
ti.align, // align
791-
take_glue, // take_glue
792-
drop_glue, // drop_glue
793-
free_glue, // free_glue
794-
visit_glue]); // visit_glue
806+
ti.align, // align
807+
take_glue, // take_glue
808+
drop_glue, // drop_glue
809+
free_glue, // free_glue
810+
visit_glue, // visit_glue
811+
ti.borrow_offset]); // borrow_offset
795812

796813
unsafe {
797814
let gvar = ti.tydesc;

src/librustc/middle/trans/type_.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,18 @@ impl Type {
205205

206206
let int_ty = Type::int(arch);
207207

208-
let elems = [
209-
int_ty, int_ty,
210-
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
211-
];
208+
// Must mirror:
209+
//
210+
// std::unstable::intrinsics::TyDesc
211+
// type_desc in rt
212+
213+
let elems = [int_ty, // size
214+
int_ty, // align
215+
glue_fn_ty, // take
216+
glue_fn_ty, // drop
217+
glue_fn_ty, // free
218+
glue_fn_ty, // visit
219+
int_ty]; // borrow_offset
212220

213221
tydesc.set_struct_body(elems, false);
214222

@@ -249,8 +257,12 @@ impl Type {
249257
Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
250258
}
251259

260+
pub fn opaque() -> Type {
261+
Type::i8()
262+
}
263+
252264
pub fn opaque_box(ctx: &CrateContext) -> Type {
253-
Type::box(ctx, &Type::i8())
265+
Type::box(ctx, &Type::opaque())
254266
}
255267

256268
pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {

src/librustc/middle/ty.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,7 @@ pub enum AutoRef {
226226
AutoBorrowFn(Region),
227227

228228
/// Convert from T to *T
229-
AutoUnsafe(ast::mutability),
230-
231-
/// Convert from @Trait/~Trait/&Trait to &Trait
232-
AutoBorrowObj(Region, ast::mutability),
229+
AutoUnsafe(ast::mutability)
233230
}
234231

235232
pub type ctxt = @ctxt_;

src/libstd/unstable/intrinsics.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,34 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
3838

3939
pub type GlueFn = extern "Rust" fn(*i8);
4040

41-
// NB: this has to be kept in sync with the Rust ABI.
41+
// NB: this has to be kept in sync with `type_desc` in `rt`
4242
#[lang="ty_desc"]
4343
#[cfg(not(test))]
4444
pub struct TyDesc {
45+
// sizeof(T)
4546
size: uint,
47+
48+
// alignof(T)
4649
align: uint,
50+
51+
// Called on a copy of a value of type `T` *after* memcpy
4752
take_glue: GlueFn,
53+
54+
// Called when a value of type `T` is no longer needed
4855
drop_glue: GlueFn,
56+
57+
// Called by drop glue when a value of type `T` can be freed
4958
free_glue: GlueFn,
59+
60+
// Called by reflection visitor to visit a value of type `T`
5061
visit_glue: GlueFn,
62+
63+
// If T represents a box pointer (`@U` or `~U`), then
64+
// `borrow_offset` is the amount that the pointer must be adjusted
65+
// to find the payload. This is always derivable from the type
66+
// `U`, but in the case of `@Trait` or `~Trait` objects, the type
67+
// `U` is unknown.
68+
borrow_offset: uint,
5169
}
5270

5371
#[lang="opaque"]

src/rt/rust_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct type_desc {
5858
glue_fn *drop_glue;
5959
glue_fn *free_glue;
6060
glue_fn *visit_glue;
61+
size_t borrow_offset;
6162
};
6263

6364
extern "C" type_desc *rust_clone_type_desc(type_desc*);

src/rt/rust_util.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
2121
NULL, // drop_glue
2222
NULL, // free_glue
2323
NULL, // visit_glue
24+
0, // borrow_offset
2425
};
2526

2627
//

0 commit comments

Comments
 (0)