@@ -7,6 +7,11 @@ import std::map::hashmap;
7
7
8
8
import ty:: * ;
9
9
10
+ export type_of;
11
+ export type_of_explicit_args;
12
+ export type_of_fn_from_ty;
13
+ export type_of_fn;
14
+
10
15
fn type_of_explicit_args ( cx : @crate_ctxt , inputs : [ ty:: arg ] ) -> [ TypeRef ] {
11
16
vec:: map ( inputs) { |arg|
12
17
let arg_ty = arg. ty ;
@@ -39,93 +44,149 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
39
44
40
45
fn type_of ( cx : @crate_ctxt , t : ty:: t ) -> TypeRef {
41
46
assert !ty:: type_has_vars ( t) ;
42
- // Check the cache.
43
47
48
+ #debug ( "type_of %?: %?" , t, ty:: get ( t) ) ;
49
+
50
+ // Check the cache.
44
51
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
- }
68
52
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 ) ) }
73
80
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
+ }
77
85
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
+ }
81
90
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" ) ; }
102
136
}
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" ) ; }
119
137
} ;
120
138
cx. lltypes . insert ( t, llty) ;
121
139
ret llty;
122
140
}
123
141
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
124
145
fn type_of_enum ( cx : @crate_ctxt , did : ast:: def_id , t : ty:: t )
125
146
-> 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;
131
173
}
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