1010
1111use core:: prelude:: * ;
1212
13+ use back:: abi;
1314use lib:: llvm:: { llvm, ValueRef , TypeRef , Bool , True , False } ;
1415use metadata:: csearch;
1516use middle:: const_eval;
@@ -94,30 +95,56 @@ pub fn const_vec(cx: @CrateContext, e: @ast::expr, es: &[@ast::expr])
9495 }
9596}
9697
97- pub fn const_deref ( cx : @CrateContext , v : ValueRef ) -> ValueRef {
98+ fn const_addr_of ( cx : @CrateContext , cv : ValueRef ) -> ValueRef {
9899 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)
102102 } ;
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 {
103115 fail_unless ! ( llvm:: LLVMIsGlobalConstant ( v) == True ) ;
104- let v = llvm:: LLVMGetInitializer ( v) ;
105- v
116+ llvm:: LLVMGetInitializer ( v)
106117 }
107118}
108119
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) ) )
121148 }
122149 }
123150}
@@ -142,15 +169,68 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
142169}
143170
144171pub 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) ;
148227 let csize = machine:: llsize_of_alloc( cx, val_ty( llconst) ) ;
149228 let tsize = machine:: llsize_of_alloc( cx, llty) ;
150229 if csize != tsize {
151230 unsafe {
231+ // XXX these values could use some context
152232 llvm : : LLVMDumpValue ( llconst) ;
153- llvm:: LLVMDumpValue ( C_null ( llty) ) ;
233+ llvm:: LLVMDumpValue ( C_undef ( llty) ) ;
154234 }
155235 cx. sess. bug( fmt ! ( "const %s of type %s has size %u instead of %u" ,
156236 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 {
159239 llconst
160240}
161241
162- fn const_expr_unchecked ( cx : @CrateContext , e : @ast:: expr ) -> ValueRef {
242+ fn const_expr_unadjusted ( cx: @CrateContext , e: @ast:: expr) -> ValueRef {
163243 unsafe {
164244 let _icx = cx. insn_ctxt( "const_expr" ) ;
165245 return match /*bad*/ copy e. node {
@@ -223,7 +303,10 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
223303 return match u {
224304 ast : : box( _) |
225305 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+ }
227310 ast:: not => {
228311 match ty:: get( ty) . sty {
229312 ty : : ty_bool => {
@@ -243,20 +326,18 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
243326 }
244327 }
245328 ast:: expr_field( base, field, _) => {
246- let bt = ty:: expr_ty ( cx. tcx , base) ;
329+ let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
247330 let brepr = adt:: represent_type( cx, bt) ;
248331 let bv = const_expr( cx, base) ;
249- let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
250332 do expr:: with_field_tys( cx. tcx, bt, None ) |discr, field_tys| {
251333 let ix = ty:: field_idx_strict( cx. tcx, field, field_tys) ;
252334 adt:: const_get_field( cx, brepr, bv, discr, ix)
253335 }
254336 }
255337
256338 ast:: expr_index( base, index) => {
257- let bt = ty:: expr_ty ( cx. tcx , base) ;
339+ let bt = ty:: expr_ty_adjusted ( cx. tcx, base) ;
258340 let bv = const_expr( cx, base) ;
259- let ( bt, bv) = const_autoderef ( cx, bt, bv) ;
260341 let iv = match const_eval:: eval_const_expr( cx. tcx, index) {
261342 const_eval:: const_int( i) => i as u64,
262343 const_eval:: const_uint( u) => u,
@@ -275,7 +356,7 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
275356 let llunitty = type_of:: type_of( cx, unit_ty) ;
276357 let unit_sz = machine:: llsize_of( cx, llunitty) ;
277358
278- ( const_deref ( cx, const_get_elt ( cx, bv, [ 0 ] ) ) ,
359+ ( const_deref_ptr ( cx, const_get_elt( cx, bv, [ 0 ] ) ) ,
279360 llvm:: LLVMConstUDiv ( const_get_elt( cx, bv, [ 1 ] ) ,
280361 unit_sz) )
281362 } ,
@@ -355,13 +436,7 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
355436 }
356437 }
357438 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) )
365440 }
366441 ast:: expr_tup( es) => {
367442 let ety = ty:: expr_ty( cx. tcx, e) ;
@@ -420,26 +495,12 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
420495 fail_unless ! ( pth. types. len( ) == 0 ) ;
421496 match cx. tcx. def_map. find( & e. id) {
422497 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) {
424499 let ty = csearch:: get_type( cx. tcx, def_id) . ty;
425500 base:: trans_external_path( cx, def_id, ty)
426501 } else {
427502 fail_unless ! ( ast_util:: is_local( def_id) ) ;
428503 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- }
443504 }
444505 }
445506 Some ( ast:: def_const( def_id) ) => {
0 commit comments