@@ -5,8 +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;
9
- import llvm:: llvm :: { ValueRef , TypeRef , LLVMGetParam } ;
8
+ import lib:: llvm:: llvm ;
9
+ import llvm:: { ValueRef , TypeRef , LLVMGetParam } ;
10
10
11
11
fn trans_impl ( cx : @local_ctxt , name : ast:: ident , methods : [ @ast:: method ] ,
12
12
id : ast:: node_id , tps : [ ast:: ty_param ] ) {
@@ -76,18 +76,18 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
76
76
}
77
77
78
78
fn llfn_arg_tys ( ft : TypeRef ) -> { inputs : [ TypeRef ] , output : TypeRef } {
79
- let out_ty = llvm:: llvm :: LLVMGetReturnType ( ft) ;
80
- let n_args = llvm:: llvm :: LLVMCountParamTypes ( ft) ;
79
+ let out_ty = llvm:: LLVMGetReturnType ( ft) ;
80
+ let n_args = llvm:: LLVMCountParamTypes ( ft) ;
81
81
let args = vec:: init_elt ( 0 as TypeRef , n_args) ;
82
- unsafe { llvm:: llvm :: LLVMGetParamTypes ( ft, vec:: to_ptr ( args) ) ; }
82
+ unsafe { llvm:: LLVMGetParamTypes ( ft, vec:: to_ptr ( args) ) ; }
83
83
{ inputs: args, output: out_ty}
84
84
}
85
85
86
86
fn trans_wrapper ( ccx : @crate_ctxt , pt : [ ast:: ident ] ,
87
87
extra_tps : [ ty:: param_bounds ] , m : @ast:: method ) -> ValueRef {
88
88
let real_fn = ccx. item_ids . get ( m. id ) ;
89
89
let { inputs: real_args , output: real_ret} =
90
- llfn_arg_tys ( llvm:: llvm :: LLVMGetElementType ( val_ty ( real_fn) ) ) ;
90
+ llfn_arg_tys ( llvm:: LLVMGetElementType ( val_ty ( real_fn) ) ) ;
91
91
let extra_ptrs = [ ] ;
92
92
for tp in extra_tps {
93
93
extra_ptrs += [ T_ptr ( ccx. tydesc_type ) ] ;
@@ -121,7 +121,7 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
121
121
args += [ load_inbounds ( bcx, dict, [ 0 , i as int ] ) ] ;
122
122
}
123
123
// the rest of the parameters
124
- let i = 3 u, params_total = llvm:: llvm :: LLVMCountParamTypes ( llfn_ty) ;
124
+ let i = 3 u, params_total = llvm:: LLVMCountParamTypes ( llfn_ty) ;
125
125
while i < params_total {
126
126
args += [ LLVMGetParam ( llfn, i) ] ;
127
127
i += 1 u;
@@ -132,9 +132,84 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
132
132
ret llfn;
133
133
}
134
134
135
- // FIXME[impl] cache these on the function level somehow
135
+ fn dict_is_static ( tcx : ty:: ctxt , origin : typeck:: dict_origin ) -> bool {
136
+ alt origin {
137
+ typeck : : dict_static ( _, ts, origs) {
138
+ vec:: all ( ts, { |t| !ty:: type_contains_params ( tcx, t) } ) &&
139
+ vec:: all ( * origs, { |o| dict_is_static ( tcx, o) } )
140
+ }
141
+ typeck:: dict_param ( _, _) { false }
142
+ }
143
+ }
144
+
136
145
fn get_dict ( bcx : @block_ctxt , origin : typeck:: dict_origin ) -> result {
137
- let bcx = bcx, ccx = bcx_ccx ( bcx) ;
146
+ alt origin {
147
+ typeck : : dict_static ( impl_did, tys, sub_origins) {
148
+ if dict_is_static ( bcx_tcx ( bcx) , origin) {
149
+ ret rslt ( bcx, get_static_dict ( bcx, origin) ) ;
150
+ }
151
+ let { bcx, ptrs} = get_dict_ptrs ( bcx, origin) ;
152
+ let pty = T_ptr ( T_i8 ( ) ) , dict_ty = T_array ( pty, vec:: len ( ptrs) ) ;
153
+ let dict = alloca ( bcx, dict_ty) , i = 0 ;
154
+ for ptr in ptrs {
155
+ Store ( bcx, PointerCast ( bcx, ptr, pty) , GEPi ( bcx, dict, [ 0 , i] ) ) ;
156
+ i += 1 ;
157
+ }
158
+ rslt ( bcx, PointerCast ( bcx, dict, T_ptr ( T_dict ( ) ) ) )
159
+ }
160
+ typeck:: dict_param( n_param, n_bound) {
161
+ rslt ( bcx, option:: get ( bcx. fcx . lltyparams [ n_param] . dicts ) [ n_bound] )
162
+ }
163
+ }
164
+ }
165
+
166
+ fn dict_id ( tcx : ty:: ctxt , origin : typeck:: dict_origin ) -> dict_id {
167
+ alt origin {
168
+ typeck : : dict_static ( did, ts, origs) {
169
+ let d_params = [ ] , orig = 0 u;
170
+ if vec:: len ( ts) == 0 u { ret @{ impl_def : did, params : d_params} ; }
171
+ let impl_params = ty:: lookup_item_type ( tcx, did) . bounds ;
172
+ vec:: iter2 ( ts, * impl_params) { |t, bounds|
173
+ d_params += [ dict_param_ty ( t) ] ;
174
+ for bound in * bounds {
175
+ alt bound {
176
+ ty : : bound_iface ( _) {
177
+ d_params += [ dict_param_dict ( dict_id ( tcx, origs[ orig] ) ) ] ;
178
+ orig += 1 u;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ @{ impl_def: did, params: d_params}
184
+ }
185
+ }
186
+ }
187
+
188
+ fn get_static_dict ( bcx : @block_ctxt , origin : typeck:: dict_origin )
189
+ -> ValueRef {
190
+ let ccx = bcx_ccx ( bcx) ;
191
+ let id = dict_id ( ccx. tcx , origin) ;
192
+ alt ccx. dicts . find ( id) {
193
+ some ( d) { ret d; }
194
+ none. { }
195
+ }
196
+ let ptrs = C_struct ( get_dict_ptrs ( bcx, origin) . ptrs ) ;
197
+ let name = ccx. names . next ( "dict" ) ;
198
+ let gvar = str:: as_buf ( name, { |buf|
199
+ llvm:: LLVMAddGlobal ( ccx. llmod , val_ty ( ptrs) , buf)
200
+ } ) ;
201
+ llvm:: LLVMSetGlobalConstant ( gvar, lib:: llvm:: True ) ;
202
+ llvm:: LLVMSetInitializer ( gvar, ptrs) ;
203
+ llvm:: LLVMSetLinkage ( gvar,
204
+ lib:: llvm:: LLVMInternalLinkage as llvm:: Linkage ) ;
205
+ let cast = llvm:: LLVMConstPointerCast ( gvar, T_ptr ( T_dict ( ) ) ) ;
206
+ ccx. dicts . insert ( id, cast) ;
207
+ cast
208
+ }
209
+
210
+ fn get_dict_ptrs( bcx : @block_ctxt , origin : typeck:: dict_origin )
211
+ -> { bcx : @block_ctxt , ptrs : [ ValueRef ] } {
212
+ let ccx = bcx_ccx ( bcx) ;
138
213
alt origin {
139
214
typeck : : dict_static ( impl_did, tys, sub_origins) {
140
215
let vtable = if impl_did. crate == ast:: local_crate {
@@ -144,9 +219,9 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
144
219
get_extern_const ( ccx. externs , ccx. llmod , name, T_ptr ( T_i8 ( ) ) )
145
220
} ;
146
221
let impl_params = ty:: lookup_item_type ( ccx. tcx , impl_did) . bounds ;
147
- let ptrs = [ vtable] , i = 0 u, origin = 0 u , ti = none ;
148
- for param in * impl_params {
149
- let rslt = get_tydesc ( bcx, tys [ i ] , false , tps_normal, ti) . result ;
222
+ let ptrs = [ vtable] , origin = 0 u, ti = none , bcx = bcx ;
223
+ vec :: iter2 ( * impl_params, tys ) { |param , ty|
224
+ let rslt = get_tydesc ( bcx, ty , true , tps_normal, ti) . result ;
150
225
ptrs += [ rslt. val ] ;
151
226
bcx = rslt. bcx ;
152
227
for bound in * param {
@@ -160,18 +235,8 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
160
235
_ { }
161
236
}
162
237
}
163
- i += 1 u;
164
238
}
165
- let pty = T_ptr ( T_i8 ( ) ) , dict_ty = T_array ( pty, vec:: len ( ptrs) ) ;
166
- let dict = alloca ( bcx, dict_ty) , i = 0 ;
167
- for ptr in ptrs {
168
- Store ( bcx, PointerCast ( bcx, ptr, pty) , GEPi ( bcx, dict, [ 0 , i] ) ) ;
169
- i += 1 ;
170
- }
171
- rslt ( bcx, PointerCast ( bcx, dict, T_ptr ( T_dict ( ) ) ) )
172
- }
173
- typeck:: dict_param ( n_param, n_bound) {
174
- rslt ( bcx, option:: get ( bcx. fcx . lltyparams [ n_param] . dicts ) [ n_bound] )
239
+ { bcx: bcx, ptrs: ptrs}
175
240
}
176
241
}
177
- }
242
+ }
0 commit comments