10
10
11
11
use core:: prelude:: * ;
12
12
13
- use back:: abi;
14
13
use lib:: llvm:: { llvm, ValueRef , TypeRef , Bool , True , False } ;
15
14
use metadata:: csearch;
16
15
use middle:: const_eval;
@@ -95,56 +94,30 @@ pub fn const_vec(cx: @CrateContext, e: @ast::expr, es: &[@ast::expr])
95
94
}
96
95
}
97
96
98
- fn const_addr_of ( cx : @CrateContext , cv : ValueRef ) -> ValueRef {
97
+ pub fn const_deref ( cx : @CrateContext , v : ValueRef ) -> ValueRef {
99
98
unsafe {
100
- let gv = do str:: as_c_str ( "const" ) |name| {
101
- llvm:: LLVMAddGlobal ( cx. llmod , val_ty ( cv) , name)
99
+ let v = match cx. const_globals . find ( & ( v as int ) ) {
100
+ Some ( v) => v,
101
+ None => v
102
102
} ;
103
- llvm:: LLVMSetInitializer ( gv, cv) ;
104
- llvm:: LLVMSetGlobalConstant ( gv, True ) ;
105
- gv
106
- }
107
- }
108
-
109
- fn const_deref_ptr ( cx : @CrateContext , v : ValueRef ) -> ValueRef {
110
- let v = match cx. const_globals . find ( & ( v as int ) ) {
111
- Some ( v) => v,
112
- None => v
113
- } ;
114
- unsafe {
115
103
fail_unless ! ( llvm:: LLVMIsGlobalConstant ( v) == True ) ;
116
- llvm:: LLVMGetInitializer ( v)
104
+ let v = llvm:: LLVMGetInitializer ( v) ;
105
+ v
117
106
}
118
107
}
119
108
120
- fn const_deref_newtype ( cx : @CrateContext , v : ValueRef , t : ty:: t )
121
- -> ValueRef {
122
- let repr = adt:: represent_type ( cx, t) ;
123
- adt:: const_get_field ( cx, repr, v, 0 , 0 )
124
- }
125
-
126
- fn const_deref ( cx : @CrateContext , v : ValueRef , t : ty:: t , explicit : bool )
127
- -> ( ValueRef , ty:: t ) {
128
- match ty:: deref ( cx. tcx , t, explicit) {
129
- Some ( ref mt) => {
130
- fail_unless ! ( mt. mutbl != ast:: m_mutbl) ;
131
- let dv = match ty:: get ( t) . sty {
132
- ty:: ty_ptr( * ) | ty:: ty_rptr( * ) => {
133
- const_deref_ptr ( cx, v)
134
- }
135
- ty:: ty_enum( * ) | ty:: ty_struct( * ) => {
136
- const_deref_newtype ( cx, v, t)
137
- }
138
- _ => {
139
- cx. sess . bug ( fmt ! ( "Unexpected dereferenceable type %s" ,
140
- ty_to_str( cx. tcx, t) ) )
141
- }
142
- } ;
143
- ( dv, mt. ty )
144
- }
145
- None => {
146
- cx. sess . bug ( fmt ! ( "Can't dereference const of type %s" ,
147
- ty_to_str( cx. tcx, t) ) )
109
+ pub fn const_autoderef ( cx : @CrateContext , ty : ty:: t , v : ValueRef )
110
+ -> ( ty:: t , ValueRef ) {
111
+ let mut t1 = ty;
112
+ let mut v1 = v;
113
+ loop {
114
+ // Only rptrs can be autoderef'ed in a const context.
115
+ match ty:: get ( t1) . sty {
116
+ ty:: ty_rptr( _, mt) => {
117
+ t1 = mt. ty ;
118
+ v1 = const_deref ( cx, v1) ;
119
+ }
120
+ _ => return ( t1, v1)
148
121
}
149
122
}
150
123
}
@@ -169,68 +142,15 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
169
142
}
170
143
171
144
pub fn const_expr ( cx : @CrateContext , e : @ast:: expr ) -> ValueRef {
172
- let mut llconst = const_expr_unadjusted ( cx, e) ;
173
- let ety = ty:: expr_ty ( cx. tcx , e) ;
174
- match cx. tcx . adjustments . find ( & e. id ) {
175
- None => { }
176
- Some ( @ty:: AutoAddEnv ( ty:: re_static, ast:: BorrowedSigil ) ) => {
177
- llconst = C_struct ( ~[ llconst, C_null ( T_opaque_box_ptr ( cx) ) ] )
178
- }
179
- Some ( @ty:: AutoAddEnv ( ref r, ref s) ) => {
180
- cx. sess . span_bug ( e. span , fmt ! ( "unexpected const function: \
181
- region %? sigil %?", * r, * s) )
182
- }
183
- Some ( @ty:: AutoDerefRef ( ref adj) ) => {
184
- let mut ty = ety;
185
- let mut maybe_ptr = None ;
186
- for adj. autoderefs. times {
187
- let ( dv, dt) = const_deref( cx, llconst, ty, false ) ;
188
- maybe_ptr = Some ( llconst) ;
189
- llconst = dv;
190
- ty = dt;
191
- }
192
-
193
- match adj. autoref {
194
- None => { }
195
- Some ( ref autoref) => {
196
- fail_unless ! ( autoref. region == ty:: re_static) ;
197
- fail_unless ! ( autoref. mutbl != ast:: m_mutbl) ;
198
- // Don't copy data to do a deref+ref.
199
- let llptr = match maybe_ptr {
200
- Some ( ptr) => ptr,
201
- None => const_addr_of( cx, llconst)
202
- } ;
203
- match autoref. kind {
204
- ty : : AutoPtr => {
205
- llconst = llptr;
206
- }
207
- ty:: AutoBorrowVec => {
208
- let size = machine:: llsize_of( cx,
209
- val_ty( llconst) ) ;
210
- fail_unless ! ( abi:: slice_elt_base == 0 ) ;
211
- fail_unless ! ( abi:: slice_elt_len == 1 ) ;
212
- llconst = C_struct ( ~[ llptr, size] ) ;
213
- }
214
- _ => {
215
- cx. sess. span_bug( e. span,
216
- fmt ! ( "unimplemented const \
217
- autoref %?", autoref) )
218
- }
219
- }
220
- }
221
- }
222
- }
223
- }
224
-
225
- let ety_adjusted = ty:: expr_ty_adjusted( cx. tcx, e) ;
226
- let llty = type_of:: sizing_type_of( cx, ety_adjusted) ;
145
+ let ety = ty:: expr_ty_adjusted ( cx. tcx , e) ;
146
+ let llty = type_of:: sizing_type_of ( cx, ety) ;
147
+ let llconst = const_expr_unchecked ( cx, e) ;
227
148
let csize = machine:: llsize_of_alloc ( cx, val_ty ( llconst) ) ;
228
149
let tsize = machine:: llsize_of_alloc ( cx, llty) ;
229
150
if csize != tsize {
230
151
unsafe {
231
- // XXX these values could use some context
232
152
llvm:: LLVMDumpValue ( llconst) ;
233
- llvm:: LLVMDumpValue ( C_undef ( llty) ) ;
153
+ llvm:: LLVMDumpValue ( C_null ( llty) ) ;
234
154
}
235
155
cx. sess . bug ( fmt ! ( "const %s of type %s has size %u instead of %u" ,
236
156
expr_repr( cx. tcx, e) , ty_to_str( cx. tcx, ety) ,
@@ -239,7 +159,7 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
239
159
llconst
240
160
}
241
161
242
- fn const_expr_unadjusted ( cx: @CrateContext , e: @ast:: expr) -> ValueRef {
162
+ fn const_expr_unchecked ( cx : @CrateContext , e : @ast:: expr ) -> ValueRef {
243
163
unsafe {
244
164
let _icx = cx. insn_ctxt ( "const_expr" ) ;
245
165
return match /*bad*/ copy e. node {
@@ -303,10 +223,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
303
223
return match u {
304
224
ast:: box( _) |
305
225
ast:: uniq( _) |
306
- ast:: deref => {
307
- let ( dv, _dt) = const_deref( cx, te, ty, true ) ;
308
- dv
309
- }
226
+ ast:: deref => const_deref ( cx, te) ,
310
227
ast:: not => {
311
228
match ty:: get ( ty) . sty {
312
229
ty:: ty_bool => {
@@ -326,18 +243,20 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
326
243
}
327
244
}
328
245
ast:: expr_field( base, field, _) => {
329
- let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
246
+ let bt = ty:: expr_ty ( cx. tcx , base) ;
330
247
let brepr = adt:: represent_type ( cx, bt) ;
331
248
let bv = const_expr ( cx, base) ;
249
+ let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
332
250
do expr:: with_field_tys ( cx. tcx , bt, None ) |discr, field_tys| {
333
251
let ix = ty:: field_idx_strict ( cx. tcx , field, field_tys) ;
334
252
adt:: const_get_field ( cx, brepr, bv, discr, ix)
335
253
}
336
254
}
337
255
338
256
ast:: expr_index( base, index) => {
339
- let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
257
+ let bt = ty:: expr_ty ( cx. tcx , base) ;
340
258
let bv = const_expr ( cx, base) ;
259
+ let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
341
260
let iv = match const_eval:: eval_const_expr ( cx. tcx , index) {
342
261
const_eval:: const_int( i) => i as u64 ,
343
262
const_eval:: const_uint( u) => u,
@@ -356,7 +275,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
356
275
let llunitty = type_of:: type_of ( cx, unit_ty) ;
357
276
let unit_sz = machine:: llsize_of ( cx, llunitty) ;
358
277
359
- ( const_deref_ptr ( cx, const_get_elt( cx, bv, [ 0 ] ) ) ,
278
+ ( const_deref ( cx, const_get_elt ( cx, bv, [ 0 ] ) ) ,
360
279
llvm:: LLVMConstUDiv ( const_get_elt ( cx, bv, [ 1 ] ) ,
361
280
unit_sz) )
362
281
} ,
@@ -436,7 +355,13 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
436
355
}
437
356
}
438
357
ast:: expr_addr_of( ast:: m_imm, sub) => {
439
- const_addr_of( cx, const_expr( cx, sub) )
358
+ let cv = const_expr ( cx, sub) ;
359
+ let gv = do str:: as_c_str ( "const" ) |name| {
360
+ llvm:: LLVMAddGlobal ( cx. llmod , val_ty ( cv) , name)
361
+ } ;
362
+ llvm:: LLVMSetInitializer ( gv, cv) ;
363
+ llvm:: LLVMSetGlobalConstant ( gv, True ) ;
364
+ gv
440
365
}
441
366
ast:: expr_tup ( es) => {
442
367
let ety = ty:: expr_ty ( cx. tcx , e) ;
@@ -495,12 +420,26 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
495
420
fail_unless ! ( pth. types. len( ) == 0 ) ;
496
421
match cx. tcx . def_map . find ( & e. id ) {
497
422
Some ( ast:: def_fn( def_id, _purity) ) => {
498
- if !ast_util:: is_local( def_id) {
423
+ let f = if !ast_util:: is_local ( def_id) {
499
424
let ty = csearch:: get_type ( cx. tcx , def_id) . ty ;
500
425
base:: trans_external_path ( cx, def_id, ty)
501
426
} else {
502
427
fail_unless ! ( ast_util:: is_local( def_id) ) ;
503
428
base:: get_item_val ( cx, def_id. node )
429
+ } ;
430
+ let ety = ty:: expr_ty_adjusted ( cx. tcx , e) ;
431
+ match ty:: get ( ety) . sty {
432
+ ty:: ty_bare_fn( * ) | ty:: ty_ptr( * ) => {
433
+ llvm:: LLVMConstPointerCast ( f, T_ptr ( T_i8 ( ) ) )
434
+ }
435
+ ty:: ty_closure( * ) => {
436
+ C_struct ( ~[ f, C_null ( T_opaque_box_ptr ( cx) ) ] )
437
+ }
438
+ _ => {
439
+ cx. sess . span_bug ( e. span , fmt ! (
440
+ "unexpected const fn type: %s" ,
441
+ ty_to_str( cx. tcx, ety) ) )
442
+ }
504
443
}
505
444
}
506
445
Some ( ast:: def_const( def_id) ) => {
0 commit comments