Skip to content

Commit d74daec

Browse files
committed
---
yaml --- r: 1004 b: refs/heads/master c: 7bdb932 h: refs/heads/master v: v3
1 parent 0fb0190 commit d74daec

File tree

2 files changed

+175
-73
lines changed

2 files changed

+175
-73
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: d922b0ad9c126e416b1d6d68a567e0dcbabbbf29
2+
refs/heads/master: 7bdb93266d3a88e407f7996d374a8364b84b8e01

trunk/src/comp/middle/trans.rs

Lines changed: 174 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import std._str;
2+
import std._uint;
23
import std._vec;
34
import std._str.rustrt.sbuf;
45
import std._vec.rustrt.vbuf;
@@ -387,6 +388,10 @@ fn C_tydesc(TypeRef t) -> ValueRef {
387388
C_null(T_ptr(T_opaque())))); // is_stateful
388389
}
389390

391+
fn C_union(TypeRef ty, ValueRef val) -> ValueRef {
392+
ret llvm.LLVMConstUnion(ty, val);
393+
}
394+
390395
fn decl_fn(ModuleRef llmod, str name, uint cc, TypeRef llty) -> ValueRef {
391396
let ValueRef llfn =
392397
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
@@ -560,10 +565,69 @@ fn iter_structural_ty(@block_ctxt cx,
560565
i += 1;
561566
}
562567
}
568+
case (typeck.ty_tag(?tid)) {
569+
check (cx.fcx.ccx.tags.contains_key(tid));
570+
auto info = cx.fcx.ccx.tags.get(tid);
571+
auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants);
572+
573+
// Look up the tag in the typechecked AST.
574+
check (cx.fcx.ccx.items.contains_key(tid));
575+
auto tag_item = cx.fcx.ccx.items.get(tid);
576+
let vec[ast.variant] variants = vec(); // FIXME: typestate bug
577+
alt (tag_item.node) {
578+
case (ast.item_tag(_, ?vs, _, _)) {
579+
variants = vs;
580+
}
581+
case (_) {
582+
log "trans: ty_tag doesn't actually refer to a tag";
583+
fail;
584+
}
585+
}
586+
587+
auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0)));
588+
auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1)));
589+
auto lldiscrim = cx.build.Load(lldiscrim_ptr);
590+
591+
auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr");
592+
unr_cx.build.Unreachable();
593+
594+
auto llswitch = cx.build.Switch(lldiscrim, unr_cx.llbb,
595+
n_variants);
596+
597+
auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next");
598+
599+
auto i = 0u;
600+
for (tup(ast.def_id,arity) variant in info.variants) {
601+
auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" +
602+
_uint.to_str(i, 10u));
603+
llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb);
604+
605+
alt (variant._1) {
606+
case (n_ary) {
607+
// FIXME: broken at the moment, causes type_is_binding
608+
// errors; need to unpack the fn type returned by
609+
// ann_to_type.
610+
let vec[ValueRef] vals = vec(C_int(0), C_int(1),
611+
C_int(i as int));
612+
auto llfld = r.bcx.build.GEP(v, vals);
613+
auto ty = typeck.ann_to_type(variants.(i).ann);
614+
r = f(variant_cx, llfld, ty);
615+
r.bcx.build.Br(next_cx.llbb);
616+
}
617+
case (nullary) {
618+
// Nothing to do.
619+
variant_cx.build.Br(next_cx.llbb);
620+
}
621+
}
622+
623+
i += 1u;
624+
}
625+
626+
ret res(next_cx, C_nil());
627+
}
563628
case (_) {
564629
cx.fcx.ccx.sess.unimpl("type in iter_structural_ty");
565630
}
566-
// FIXME: handle records and tags when we support them.
567631
}
568632
ret r;
569633
}
@@ -1191,24 +1255,9 @@ fn trans_name(@block_ctxt cx, &ast.name n, &option.t[ast.def] dopt)
11911255
}
11921256
case (ast.def_variant(?tid, ?vid)) {
11931257
check (cx.fcx.ccx.tags.contains_key(tid));
1194-
auto info = cx.fcx.ccx.tags.get(tid);
1195-
auto i = 0;
1196-
for (tup(ast.def_id,arity) v in info.variants) {
1197-
if (vid == v._0) {
1198-
alt (v._1) {
1199-
case (nullary) {
1200-
auto elems = vec(C_int(i));
1201-
ret tup(res(cx, C_struct(elems)), false);
1202-
}
1203-
case (n_ary) {
1204-
cx.fcx.ccx.sess.unimpl("n-ary tag " +
1205-
"constructor in " +
1206-
"trans");
1207-
}
1208-
}
1209-
}
1210-
i += 1;
1211-
}
1258+
check (cx.fcx.ccx.item_ids.contains_key(vid));
1259+
ret tup(res(cx, cx.fcx.ccx.item_ids.get(vid)),
1260+
false);
12121261
}
12131262
case (_) {
12141263
cx.fcx.ccx.sess.unimpl("def variant in trans");
@@ -1791,59 +1840,6 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
17911840
}
17921841

17931842

1794-
fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
1795-
alt (i.node) {
1796-
case (ast.item_tag(_, ?variants, _, ?tag_id)) {
1797-
let vec[TypeRef] variant_tys = vec();
1798-
1799-
auto info = cx.tags.get(tag_id);
1800-
let vec[tup(ast.def_id,arity)] variant_info = vec();
1801-
1802-
auto tag_ty;
1803-
if (_vec.len[ast.variant](variants) == 0u) {
1804-
tag_ty = T_struct(vec(T_int()));
1805-
} else {
1806-
auto n_ary_idx = 0u;
1807-
for (ast.variant variant in variants) {
1808-
auto arity_info;
1809-
if (_vec.len[@ast.ty](variant.args) > 0u) {
1810-
let vec[TypeRef] lltys = vec();
1811-
1812-
alt (typeck.ann_to_type(variant.ann).struct) {
1813-
case (typeck.ty_fn(?args, _)) {
1814-
for (typeck.arg arg in args) {
1815-
lltys += vec(type_of(cx, arg.ty));
1816-
}
1817-
}
1818-
case (_) { fail; }
1819-
}
1820-
1821-
variant_tys += vec(T_struct(lltys));
1822-
arity_info = n_ary;
1823-
} else {
1824-
variant_tys += vec(T_nil());
1825-
arity_info = nullary;
1826-
}
1827-
1828-
variant_info += vec(tup(variant.id, arity_info));
1829-
}
1830-
1831-
tag_ty = T_struct(vec(T_int(), T_union(variant_tys)));
1832-
}
1833-
1834-
info.variants = variant_info;
1835-
1836-
auto th = cx.tags.get(tag_id).th.llth;
1837-
llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty);
1838-
}
1839-
case (_) {
1840-
// fall through
1841-
}
1842-
}
1843-
1844-
ret cx;
1845-
}
1846-
18471843
fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
18481844
alt (i.node) {
18491845
case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) {
@@ -1865,6 +1861,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
18651861
let vec[tup(ast.def_id,arity)] variant_info = vec();
18661862
cx.tags.insert(tag_id, @rec(th=mk_type_handle(),
18671863
mutable variants=variant_info));
1864+
cx.items.insert(tag_id, i);
18681865
}
18691866

18701867
case (_) { /* fall through */ }
@@ -1884,6 +1881,55 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) {
18841881
fold.fold_crate[@crate_ctxt](cx, fld, crate);
18851882
}
18861883

1884+
// The tag type resolution pass, which determines all the LLVM types that
1885+
// correspond to each tag type in the crate.
1886+
1887+
fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
1888+
alt (i.node) {
1889+
case (ast.item_tag(_, ?variants, _, ?tag_id)) {
1890+
let vec[TypeRef] variant_tys = vec();
1891+
1892+
auto info = cx.tags.get(tag_id);
1893+
let vec[tup(ast.def_id,arity)] variant_info = vec();
1894+
1895+
for (ast.variant variant in variants) {
1896+
auto arity_info;
1897+
if (_vec.len[@ast.ty](variant.args) > 0u) {
1898+
let vec[TypeRef] lltys = vec();
1899+
1900+
alt (typeck.ann_to_type(variant.ann).struct) {
1901+
case (typeck.ty_fn(?args, _)) {
1902+
for (typeck.arg arg in args) {
1903+
lltys += vec(type_of(cx, arg.ty));
1904+
}
1905+
}
1906+
case (_) { fail; }
1907+
}
1908+
1909+
variant_tys += vec(T_struct(lltys));
1910+
arity_info = n_ary;
1911+
} else {
1912+
variant_tys += vec(T_nil());
1913+
arity_info = nullary;
1914+
}
1915+
1916+
variant_info += vec(tup(variant.id, arity_info));
1917+
}
1918+
1919+
info.variants = variant_info;
1920+
1921+
auto tag_ty = T_struct(vec(T_int(), T_union(variant_tys)));
1922+
auto th = cx.tags.get(tag_id).th.llth;
1923+
llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty);
1924+
}
1925+
case (_) {
1926+
// fall through
1927+
}
1928+
}
1929+
1930+
ret cx;
1931+
}
1932+
18871933
fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) {
18881934
let fold.ast_fold[@crate_ctxt] fld =
18891935
fold.new_identity_fold[@crate_ctxt]();
@@ -1894,6 +1940,61 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) {
18941940
fold.fold_crate[@crate_ctxt](cx, fld, crate);
18951941
}
18961942

1943+
// The constant translation pass.
1944+
1945+
fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt {
1946+
alt (it.node) {
1947+
case (ast.item_tag(_, ?variants, _, ?tag_id)) {
1948+
auto info = cx.tags.get(tag_id);
1949+
1950+
auto tag_ty = llvm.LLVMResolveTypeHandle(info.th.llth);
1951+
check (llvm.LLVMCountStructElementTypes(tag_ty) == 2u);
1952+
auto elts = vec(0 as TypeRef, 0 as TypeRef);
1953+
llvm.LLVMGetStructElementTypes(tag_ty, _vec.buf[TypeRef](elts));
1954+
auto union_ty = elts.(1);
1955+
1956+
auto i = 0u;
1957+
while (i < _vec.len[tup(ast.def_id,arity)](info.variants)) {
1958+
auto variant_info = info.variants.(i);
1959+
alt (variant_info._1) {
1960+
case (nullary) {
1961+
// Nullary tags become constants.
1962+
auto union_val = C_union(union_ty, C_nil());
1963+
auto val = C_struct(vec(C_int(i as int), union_val));
1964+
1965+
// FIXME: better name
1966+
auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val),
1967+
_str.buf("tag"));
1968+
llvm.LLVMSetInitializer(gvar, val);
1969+
llvm.LLVMSetGlobalConstant(gvar, True);
1970+
cx.item_ids.insert(variant_info._0, gvar);
1971+
}
1972+
case (n_ary) {
1973+
// N-ary tags are treated as functions and generated
1974+
// later.
1975+
}
1976+
}
1977+
1978+
i += 1u;
1979+
}
1980+
}
1981+
case (_) {
1982+
// empty
1983+
}
1984+
}
1985+
1986+
ret cx;
1987+
}
1988+
1989+
fn trans_constants(@crate_ctxt cx, @ast.crate crate) {
1990+
let fold.ast_fold[@crate_ctxt] fld =
1991+
fold.new_identity_fold[@crate_ctxt]();
1992+
1993+
fld = @rec(update_env_for_item = bind trans_constant(_,_) with *fld);
1994+
1995+
fold.fold_crate[@crate_ctxt](cx, fld, crate);
1996+
}
1997+
18971998
fn p2i(ValueRef v) -> ValueRef {
18981999
ret llvm.LLVMConstPtrToInt(v, T_int());
18992000
}
@@ -2060,6 +2161,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
20602161

20612162
collect_items(cx, crate);
20622163
resolve_tag_types(cx, crate);
2164+
trans_constants(cx, crate);
20632165

20642166
trans_mod(cx, crate.node.module);
20652167
trans_exit_task_glue(cx);

0 commit comments

Comments
 (0)