aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-12-30 17:01:20 -0800
committerGraydon Hoare <[email protected]>2010-12-30 17:01:20 -0800
commit1f2585f4792dc6d390c67906d8bde4ac9cdef2e3 (patch)
tree9ee2d163228045d189727e161e0ff2c4eabcf46e
parentAssign method types properly by sorted-order. (diff)
downloadrust-1f2585f4792dc6d390c67906d8bde4ac9cdef2e3.tar.xz
rust-1f2585f4792dc6d390c67906d8bde4ac9cdef2e3.zip
Teach trans to access object fields.
-rw-r--r--src/comp/middle/trans.rs114
1 files changed, 100 insertions, 14 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 0064ba3c..7119fa11 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -68,6 +68,7 @@ state type crate_ctxt = rec(session.session sess,
hashmap[ast.def_id, @ast.item] items,
hashmap[ast.def_id, @tag_info] tags,
hashmap[@ty.t, ValueRef] tydescs,
+ vec[ast.obj_field] obj_fields,
@glue_fns glues,
namegen names,
str path);
@@ -77,6 +78,7 @@ state type fn_ctxt = rec(ValueRef llfn,
mutable option.t[ValueRef] llself,
mutable option.t[ValueRef] llretptr,
hashmap[ast.def_id, ValueRef] llargs,
+ hashmap[ast.def_id, ValueRef] llobjfields,
hashmap[ast.def_id, ValueRef] lllocals,
hashmap[ast.def_id, ValueRef] lltydescs,
@crate_ctxt ccx);
@@ -1667,6 +1669,10 @@ fn trans_name(@block_ctxt cx, &ast.name n, &option.t[ast.def] dopt)
check (cx.fcx.lllocals.contains_key(did));
ret lval_mem(cx, cx.fcx.lllocals.get(did));
}
+ case (ast.def_obj_field(?did)) {
+ check (cx.fcx.llobjfields.contains_key(did));
+ ret lval_mem(cx, cx.fcx.llobjfields.get(did));
+ }
case (ast.def_fn(?did)) {
check (cx.fcx.ccx.item_ids.contains_key(did));
ret lval_val(cx, cx.fcx.ccx.item_ids.get(did));
@@ -2382,8 +2388,9 @@ fn new_fn_ctxt(@crate_ctxt cx,
let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 0u);
- let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef]();
+ let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef]();
+ let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] lltydescs = new_def_hash[ValueRef]();
ret @rec(llfn=llfndecl,
@@ -2391,6 +2398,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
mutable llself=none[ValueRef],
mutable llretptr=none[ValueRef],
llargs=llargs,
+ llobjfields=llobjfields,
lllocals=lllocals,
lltydescs=lltydescs,
ccx=cx);
@@ -2434,16 +2442,31 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
}
}
-
// Recommended LLVM style, strange though this is, is to copy from args to
// allocas immediately upon entry; this permits us to GEP into structures we
// were passed and whatnot. Apparently mem2reg will mop up.
-fn copy_args_to_allocas(@block_ctxt cx, vec[ast.arg] args,
- vec[ty.arg] arg_tys) {
+impure fn copy_args_to_allocas(@block_ctxt cx,
+ option.t[TypeRef] ty_self,
+ vec[ast.arg] args,
+ vec[ty.arg] arg_tys) {
let uint arg_n = 0u;
+ alt (cx.fcx.llself) {
+ case (some[ValueRef](?self_v)) {
+ alt (ty_self) {
+ case (some[TypeRef](?self_t)) {
+ auto alloca = cx.build.Alloca(self_t);
+ cx.build.Store(self_v, alloca);
+ cx.fcx.llself = some[ValueRef](alloca);
+ }
+ }
+ }
+ case (_) {
+ }
+ }
+
for (ast.arg aarg in args) {
if (aarg.mode != ast.alias) {
auto arg_t = type_of_arg(cx.fcx.ccx, arg_tys.(arg_n));
@@ -2481,19 +2504,66 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t {
fail;
}
+fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) {
+
+ let vec[TypeRef] llfield_tys = vec();
+
+ for (ast.obj_field f in cx.fcx.ccx.obj_fields) {
+ llfield_tys += node_type(cx.fcx.ccx, f.ann);
+ }
+
+ let TypeRef llfields_ty = T_struct(llfield_tys);
+ let TypeRef lltydesc_ty = T_ptr(T_tydesc());
+ let TypeRef llobj_body_ty = T_struct(vec(lltydesc_ty,
+ llfields_ty));
+ let TypeRef llobj_box_ty = T_ptr(T_box(llobj_body_ty));
+
+ auto box_cell =
+ cx.build.GEP(llself,
+ vec(C_int(0),
+ C_int(abi.obj_field_box)));
+
+ auto box_ptr = cx.build.Load(box_cell);
+
+ box_ptr = cx.build.PointerCast(box_ptr, llobj_box_ty);
+
+ auto obj_fields = cx.build.GEP(box_ptr,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body),
+ C_int(abi.obj_body_elt_fields)));
+
+ let int i = 0;
+ for (ast.obj_field f in cx.fcx.ccx.obj_fields) {
+ let ValueRef llfield = cx.build.GEP(obj_fields,
+ vec(C_int(0),
+ C_int(i)));
+ cx.fcx.llobjfields.insert(f.id, llfield);
+ i += 1;
+ }
+}
+
impure fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
+ option.t[TypeRef] ty_self,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
auto llfndecl = cx.item_ids.get(fid);
cx.item_names.insert(cx.path, llfndecl);
auto fcx = new_fn_ctxt(cx, cx.path, llfndecl);
- create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(ann),
+ create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann),
f.inputs, ty_params);
-
auto bcx = new_top_block_ctxt(fcx);
- copy_args_to_allocas(bcx, f.inputs, arg_tys_of_fn(ann));
+ copy_args_to_allocas(bcx, ty_self, f.inputs,
+ arg_tys_of_fn(ann));
+
+ alt (fcx.llself) {
+ case (some[ValueRef](?llself)) {
+ create_llobjfields_for_fields(bcx, llself);
+ }
+ case (_) {
+ }
+ }
auto res = trans_block(bcx, f.body);
if (!is_terminated(res.bcx)) {
@@ -2507,7 +2577,15 @@ impure fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
&ast._obj ob,
&vec[ast.ty_param] ty_params) -> ValueRef {
let vec[ValueRef] methods = vec();
- for (@ast.method m in ob.methods) {
+
+ fn meth_lteq(&@ast.method a, &@ast.method b) -> bool {
+ ret _str.lteq(a.node.ident, b.node.ident);
+ }
+
+ auto meths = std.sort.merge_sort[@ast.method](bind meth_lteq(_,_),
+ ob.methods);
+
+ for (@ast.method m in meths) {
auto llfnty = T_nil();
alt (node_ann_type(cx, m.node.ann).struct) {
@@ -2518,11 +2596,15 @@ impure fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
}
}
- let str s = cx.names.next("_rust_method") + "." + cx.path;
+ let @crate_ctxt mcx = @rec(path=cx.path + "." + m.node.ident
+ with *cx);
+
+ let str s = cx.names.next("_rust_method") + "." + mcx.path;
let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfnty);
cx.item_ids.insert(m.node.id, llfn);
- trans_fn(cx, m.node.meth, m.node.id, ty_params, m.node.ann);
+ trans_fn(mcx, m.node.meth, m.node.id, some[TypeRef](self_ty),
+ ty_params, m.node.ann);
methods += llfn;
}
auto vtbl = C_struct(methods);
@@ -2556,7 +2638,7 @@ impure fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
auto bcx = new_top_block_ctxt(fcx);
let vec[ty.arg] arg_tys = arg_tys_of_fn(ann);
- copy_args_to_allocas(bcx, fn_args, arg_tys);
+ copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys);
auto llself_ty = type_of(cx, ret_ty_of_fn(ann));
auto pair = bcx.build.Alloca(llself_ty);
@@ -2664,7 +2746,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
auto bcx = new_top_block_ctxt(fcx);
auto arg_tys = arg_tys_of_fn(variant.ann);
- copy_args_to_allocas(bcx, fn_args, arg_tys);
+ copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys);
auto info = cx.tags.get(tag_id);
@@ -2707,10 +2789,11 @@ impure fn trans_item(@crate_ctxt cx, &ast.item item) {
alt (item.node) {
case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
auto sub_cx = @rec(path=cx.path + "." + name with *cx);
- trans_fn(sub_cx, f, fid, tps, ann);
+ trans_fn(sub_cx, f, fid, none[TypeRef], tps, ann);
}
case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) {
- auto sub_cx = @rec(path=cx.path + "." + name with *cx);
+ auto sub_cx = @rec(path=cx.path + "." + name,
+ obj_fields=ob.fields with *cx);
trans_obj(sub_cx, ob, oid, tps, ann);
}
case (ast.item_mod(?name, ?m, _)) {
@@ -2927,6 +3010,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
mutable llself=none[ValueRef],
mutable llretptr=none[ValueRef],
llargs=new_def_hash[ValueRef](),
+ llobjfields=new_def_hash[ValueRef](),
lllocals=new_def_hash[ValueRef](),
lltydescs=new_def_hash[ValueRef](),
ccx=cx);
@@ -3097,6 +3181,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
auto hasher = ty.hash_ty;
auto eqer = ty.eq_ty;
auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer);
+ let vec[ast.obj_field] obj_fields = vec();
auto cx = @rec(sess = sess,
llmod = llmod,
@@ -3108,6 +3193,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
items = new_def_hash[@ast.item](),
tags = new_def_hash[@tag_info](),
tydescs = tydescs,
+ obj_fields = obj_fields,
glues = glues,
names = namegen(0),
path = "_rust");