10
10
11
11
use core:: prelude:: * ;
12
12
13
+ use back:: abi;
13
14
use lib:: llvm:: { llvm, ValueRef , TypeRef , Bool , True , False } ;
14
15
use metadata:: csearch;
15
16
use middle:: const_eval;
@@ -94,30 +95,56 @@ pub fn const_vec(cx: @CrateContext, e: @ast::expr, es: &[@ast::expr])
94
95
}
95
96
}
96
97
97
- pub fn const_deref ( cx : @CrateContext , v : ValueRef ) -> ValueRef {
98
+ fn const_addr_of ( cx : @CrateContext , cv : ValueRef ) -> ValueRef {
98
99
unsafe {
99
- let v = match cx. const_globals . find ( & ( v as int ) ) {
100
- Some ( v) => v,
101
- None => v
100
+ let gv = do str:: as_c_str ( "const" ) |name| {
101
+ llvm:: LLVMAddGlobal ( cx. llmod , val_ty ( cv) , name)
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 {
103
115
fail_unless ! ( llvm:: LLVMIsGlobalConstant ( v) == True ) ;
104
- let v = llvm:: LLVMGetInitializer ( v) ;
105
- v
116
+ llvm:: LLVMGetInitializer ( v)
106
117
}
107
118
}
108
119
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)
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) ) )
121
148
}
122
149
}
123
150
}
@@ -142,15 +169,68 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
142
169
}
143
170
144
171
pub fn const_expr( cx : @CrateContext , e : @ast:: expr ) -> ValueRef {
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) ;
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) ;
148
227
let csize = machine:: llsize_of_alloc( cx, val_ty( llconst) ) ;
149
228
let tsize = machine:: llsize_of_alloc( cx, llty) ;
150
229
if csize != tsize {
151
230
unsafe {
231
+ // XXX these values could use some context
152
232
llvm : : LLVMDumpValue ( llconst) ;
153
- llvm:: LLVMDumpValue ( C_null ( llty) ) ;
233
+ llvm:: LLVMDumpValue ( C_undef ( llty) ) ;
154
234
}
155
235
cx. sess. bug( fmt ! ( "const %s of type %s has size %u instead of %u" ,
156
236
expr_repr( cx. tcx, e) , ty_to_str( cx. tcx, ety) ,
@@ -159,7 +239,7 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
159
239
llconst
160
240
}
161
241
162
- fn const_expr_unchecked ( cx : @CrateContext , e : @ast:: expr ) -> ValueRef {
242
+ fn const_expr_unadjusted ( cx: @CrateContext , e: @ast:: expr) -> ValueRef {
163
243
unsafe {
164
244
let _icx = cx. insn_ctxt( "const_expr" ) ;
165
245
return match /*bad*/ copy e. node {
@@ -223,7 +303,10 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
223
303
return match u {
224
304
ast : : box( _) |
225
305
ast:: uniq( _) |
226
- ast:: deref => const_deref ( cx, te) ,
306
+ ast:: deref => {
307
+ let ( dv, _dt) = const_deref( cx, te, ty, true ) ;
308
+ dv
309
+ }
227
310
ast:: not => {
228
311
match ty:: get( ty) . sty {
229
312
ty : : ty_bool => {
@@ -243,20 +326,18 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
243
326
}
244
327
}
245
328
ast:: expr_field( base, field, _) => {
246
- let bt = ty:: expr_ty ( cx. tcx , base) ;
329
+ let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
247
330
let brepr = adt:: represent_type( cx, bt) ;
248
331
let bv = const_expr( cx, base) ;
249
- let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
250
332
do expr:: with_field_tys( cx. tcx, bt, None ) |discr, field_tys| {
251
333
let ix = ty:: field_idx_strict( cx. tcx, field, field_tys) ;
252
334
adt:: const_get_field( cx, brepr, bv, discr, ix)
253
335
}
254
336
}
255
337
256
338
ast:: expr_index( base, index) => {
257
- let bt = ty:: expr_ty ( cx. tcx , base) ;
339
+ let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
258
340
let bv = const_expr( cx, base) ;
259
- let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
260
341
let iv = match const_eval:: eval_const_expr( cx. tcx, index) {
261
342
const_eval:: const_int( i) => i as u64,
262
343
const_eval:: const_uint( u) => u,
@@ -275,7 +356,7 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
275
356
let llunitty = type_of:: type_of( cx, unit_ty) ;
276
357
let unit_sz = machine:: llsize_of( cx, llunitty) ;
277
358
278
- ( const_deref ( cx, const_get_elt ( cx, bv, [ 0 ] ) ) ,
359
+ ( const_deref_ptr ( cx, const_get_elt( cx, bv, [ 0 ] ) ) ,
279
360
llvm:: LLVMConstUDiv ( const_get_elt( cx, bv, [ 1 ] ) ,
280
361
unit_sz) )
281
362
} ,
@@ -355,13 +436,7 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
355
436
}
356
437
}
357
438
ast:: expr_addr_of( ast:: m_imm, 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
439
+ const_addr_of( cx, const_expr( cx, sub) )
365
440
}
366
441
ast:: expr_tup( es) => {
367
442
let ety = ty:: expr_ty( cx. tcx, e) ;
@@ -420,26 +495,12 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
420
495
fail_unless ! ( pth. types. len( ) == 0 ) ;
421
496
match cx. tcx. def_map. find( & e. id) {
422
497
Some ( ast:: def_fn( def_id, _purity) ) => {
423
- let f = if !ast_util:: is_local ( def_id) {
498
+ if !ast_util:: is_local( def_id) {
424
499
let ty = csearch:: get_type( cx. tcx, def_id) . ty;
425
500
base:: trans_external_path( cx, def_id, ty)
426
501
} else {
427
502
fail_unless ! ( ast_util:: is_local( def_id) ) ;
428
503
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
- }
443
504
}
444
505
}
445
506
Some ( ast:: def_const( def_id) ) => {
0 commit comments