@@ -7,6 +7,11 @@ import std::map::hashmap;
77
88import ty:: * ;
99
10+ export type_of;
11+ export type_of_explicit_args;
12+ export type_of_fn_from_ty;
13+ export type_of_fn;
14+
1015fn type_of_explicit_args ( cx : @crate_ctxt , inputs : [ ty:: arg ] ) -> [ TypeRef ] {
1116 vec:: map ( inputs) { |arg|
1217 let arg_ty = arg. ty ;
@@ -39,93 +44,149 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
3944
4045fn type_of ( cx : @crate_ctxt , t : ty:: t ) -> TypeRef {
4146 assert !ty:: type_has_vars ( t) ;
42- // Check the cache.
4347
48+ #debug ( "type_of %?: %?" , t, ty:: get ( t) ) ;
49+
50+ // Check the cache.
4451 if cx. lltypes . contains_key ( t) { ret cx. lltypes . get ( t) ; }
45- let llty = alt ty:: get ( t) . struct {
46- ty:: ty_nil | ty:: ty_bot { T_nil ( ) }
47- ty:: ty_bool { T_bool ( ) }
48- ty:: ty_int ( t) { T_int_ty ( cx, t) }
49- ty:: ty_uint ( t) { T_uint_ty ( cx, t) }
50- ty:: ty_float ( t) { T_float_ty ( cx, t) }
51- ty:: ty_estr ( ty:: vstore_uniq) |
52- ty:: ty_str { T_ptr ( T_vec ( cx, T_i8 ( ) ) ) }
53- ty:: ty_enum ( did, _) { type_of_enum ( cx, did, t) }
54- ty:: ty_estr ( ty:: vstore_box) { T_ptr ( T_box ( cx, T_i8 ( ) ) ) }
55- ty:: ty_evec ( mt, ty:: vstore_box) |
56- ty:: ty_box ( mt) { T_ptr ( T_box ( cx, type_of ( cx, mt. ty ) ) ) }
57- ty:: ty_opaque_box { T_ptr ( T_box ( cx, T_i8 ( ) ) ) }
58- ty:: ty_uniq ( mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
59- ty:: ty_evec ( mt, ty:: vstore_uniq) |
60- ty:: ty_vec ( mt) { T_ptr ( T_vec ( cx, type_of ( cx, mt. ty ) ) ) }
61- ty:: ty_ptr ( mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
62- ty:: ty_rptr ( _, mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
63-
64- ty:: ty_evec ( mt, ty:: vstore_slice ( _) ) {
65- T_struct ( [ T_ptr ( type_of ( cx, mt. ty ) ) ,
66- T_uint_ty ( cx, ast:: ty_u) ] )
67- }
6852
69- ty:: ty_estr ( ty:: vstore_slice ( _) ) {
70- T_struct ( [ T_ptr ( T_i8 ( ) ) ,
71- T_uint_ty ( cx, ast:: ty_u) ] )
72- }
53+ // Replace any typedef'd types with their equivalent non-typedef
54+ // type. This ensures that all LLVM nominal types that contain
55+ // Rust types are defined as the same LLVM types. If we don't do
56+ // this then, e.g. `option<{myfield: bool}>` would be a different
57+ // type than `option<myrec>`.
58+ let t_norm = ty:: normalize_ty ( cx. tcx , t) ;
59+ let llty = if t != t_norm {
60+ type_of ( cx, t_norm)
61+ } else {
62+ alt ty:: get ( t) . struct {
63+ ty:: ty_nil | ty:: ty_bot { T_nil ( ) }
64+ ty:: ty_bool { T_bool ( ) }
65+ ty:: ty_int ( t) { T_int_ty ( cx, t) }
66+ ty:: ty_uint ( t) { T_uint_ty ( cx, t) }
67+ ty:: ty_float ( t) { T_float_ty ( cx, t) }
68+ ty:: ty_estr ( ty:: vstore_uniq) |
69+ ty:: ty_str { T_ptr ( T_vec ( cx, T_i8 ( ) ) ) }
70+ ty:: ty_enum ( did, _) { type_of_enum ( cx, did, t) }
71+ ty:: ty_estr ( ty:: vstore_box) { T_ptr ( T_box ( cx, T_i8 ( ) ) ) }
72+ ty:: ty_evec ( mt, ty:: vstore_box) |
73+ ty:: ty_box ( mt) { T_ptr ( T_box ( cx, type_of ( cx, mt. ty ) ) ) }
74+ ty:: ty_opaque_box { T_ptr ( T_box ( cx, T_i8 ( ) ) ) }
75+ ty:: ty_uniq ( mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
76+ ty:: ty_evec ( mt, ty:: vstore_uniq) |
77+ ty:: ty_vec ( mt) { T_ptr ( T_vec ( cx, type_of ( cx, mt. ty ) ) ) }
78+ ty:: ty_ptr ( mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
79+ ty:: ty_rptr ( _, mt) { T_ptr ( type_of ( cx, mt. ty ) ) }
7380
74- ty:: ty_estr ( ty:: vstore_fixed ( n) ) {
75- T_array ( T_i8 ( ) , n + 1 u /* +1 for trailing null */ )
76- }
81+ ty:: ty_evec ( mt, ty:: vstore_slice ( _) ) {
82+ T_struct ( [ T_ptr ( type_of ( cx, mt. ty ) ) ,
83+ T_uint_ty ( cx, ast:: ty_u) ] )
84+ }
7785
78- ty:: ty_evec ( mt, ty:: vstore_fixed ( n) ) {
79- T_array ( type_of ( cx, mt. ty ) , n)
80- }
86+ ty:: ty_estr ( ty:: vstore_slice ( _) ) {
87+ T_struct ( [ T_ptr ( T_i8 ( ) ) ,
88+ T_uint_ty ( cx, ast:: ty_u) ] )
89+ }
8190
82- ty:: ty_rec ( fields) {
83- let mut tys: [ TypeRef ] = [ ] ;
84- for vec:: each( fields) { |f|
85- let mt_ty = f. mt. ty;
86- tys += [ type_of( cx, mt_ty) ] ;
87- }
88- T_struct ( tys)
89- }
90- ty:: ty_fn ( _) { T_fn_pair ( cx, type_of_fn_from_ty ( cx, t) ) }
91- ty:: ty_iface ( _, _) { T_opaque_iface ( cx) }
92- ty:: ty_res ( _, sub, substs) {
93- let sub1 = ty:: subst ( cx. tcx , substs, sub) ;
94- ret T_struct ( [ T_i8 ( ) , type_of ( cx, sub1) ] ) ;
95- }
96- ty:: ty_param ( _, _) { T_typaram ( cx. tn ) }
97- ty:: ty_type { T_ptr ( cx. tydesc_type ) }
98- ty:: ty_tup ( elts) {
99- let mut tys = [ ] ;
100- for vec:: each( elts) { |elt|
101- tys += [ type_of ( cx, elt) ] ;
91+ ty:: ty_estr ( ty:: vstore_fixed ( n) ) {
92+ T_array ( T_i8 ( ) , n + 1 u /* +1 for trailing null */ )
93+ }
94+
95+ ty:: ty_evec ( mt, ty:: vstore_fixed ( n) ) {
96+ T_array ( type_of ( cx, mt. ty ) , n)
97+ }
98+
99+ ty:: ty_rec ( fields) {
100+ let mut tys: [ TypeRef ] = [ ] ;
101+ for vec:: each( fields) { |f|
102+ let mt_ty = f. mt. ty;
103+ tys += [ type_of( cx, mt_ty) ] ;
104+ }
105+ T_struct ( tys)
106+ }
107+ ty:: ty_fn ( _) { T_fn_pair ( cx, type_of_fn_from_ty ( cx, t) ) }
108+ ty:: ty_iface ( _, _) { T_opaque_iface ( cx) }
109+ ty:: ty_res ( _, sub, substs) {
110+ let sub1 = ty:: subst ( cx. tcx , substs, sub) ;
111+ ret T_struct ( [ T_i8 ( ) , type_of ( cx, sub1) ] ) ;
112+ }
113+ ty:: ty_param ( _, _) { T_typaram ( cx. tn ) }
114+ ty:: ty_type { T_ptr ( cx. tydesc_type ) }
115+ ty:: ty_tup ( elts) {
116+ let mut tys = [ ] ;
117+ for vec:: each( elts) { |elt|
118+ tys += [ type_of ( cx, elt) ] ;
119+ }
120+ T_struct ( tys)
121+ }
122+ ty:: ty_opaque_closure_ptr ( _) { T_opaque_box_ptr ( cx) }
123+ ty:: ty_constr ( subt, _) { type_of ( cx, subt) }
124+ ty:: ty_class ( did, ts) {
125+ // only instance vars are record fields at runtime
126+ let fields = lookup_class_fields ( cx. tcx , did) ;
127+ let tys = vec:: map ( fields) { |f|
128+ let t = ty:: lookup_field_type ( cx. tcx , did, f. id , ts) ;
129+ type_of ( cx, t)
130+ } ;
131+ T_struct ( tys)
132+ }
133+ ty:: ty_self ( _) { cx. tcx . sess . unimpl ( "type_of: ty_self \
134+ not implemented") ; }
135+ ty:: ty_var ( _) { cx. tcx . sess . bug ( "type_of shouldn't see a ty_var" ) ; }
102136 }
103- T_struct ( tys)
104- }
105- ty:: ty_opaque_closure_ptr ( _) { T_opaque_box_ptr ( cx) }
106- ty:: ty_constr ( subt, _) { type_of ( cx, subt) }
107- ty:: ty_class ( did, ts) {
108- // only instance vars are record fields at runtime
109- let fields = lookup_class_fields ( cx. tcx , did) ;
110- let tys = vec:: map ( fields) { |f|
111- let t = ty:: lookup_field_type ( cx. tcx , did, f. id , ts) ;
112- type_of ( cx, t)
113- } ;
114- T_struct ( tys)
115- }
116- ty:: ty_self ( _) { cx. tcx . sess . unimpl ( "type_of: ty_self \
117- not implemented") ; }
118- ty:: ty_var ( _) { cx. tcx . sess . bug ( "type_of shouldn't see a ty_var" ) ; }
119137 } ;
120138 cx. lltypes . insert ( t, llty) ;
121139 ret llty;
122140}
123141
142+ // This should only be called from type_of, above, because it
143+ // creates new llvm named struct types lazily that are then
144+ // cached by type_of
124145fn type_of_enum ( cx : @crate_ctxt , did : ast:: def_id , t : ty:: t )
125146 -> TypeRef {
126- let degen = ( * ty:: enum_variants ( cx. tcx , did) ) . len ( ) == 1 u;
127- let size = shape:: static_size_of_enum ( cx, t) ;
128- if !degen { T_enum ( cx, size) }
129- else if size == 0 u { T_struct ( [ T_enum_variant ( cx) ] ) }
130- else { T_array ( T_i8 ( ) , size) }
147+
148+ #debug ( "type_of_enum %?: %?" , t, ty:: get ( t) ) ;
149+
150+ // Every enum type has a unique name. When we find our roots
151+ // for GC and unwinding we will use this name to rediscover
152+ // the Rust type
153+ let name = llvm_type_name ( cx, t) ;
154+
155+ let named_llty = common:: T_named_struct ( name) ;
156+
157+ let lltys = {
158+ let degen = ( * ty:: enum_variants ( cx. tcx , did) ) . len ( ) == 1 u;
159+ let size = shape:: static_size_of_enum ( cx, t) ;
160+ if !degen {
161+ [ T_enum_variant ( cx) , T_array ( T_i8 ( ) , size) ]
162+ }
163+ else if size == 0 u {
164+ [ T_enum_variant ( cx) ]
165+ }
166+ else {
167+ [ T_array ( T_i8 ( ) , size) ]
168+ }
169+ } ;
170+
171+ common:: set_struct_body ( named_llty, lltys) ;
172+ ret named_llty;
131173}
174+
175+ fn llvm_type_name ( cx : @crate_ctxt , t : ty:: t ) -> str {
176+ let ( name, did, tps) = alt check ty:: get ( t) . struct {
177+ ty:: ty_enum ( did, substs) {
178+ ( "enum" , did, substs. tps )
179+ }
180+ } ;
181+ ret #fmt(
182+ "%s %s[#%d]" ,
183+ name,
184+ util:: ppaux:: parameterized (
185+ cx. tcx ,
186+ ty:: item_path_str ( cx. tcx , did) ,
187+ none,
188+ tps) ,
189+ did. crate
190+ ) ;
191+ }
192+
0 commit comments