aboutsummaryrefslogtreecommitdiff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2010-12-20 10:23:37 -0800
committerPatrick Walton <[email protected]>2010-12-20 10:23:37 -0800
commita7e9984999121c84c92a3236f29d4edf649e9431 (patch)
treed5b9ca02c255a0ea3ed9de5338041f4b1cf8ead8 /src/comp
parentrustc: Remove the unused "name" parameter from trans.new_builder (diff)
downloadrust-a7e9984999121c84c92a3236f29d4edf649e9431.tar.xz
rust-a7e9984999121c84c92a3236f29d4edf649e9431.zip
rustc: Build tydescs for types, and make all take and drop operations go through the tydescs for simplicity (LLVM inlines them).
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/abi.rs11
-rw-r--r--src/comp/middle/trans.rs70
2 files changed, 54 insertions, 27 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 7f0ced61..fc44440a 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -28,6 +28,17 @@ const int vec_elt_alloc = 1;
const int vec_elt_fill = 2;
const int vec_elt_data = 3;
+const int tydesc_field_first_param = 0;
+const int tydesc_field_size = 1;
+const int tydesc_field_align = 2;
+const int tydesc_field_copy_glue_off = 3;
+const int tydesc_field_drop_glue_off = 4;
+const int tydesc_field_free_glue_off = 5;
+const int tydesc_field_sever_glue_off = 6;
+const int tydesc_field_mark_glue_off = 7;
+const int tydesc_field_obj_drop_glue_off = 8;
+const int tydesc_field_is_stateful = 9;
+
/* Both obj and fn are two-word "bindings": One word points to some static
* dispatch information (vtbl, thunk, callee), and the other points to some
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 50725df4..c40b2d0d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -68,7 +68,7 @@ state type crate_ctxt = rec(session.session sess,
hashmap[ast.def_id, ValueRef] item_ids,
hashmap[ast.def_id, @ast.item] items,
hashmap[ast.def_id, @tag_info] tags,
- hashmap[@typeck.ty, @ty_info] types,
+ hashmap[@typeck.ty, ValueRef] tydescs,
@glue_fns glues,
namegen names,
str path);
@@ -471,19 +471,6 @@ fn C_struct(vec[ValueRef] elts) -> ValueRef {
False);
}
-fn C_tydesc(TypeRef t) -> ValueRef {
- ret C_struct(vec(C_null(T_ptr(T_opaque())), // first_param
- llvm.LLVMSizeOf(t), // size
- llvm.LLVMAlignOf(t), // align
- C_null(T_ptr(T_opaque())), // copy_glue_off
- C_null(T_ptr(T_opaque())), // drop_glue_off
- C_null(T_ptr(T_opaque())), // free_glue_off
- C_null(T_ptr(T_opaque())), // sever_glue_off
- C_null(T_ptr(T_opaque())), // mark_glue_off
- C_null(T_ptr(T_opaque())), // obj_drop_glue_off
- C_null(T_ptr(T_opaque())))); // is_stateful
-}
-
fn decl_fn(ModuleRef llmod, str name, uint cc, TypeRef llty) -> ValueRef {
let ValueRef llfn =
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
@@ -576,21 +563,48 @@ fn trans_malloc(@block_ctxt cx, @typeck.ty t) -> result {
}
-// Glue and referent count twiddling
+// Type descriptor and type glue stuff
+
+// Given a type and a field index into its corresponding type descriptor,
+// returns an LLVM ValueRef of that field from the tydesc, generating the
+// tydesc if necessary.
+fn field_of_tydesc(@block_ctxt cx, @typeck.ty ty, int field) -> ValueRef {
+ auto tydesc = get_tydesc(cx.fcx.ccx, ty);
+ ret cx.build.GEP(tydesc, vec(C_int(0), C_int(field)));
+}
-fn get_ty_info(@crate_ctxt cx, @typeck.ty ty) -> @ty_info {
- if (!cx.types.contains_key(ty)) {
- make_ty_info(cx, ty);
+fn get_tydesc(@crate_ctxt cx, @typeck.ty ty) -> ValueRef {
+ if (!cx.tydescs.contains_key(ty)) {
+ make_tydesc(cx, ty);
}
- ret cx.types.get(ty);
+ ret cx.tydescs.get(ty);
}
-fn make_ty_info(@crate_ctxt cx, @typeck.ty ty) {
+fn make_tydesc(@crate_ctxt cx, @typeck.ty ty) {
auto tg = make_take_glue;
auto take_glue = make_generic_glue(cx, ty, "take", tg);
auto dg = make_drop_glue;
auto drop_glue = make_generic_glue(cx, ty, "drop", dg);
- cx.types.insert(ty, @rec(take_glue=take_glue, drop_glue=drop_glue));
+
+ auto llty = type_of(cx, ty);
+ auto pvoid = T_ptr(T_i8());
+ auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), pvoid), T_void()));
+ auto tydesc = C_struct(vec(C_null(pvoid),
+ llvm.LLVMSizeOf(llty),
+ llvm.LLVMAlignOf(llty),
+ take_glue, // copy_glue_off
+ drop_glue, // drop_glue_off
+ C_null(glue_fn_ty), // free_glue_off
+ C_null(glue_fn_ty), // sever_glue_off
+ C_null(glue_fn_ty), // mark_glue_off
+ C_null(glue_fn_ty), // obj_drop_glue_off
+ C_null(glue_fn_ty))); // is_stateful
+
+ auto name = sanitize(cx.names.next("tydesc_" + typeck.ty_to_str(ty)));
+ auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(tydesc), _str.buf(name));
+ llvm.LLVMSetInitializer(gvar, tydesc);
+ llvm.LLVMSetGlobalConstant(gvar, True);
+ cx.tydescs.insert(ty, gvar);
}
fn make_generic_glue(@crate_ctxt cx, @typeck.ty t, str name,
@@ -970,8 +984,9 @@ fn incr_all_refcnts(@block_ctxt cx,
@typeck.ty t) -> result {
if (!typeck.type_is_scalar(t)) {
auto llrawptr = cx.build.BitCast(v, T_ptr(T_i8()));
- cx.build.FastCall(get_ty_info(cx.fcx.ccx, t).take_glue,
- vec(cx.fcx.lltaskptr, llrawptr));
+ auto llfnptr = field_of_tydesc(cx, t, abi.tydesc_field_copy_glue_off);
+ auto llfn = cx.build.Load(llfnptr);
+ cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, llrawptr));
}
ret res(cx, C_nil());
}
@@ -993,8 +1008,9 @@ fn drop_ty(@block_ctxt cx,
@typeck.ty t) -> result {
if (!typeck.type_is_scalar(t)) {
auto llrawptr = cx.build.BitCast(v, T_ptr(T_i8()));
- cx.build.FastCall(get_ty_info(cx.fcx.ccx, t).drop_glue,
- vec(cx.fcx.lltaskptr, llrawptr));
+ auto llfnptr = field_of_tydesc(cx, t, abi.tydesc_field_drop_glue_off);
+ auto llfn = cx.build.Load(llfnptr);
+ cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, llrawptr));
}
ret res(cx, C_nil());
}
@@ -2833,7 +2849,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
auto glues = make_glues(llmod);
auto hasher = typeck.hash_ty;
auto eqer = typeck.eq_ty;
- auto types = map.mk_hashmap[@typeck.ty,@ty_info](hasher, eqer);
+ auto tydescs = map.mk_hashmap[@typeck.ty,ValueRef](hasher, eqer);
auto cx = @rec(sess = sess,
llmod = llmod,
@@ -2844,7 +2860,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
item_ids = new_def_hash[ValueRef](),
items = new_def_hash[@ast.item](),
tags = new_def_hash[@tag_info](),
- types = types,
+ tydescs = tydescs,
glues = glues,
names = namegen(0),
path = "_rust");