diff options
| -rw-r--r-- | src/comp/lib/llvm.rs | 13 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 120 | ||||
| -rw-r--r-- | src/comp/middle/typeck.rs | 7 |
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; |