about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2010-12-01 19:03:47 -0800
committerPatrick Walton <pcwalton@mimiga.net>2010-12-01 19:03:47 -0800
commiteeecc8d0617b547520083b9db94ec05f84fbca64 (patch)
treef175cb07047adaab21529180bd4ae2e0a9b65a15 /src/comp
parent98a63bd1f9fda47fc34b16d9f0782022e1022277 (diff)
downloadrust-eeecc8d0617b547520083b9db94ec05f84fbca64.tar.gz
rust-eeecc8d0617b547520083b9db94ec05f84fbca64.zip
rustc: Add stub support for tag constructors in trans
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/lib/llvm.rs13
-rw-r--r--src/comp/middle/trans.rs120
-rw-r--r--src/comp/middle/typeck.rs7
3 files changed, 139 insertions, 1 deletions
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 0db40e89e81..15fc68e4b7f 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -1106,6 +1106,19 @@ obj builder(BuilderRef B) {
     }
 }
 
+/* Memory-managed object interface to type handles. */
+
+obj type_handle_dtor(TypeHandleRef TH) {
+    drop { llvm.LLVMDisposeTypeHandle(TH); }
+}
+
+type type_handle = rec(TypeHandleRef llth, type_handle_dtor dtor);
+
+fn mk_type_handle() -> type_handle {
+    auto th = llvm.LLVMCreateTypeHandle(llvm.LLVMOpaqueType());
+    ret rec(llth=th, dtor=type_handle_dtor(th));
+}
+
 fn type_to_str(TypeRef ty) -> str {
     let int kind = llvm.LLVMGetTypeKind(ty);
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 89055578d55..03b57024cce 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -20,9 +20,12 @@ import util.common.new_str_hash;
 
 import lib.llvm.llvm;
 import lib.llvm.builder;
+import lib.llvm.type_handle;
+import lib.llvm.mk_type_handle;
 import lib.llvm.llvm.ModuleRef;
 import lib.llvm.llvm.ValueRef;
 import lib.llvm.llvm.TypeRef;
+import lib.llvm.llvm.TypeHandleRef;
 import lib.llvm.llvm.BuilderRef;
 import lib.llvm.llvm.BasicBlockRef;
 
@@ -41,6 +44,10 @@ type glue_fns = rec(ValueRef activate_glue,
                     ValueRef exit_task_glue,
                     vec[ValueRef] upcall_glues);
 
+type tag_info = rec(type_handle th,
+                    hashmap[ast.def_id, uint] variant_indices,
+                    hashmap[ast.def_id, uint] n_ary_variant_indices);
+
 state type crate_ctxt = rec(session.session sess,
                             ModuleRef llmod,
                             hashmap[str, ValueRef] upcalls,
@@ -48,6 +55,7 @@ state type crate_ctxt = rec(session.session sess,
                             hashmap[str, ValueRef] fn_names,
                             hashmap[ast.def_id, ValueRef] fn_ids,
                             hashmap[ast.def_id, @ast.item] items,
+                            hashmap[ast.def_id, tag_info] tags,
                             @glue_fns glues,
                             namegen names,
                             str path);
@@ -177,6 +185,11 @@ fn T_struct(vec[TypeRef] elts) -> TypeRef {
                             False);
 }
 
+fn T_union(vec[TypeRef] elts) -> TypeRef {
+    ret llvm.LLVMUnionType(_vec.buf[TypeRef](elts),
+                           _vec.len[TypeRef](elts));
+}
+
 fn T_opaque() -> TypeRef {
     ret llvm.LLVMOpaqueType();
 }
@@ -267,6 +280,9 @@ fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef {
         }
         case (typeck.ty_char) { ret T_char(); }
         case (typeck.ty_str) { ret T_ptr(T_str()); }
+        case (typeck.ty_tag(?tag_id)) {
+            ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth);
+        }
         case (typeck.ty_box(?t)) {
             ret T_ptr(T_box(type_of(cx, t)));
         }
@@ -1114,6 +1130,19 @@ fn trans_name(@block_ctxt cx, &ast.name n, &option.t[ast.def] dopt)
                     ret tup(res(cx, cx.fcx.ccx.fn_ids.get(did)),
                             false);
                 }
+                case (ast.def_variant(?tid, ?vid)) {
+                    check (cx.fcx.ccx.tags.contains_key(tid));
+                    auto info = cx.fcx.ccx.tags.get(tid);
+                    if (info.n_ary_variant_indices.contains_key(vid)) {
+                        cx.fcx.ccx.sess.unimpl("n-ary tag constructors in " +
+                                               "trans");
+                    } else {
+                        // Nullary tag variant case.
+                        auto idx = info.variant_indices.get(vid);
+                        auto elems = vec(C_int(idx as int));
+                        ret tup(res(cx, C_struct(elems)), false);
+                    }
+                }
                 case (_) {
                     cx.fcx.ccx.sess.unimpl("def variant in trans");
                 }
@@ -1645,6 +1674,15 @@ impure fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
     }
 }
 
+fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
+                     &ast.variant variant) {
+    if (_vec.len[@ast.ty](variant.args) == 0u) {
+        ret;    // nullary constructors are just constants
+    }
+
+    // TODO
+}
+
 impure fn trans_item(@crate_ctxt cx, &ast.item item) {
     alt (item.node) {
         case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) {
@@ -1655,6 +1693,12 @@ impure fn trans_item(@crate_ctxt cx, &ast.item item) {
             auto sub_cx = @rec(path=cx.path + "." + name with *cx);
             trans_mod(sub_cx, m);
         }
+        case (ast.item_tag(?name, ?variants, _, ?tag_id)) {
+            auto sub_cx = @rec(path=cx.path + "." + name with *cx);
+            for (ast.variant variant in variants) {
+                trans_tag_variant(sub_cx, tag_id, variant);
+            }
+        }
         case (_) { /* fall through */ }
     }
 }
@@ -1666,6 +1710,60 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
 }
 
 
+fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
+    alt (i.node) {
+        case (ast.item_tag(_, ?variants, _, ?tag_id)) {
+            let vec[TypeRef] variant_tys = vec();
+
+            auto info = cx.tags.get(tag_id);
+            auto variant_indices = info.variant_indices;
+            auto n_ary_variant_indices = info.n_ary_variant_indices;
+
+            auto tag_ty;
+            if (_vec.len[ast.variant](variants) == 0u) {
+                tag_ty = T_struct(vec(T_int()));
+            } else {
+                auto variant_idx = 0u;
+                auto n_ary_variant_idx = 0u;
+
+                for (ast.variant variant in variants) {
+                    if (_vec.len[@ast.ty](variant.args) > 0u) {
+                        let vec[TypeRef] lltys = vec();
+
+                        alt (typeck.ann_to_type(variant.ann).struct) {
+                            case (typeck.ty_fn(?args, _)) {
+                                for (typeck.arg arg in args) {
+                                    lltys += vec(type_of(cx, arg.ty));
+                                }
+                            }
+                            case (_) { fail; }
+                        }
+
+                        variant_tys += vec(T_struct(lltys));
+
+                        n_ary_variant_indices.insert(variant.id,
+                                                     n_ary_variant_idx);
+                        n_ary_variant_idx += 1u;
+                    }
+
+                    variant_indices.insert(variant.id, variant_idx);
+                    variant_idx += 1u;
+                }
+
+                tag_ty = T_struct(vec(T_int(), T_union(variant_tys)));
+            }
+
+            auto th = cx.tags.get(tag_id).th.llth;
+            llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty);
+        }
+        case (_) {
+            // fall through
+        }
+    }
+
+    ret cx;
+}
+
 fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
     alt (i.node) {
         case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) {
@@ -1680,6 +1778,15 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
         case (ast.item_mod(?name, ?m, ?mid)) {
             cx.items.insert(mid, i);
         }
+
+        case (ast.item_tag(_, ?variants, _, ?tag_id)) {
+            auto vi = new_def_hash[uint]();
+            auto navi = new_def_hash[uint]();
+            cx.tags.insert(tag_id, rec(th=mk_type_handle(),
+                                       variant_indices=vi,
+                                       n_ary_variant_indices=navi));
+        }
+
         case (_) { /* fall through */ }
     }
     ret cx;
@@ -1697,6 +1804,16 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) {
     fold.fold_crate[@crate_ctxt](cx, fld, crate);
 }
 
+fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) {
+    let fold.ast_fold[@crate_ctxt] fld =
+        fold.new_identity_fold[@crate_ctxt]();
+
+    fld = @rec( update_env_for_item = bind resolve_tag_types_for_item(_,_)
+                with *fld );
+
+    fold.fold_crate[@crate_ctxt](cx, fld, crate);
+}
+
 fn p2i(ValueRef v) -> ValueRef {
     ret llvm.LLVMConstPtrToInt(v, T_int());
 }
@@ -1856,11 +1973,14 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
                    fn_names = new_str_hash[ValueRef](),
                    fn_ids = new_def_hash[ValueRef](),
                    items = new_def_hash[@ast.item](),
+                   tags = new_def_hash[tag_info](),
                    glues = glues,
                    names = namegen(0),
                    path = "_rust");
 
     collect_items(cx, crate);
+    resolve_tag_types(cx, crate);
+
     trans_mod(cx, crate.node.module);
     trans_exit_task_glue(cx);
     trans_main_fn(cx, crate_constant(cx));
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 79f57be2ae1..94bd41a674f 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -203,6 +203,11 @@ fn ty_to_str(&@ty typ) -> str {
             s = "rec(" + _str.connect(strs, ",") + ")";
         }
 
+        case (ty_tag(_)) {
+            // The user should never see this if the cname is set properly!
+            s = "<tag>";
+        }
+
         case (ty_fn(?inputs, ?output)) {
             auto f = fn_input_to_str;
             s = "fn(" + _str.connect(_vec.map[arg,str](f, inputs),
@@ -550,9 +555,9 @@ fn type_is_nil(@ty t) -> bool {
 
 fn type_is_structural(@ty t) -> bool {
     alt (t.struct) {
-        // FIXME: cover tag when we support it.
         case (ty_tup(_)) { ret true; }
         case (ty_rec(_)) { ret true; }
+        case (ty_tag(_)) { ret true; }
         case (_) { ret false; }
     }
     fail;