1
1
import std. _str ;
2
+ import std. _uint ;
2
3
import std. _vec ;
3
4
import std. _str . rustrt . sbuf ;
4
5
import std. _vec . rustrt . vbuf ;
@@ -387,6 +388,10 @@ fn C_tydesc(TypeRef t) -> ValueRef {
387
388
C_null ( T_ptr ( T_opaque ( ) ) ) ) ) ; // is_stateful
388
389
}
389
390
391
+ fn C_union ( TypeRef ty, ValueRef val) -> ValueRef {
392
+ ret llvm. LLVMConstUnion ( ty, val) ;
393
+ }
394
+
390
395
fn decl_fn ( ModuleRef llmod, str name , uint cc, TypeRef llty) -> ValueRef {
391
396
let ValueRef llfn =
392
397
llvm. LLVMAddFunction ( llmod, _str. buf ( name) , llty) ;
@@ -560,10 +565,69 @@ fn iter_structural_ty(@block_ctxt cx,
560
565
i += 1 ;
561
566
}
562
567
}
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 = 0 u;
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, 10 u) ) ;
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 += 1 u;
624
+ }
625
+
626
+ ret res( next_cx, C_nil ( ) ) ;
627
+ }
563
628
case ( _) {
564
629
cx. fcx . ccx . sess . unimpl ( "type in iter_structural_ty" ) ;
565
630
}
566
- // FIXME: handle records and tags when we support them.
567
631
}
568
632
ret r;
569
633
}
@@ -1191,24 +1255,9 @@ fn trans_name(@block_ctxt cx, &ast.name n, &option.t[ast.def] dopt)
1191
1255
}
1192
1256
case ( ast. def_variant ( ?tid, ?vid) ) {
1193
1257
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 ) ;
1212
1261
}
1213
1262
case ( _) {
1214
1263
cx. fcx . ccx . sess . unimpl ( "def variant in trans" ) ;
@@ -1791,59 +1840,6 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
1791
1840
}
1792
1841
1793
1842
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) == 0 u) {
1804
- tag_ty = T_struct ( vec ( T_int ( ) ) ) ;
1805
- } else {
1806
- auto n_ary_idx = 0 u;
1807
- for ( ast. variant variant in variants) {
1808
- auto arity_info;
1809
- if ( _vec. len [ @ast. ty ] ( variant. args ) > 0 u) {
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
-
1847
1843
fn collect_item ( & @crate_ctxt cx , @ast. item i ) -> @crate_ctxt {
1848
1844
alt ( i. node ) {
1849
1845
case ( ast. item_fn ( ?name, ?f, _, ?fid, ?ann) ) {
@@ -1865,6 +1861,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
1865
1861
let vec[ tup ( ast. def_id , arity) ] variant_info = vec ( ) ;
1866
1862
cx. tags . insert ( tag_id, @rec ( th=mk_type_handle ( ) ,
1867
1863
mutable variants=variant_info) ) ;
1864
+ cx. items . insert ( tag_id, i) ;
1868
1865
}
1869
1866
1870
1867
case ( _) { /* fall through */ }
@@ -1884,6 +1881,55 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) {
1884
1881
fold. fold_crate [ @crate_ctxt] ( cx, fld, crate ) ;
1885
1882
}
1886
1883
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 ) > 0 u) {
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
+
1887
1933
fn resolve_tag_types ( @crate_ctxt cx , @ast. crate crate) {
1888
1934
let fold. ast_fold[ @crate_ctxt] fld =
1889
1935
fold. new_identity_fold [ @crate_ctxt] ( ) ;
@@ -1894,6 +1940,61 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) {
1894
1940
fold. fold_crate [ @crate_ctxt] ( cx, fld, crate ) ;
1895
1941
}
1896
1942
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) == 2 u) ;
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 = 0 u;
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 += 1 u;
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
+
1897
1998
fn p2i ( ValueRef v) -> ValueRef {
1898
1999
ret llvm. LLVMConstPtrToInt ( v, T_int ( ) ) ;
1899
2000
}
@@ -2060,6 +2161,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
2060
2161
2061
2162
collect_items ( cx, crate ) ;
2062
2163
resolve_tag_types ( cx, crate ) ;
2164
+ trans_constants ( cx, crate ) ;
2063
2165
2064
2166
trans_mod ( cx, crate . node. module ) ;
2065
2167
trans_exit_task_glue ( cx) ;
0 commit comments