aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 0db40e89..15fc68e4 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 89055578..03b57024 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 79f57be2..94bd41a6 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;