@@ -5,38 +5,8 @@ import option::{some, none};
5
5
import syntax:: { ast, ast_util} ;
6
6
import metadata:: csearch;
7
7
import back:: link;
8
- import lib:: llvm:: llvm;
9
- import llvm:: { ValueRef , TypeRef , LLVMGetParam } ;
10
-
11
- // Translation functionality related to impls and ifaces
12
- //
13
- // Terminology:
14
- // vtable: a table of function pointers pointing to method wrappers
15
- // of an impl that implements an iface
16
- // dict: a record containing a vtable pointer along with pointers to
17
- // all tydescs and other dicts needed to run methods in this vtable
18
- // (i.e. corresponding to the type parameters of the impl)
19
- // wrapper: a function that takes a dict as first argument, along
20
- // with the method-specific tydescs for a method (and all
21
- // other args the method expects), which fetches the extra
22
- // tydescs and dicts from the dict, splices them into the
23
- // arglist, and calls through to the actual method
24
- //
25
- // Generic functions take, along with their normal arguments, a number
26
- // of extra tydesc and dict arguments -- one tydesc for each type
27
- // parameter, one dict (following the tydesc in the arg order) for
28
- // each interface bound on a type parameter.
29
- //
30
- // Most dicts are completely static, and are allocated and filled at
31
- // compile time. Dicts that depend on run-time values (tydescs or
32
- // dicts for type parameter types) are built at run-time, and interned
33
- // through upcall_intern_dict in the runtime. This means that dict
34
- // pointers are self-contained things that do not need to be cleaned
35
- // up.
36
- //
37
- // The trans_constants pass in trans.rs outputs the vtables. Typeck
38
- // annotates notes with information about the methods and dicts that
39
- // are referenced (ccx.method_map and ccx.dict_map).
8
+ import lib:: llvm;
9
+ import llvm:: llvm:: { ValueRef , TypeRef , LLVMGetParam } ;
40
10
41
11
fn trans_impl ( cx : @local_ctxt , name : ast:: ident , methods : [ @ast:: method ] ,
42
12
id : ast:: node_id , tps : [ ast:: ty_param ] ) {
@@ -85,8 +55,7 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
85
55
let generic = none;
86
56
if vec:: len ( * method. tps ) > 0 u {
87
57
let tydescs = [ ] , tis = [ ] ;
88
- let tptys = ty:: node_id_to_type_params ( tcx, e. id ) ;
89
- for t in vec:: tail_n ( tptys, vec:: len ( tptys) - vec:: len ( * method. tps ) ) {
58
+ for t in ty:: node_id_to_type_params ( tcx, e. id ) {
90
59
// TODO: Doesn't always escape.
91
60
let ti = none;
92
61
let td = get_tydesc ( bcx, t, true , tps_normal, ti) . result ;
@@ -106,18 +75,18 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
106
75
}
107
76
108
77
fn llfn_arg_tys ( ft : TypeRef ) -> { inputs : [ TypeRef ] , output : TypeRef } {
109
- let out_ty = llvm:: LLVMGetReturnType ( ft) ;
110
- let n_args = llvm:: LLVMCountParamTypes ( ft) ;
78
+ let out_ty = llvm:: llvm :: LLVMGetReturnType ( ft) ;
79
+ let n_args = llvm:: llvm :: LLVMCountParamTypes ( ft) ;
111
80
let args = vec:: init_elt ( 0 as TypeRef , n_args) ;
112
- unsafe { llvm:: LLVMGetParamTypes ( ft, vec:: to_ptr ( args) ) ; }
81
+ unsafe { llvm:: llvm :: LLVMGetParamTypes ( ft, vec:: to_ptr ( args) ) ; }
113
82
{ inputs: args, output: out_ty}
114
83
}
115
84
116
85
fn trans_wrapper( ccx : @crate_ctxt , pt : [ ast:: ident ] ,
117
86
extra_tps : [ ty:: param_bounds ] , m : @ast:: method ) -> ValueRef {
118
87
let real_fn = ccx. item_ids . get ( m. id ) ;
119
88
let { inputs: real_args , output: real_ret} =
120
- llfn_arg_tys ( llvm:: LLVMGetElementType ( val_ty ( real_fn) ) ) ;
89
+ llfn_arg_tys ( llvm:: llvm :: LLVMGetElementType ( val_ty ( real_fn) ) ) ;
121
90
let extra_ptrs = [ ] ;
122
91
for tp in extra_tps {
123
92
extra_ptrs += [ T_ptr ( ccx. tydesc_type ) ] ;
@@ -151,7 +120,7 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
151
120
args += [ load_inbounds ( bcx, dict, [ 0 , i as int ] ) ] ;
152
121
}
153
122
// the rest of the parameters
154
- let i = 3 u, params_total = llvm:: LLVMCountParamTypes ( llfn_ty) ;
123
+ let i = 3 u, params_total = llvm:: llvm :: LLVMCountParamTypes ( llfn_ty) ;
155
124
while i < params_total {
156
125
args += [ LLVMGetParam ( llfn, i) ] ;
157
126
i += 1 u;
@@ -162,88 +131,9 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
162
131
ret llfn;
163
132
}
164
133
165
- fn dict_is_static ( tcx : ty:: ctxt , origin : typeck:: dict_origin ) -> bool {
166
- alt origin {
167
- typeck : : dict_static ( _, ts, origs) {
168
- vec:: all ( ts, { |t| !ty:: type_contains_params ( tcx, t) } ) &&
169
- vec:: all ( * origs, { |o| dict_is_static ( tcx, o) } )
170
- }
171
- typeck:: dict_param ( _, _) { false }
172
- }
173
- }
174
-
134
+ // FIXME[impl] cache these on the function level somehow
175
135
fn get_dict( bcx : @block_ctxt , origin : typeck:: dict_origin ) -> result {
176
- let ccx = bcx_ccx ( bcx) ;
177
- alt origin {
178
- typeck : : dict_static ( impl_did, tys, sub_origins) {
179
- if dict_is_static ( ccx. tcx , origin) {
180
- ret rslt ( bcx, get_static_dict ( bcx, origin) ) ;
181
- }
182
- let { bcx, ptrs} = get_dict_ptrs ( bcx, origin) ;
183
- let pty = T_ptr ( T_i8 ( ) ) , dict_ty = T_array ( pty, vec:: len ( ptrs) ) ;
184
- let dict = alloca ( bcx, dict_ty) , i = 0 ;
185
- for ptr in ptrs {
186
- Store ( bcx, PointerCast ( bcx, ptr, pty) , GEPi ( bcx, dict, [ 0 , i] ) ) ;
187
- i += 1 ;
188
- }
189
- dict = Call ( bcx, ccx. upcalls . intern_dict ,
190
- [ C_uint ( ccx, vec:: len ( ptrs) ) ,
191
- PointerCast ( bcx, dict, T_ptr ( T_dict ( ) ) ) ] ) ;
192
- rslt ( bcx, dict)
193
- }
194
- typeck:: dict_param( n_param, n_bound) {
195
- rslt( bcx, option : : get ( bcx. fcx . lltyparams [ n_param] . dicts ) [ n_bound] )
196
- }
197
- }
198
- }
199
-
200
- fn dict_id ( tcx : ty:: ctxt , origin : typeck:: dict_origin ) -> dict_id {
201
- alt origin {
202
- typeck : : dict_static ( did, ts, origs) {
203
- let d_params = [ ] , orig = 0 u;
204
- if vec:: len ( ts) == 0 u { ret @{ impl_def : did, params : d_params} ; }
205
- let impl_params = ty:: lookup_item_type ( tcx, did) . bounds ;
206
- vec:: iter2 ( ts, * impl_params) { |t, bounds|
207
- d_params += [ dict_param_ty ( t) ] ;
208
- for bound in * bounds {
209
- alt bound {
210
- ty : : bound_iface ( _) {
211
- d_params += [ dict_param_dict ( dict_id ( tcx, origs[ orig] ) ) ] ;
212
- orig += 1 u;
213
- }
214
- }
215
- }
216
- }
217
- @{ impl_def: did, params: d_params}
218
- }
219
- }
220
- }
221
-
222
- fn get_static_dict ( bcx : @block_ctxt , origin : typeck:: dict_origin )
223
- -> ValueRef {
224
- let ccx = bcx_ccx ( bcx) ;
225
- let id = dict_id ( ccx. tcx , origin) ;
226
- alt ccx. dicts . find ( id) {
227
- some ( d) { ret d; }
228
- none. { }
229
- }
230
- let ptrs = C_struct ( get_dict_ptrs ( bcx, origin) . ptrs ) ;
231
- let name = ccx. names . next ( "dict" ) ;
232
- let gvar = str:: as_buf ( name, { |buf|
233
- llvm:: LLVMAddGlobal ( ccx. llmod , val_ty ( ptrs) , buf)
234
- } ) ;
235
- llvm:: LLVMSetGlobalConstant ( gvar, lib:: llvm:: True ) ;
236
- llvm:: LLVMSetInitializer ( gvar, ptrs) ;
237
- llvm:: LLVMSetLinkage ( gvar,
238
- lib:: llvm:: LLVMInternalLinkage as llvm:: Linkage ) ;
239
- let cast = llvm:: LLVMConstPointerCast ( gvar, T_ptr ( T_dict ( ) ) ) ;
240
- ccx. dicts . insert ( id, cast) ;
241
- cast
242
- }
243
-
244
- fn get_dict_ptrs( bcx : @block_ctxt , origin : typeck:: dict_origin )
245
- -> { bcx : @block_ctxt , ptrs : [ ValueRef ] } {
246
- let ccx = bcx_ccx ( bcx) ;
136
+ let bcx = bcx, ccx = bcx_ccx ( bcx) ;
247
137
alt origin {
248
138
typeck : : dict_static ( impl_did, tys, sub_origins) {
249
139
let vtable = if impl_did. crate == ast:: local_crate {
@@ -253,9 +143,9 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
253
143
get_extern_const ( ccx. externs , ccx. llmod , name, T_ptr ( T_i8 ( ) ) )
254
144
} ;
255
145
let impl_params = ty:: lookup_item_type ( ccx. tcx , impl_did) . bounds ;
256
- let ptrs = [ vtable] , origin = 0 u, ti = none , bcx = bcx ;
257
- vec :: iter2 ( * impl_params, tys ) { |param , ty|
258
- let rslt = get_tydesc ( bcx, ty , true , tps_normal, ti) . result ;
146
+ let ptrs = [ vtable] , i = 0 u, origin = 0 u , ti = none ;
147
+ for param in * impl_params {
148
+ let rslt = get_tydesc ( bcx, tys [ i ] , false , tps_normal, ti) . result ;
259
149
ptrs += [ rslt. val ] ;
260
150
bcx = rslt. bcx ;
261
151
for bound in * param {
@@ -269,8 +159,18 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
269
159
_ { }
270
160
}
271
161
}
162
+ i += 1 u;
272
163
}
273
- { bcx: bcx, ptrs: ptrs}
164
+ let pty = T_ptr ( T_i8 ( ) ) , dict_ty = T_array ( pty, vec:: len ( ptrs) ) ;
165
+ let dict = alloca ( bcx, dict_ty) , i = 0 ;
166
+ for ptr in ptrs {
167
+ Store ( bcx, PointerCast ( bcx, ptr, pty) , GEPi ( bcx, dict, [ 0 , i] ) ) ;
168
+ i += 1 ;
169
+ }
170
+ rslt ( bcx, PointerCast ( bcx, dict, T_ptr ( T_dict ( ) ) ) )
171
+ }
172
+ typeck:: dict_param ( n_param, n_bound) {
173
+ rslt ( bcx, option:: get ( bcx. fcx . lltyparams [ n_param] . dicts ) [ n_bound] )
274
174
}
275
175
}
276
- }
176
+ }
0 commit comments