@@ -32,6 +32,12 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
32
32
// duplicate constants. I think. Maybe LLVM has a magical mode that does so
33
33
// later on?
34
34
35
+ fn const_ptrcast( cx: @crate_ctxt, a: ValueRef , t: TypeRef ) -> ValueRef {
36
+ let b = llvm : : LLVMConstPointerCast ( a, T_ptr ( t) ) ;
37
+ assert cx. const_globals. insert( b as int, a) ;
38
+ b
39
+ }
40
+
35
41
fn const_vec( cx: @crate_ctxt, e: @ast:: expr, es: & [ @ast:: expr] )
36
42
-> ( ValueRef , ValueRef , TypeRef ) {
37
43
let vec_ty = ty:: expr_ty( cx. tcx, e) ;
@@ -43,17 +49,22 @@ fn const_vec(cx: @crate_ctxt, e: @ast::expr, es: &[@ast::expr])
43
49
return ( v, sz, llunitty) ;
44
50
}
45
51
46
- fn const_deref( v: ValueRef ) -> ValueRef {
52
+ fn const_deref( cx: @crate_ctxt, v: ValueRef ) -> ValueRef {
53
+ let v = match cx. const_globals. find( v as int) {
54
+ some( v) => v,
55
+ none => v
56
+ } ;
47
57
assert llvm:: LLVMIsGlobalConstant ( v) == True ;
48
- llvm:: LLVMGetInitializer ( v)
58
+ let v = llvm:: LLVMGetInitializer ( v) ;
59
+ v
49
60
}
50
61
51
62
fn const_get_elt ( v : ValueRef , u : uint ) -> ValueRef {
52
63
let u = u;
53
64
llvm:: LLVMConstExtractValue ( v, ptr:: addr_of ( u) , 1 as c_uint )
54
65
}
55
66
56
- fn const_autoderef( ty: ty:: t, v: ValueRef )
67
+ fn const_autoderef ( cx : @ crate_ctxt , ty : ty:: t , v : ValueRef )
57
68
-> ( ty:: t , ValueRef ) {
58
69
let mut t1 = ty;
59
70
let mut v1 = v;
@@ -62,7 +73,7 @@ fn const_autoderef(ty: ty::t, v: ValueRef)
62
73
match ty:: get ( ty) . struct {
63
74
ty:: ty_rptr( _, mt) => {
64
75
t1 = mt. ty ;
65
- v1 = const_deref ( v1) ;
76
+ v1 = const_deref ( cx , v1) ;
66
77
}
67
78
_ => return ( t1, v1)
68
79
}
@@ -133,7 +144,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
133
144
return match u {
134
145
ast:: box( _) |
135
146
ast:: uniq( _) |
136
- ast:: deref => const_deref ( te) ,
147
+ ast:: deref => const_deref ( cx , te) ,
137
148
ast:: not => llvm:: LLVMConstNot ( te) ,
138
149
ast:: neg => {
139
150
if is_float { llvm:: LLVMConstFNeg ( te) }
@@ -144,7 +155,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
144
155
ast:: expr_field( base, field, _) => {
145
156
let bt = ty:: expr_ty ( cx. tcx , base) ;
146
157
let bv = const_expr ( cx, base) ;
147
- let ( bt, bv) = const_autoderef ( bt, bv) ;
158
+ let ( bt, bv) = const_autoderef ( cx , bt, bv) ;
148
159
let fields = match ty:: get ( bt) . struct {
149
160
ty:: ty_rec( fs) => fs,
150
161
ty:: ty_class( did, substs) =>
@@ -159,15 +170,15 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
159
170
ast:: expr_index( base, index) => {
160
171
let bt = ty:: expr_ty ( cx. tcx , base) ;
161
172
let bv = const_expr ( cx, base) ;
162
- let ( bt, bv) = const_autoderef ( bt, bv) ;
173
+ let ( bt, bv) = const_autoderef ( cx , bt, bv) ;
163
174
let iv = match const_eval:: eval_const_expr ( cx. tcx , index) {
164
175
const_eval:: const_int( i) => i as u64 ,
165
176
const_eval:: const_uint( u) => u,
166
177
_ => cx. sess . span_bug ( index. span ,
167
178
~"index is not an integer-constant \
168
179
expression")
169
180
} ;
170
- let ( arr, len ) = match ty:: get ( bt) . struct {
181
+ let ( arr, _len ) = match ty:: get ( bt) . struct {
171
182
ty:: ty_evec( _, vstore) | ty:: ty_estr( vstore) =>
172
183
match vstore {
173
184
ty:: vstore_fixed( u) =>
@@ -177,9 +188,10 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
177
188
let unit_ty = ty:: sequence_element_type ( cx. tcx , bt) ;
178
189
let llunitty = type_of:: type_of ( cx, unit_ty) ;
179
190
let unit_sz = shape:: llsize_of ( cx, llunitty) ;
180
- ( const_deref ( const_get_elt ( bv, 0 ) ) ,
191
+
192
+ ( const_deref ( cx, const_get_elt ( bv, 0 ) ) ,
181
193
llvm:: LLVMConstUDiv ( const_get_elt ( bv, 1 ) ,
182
- unit_sz) )
194
+ unit_sz) )
183
195
} ,
184
196
_ => cx. sess . span_bug ( base. span ,
185
197
~"index-expr base must be \
@@ -189,13 +201,42 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
189
201
~"index-expr base must be \
190
202
a vector or string type ")
191
203
} ;
192
- let len = llvm:: LLVMConstIntGetZExtValue ( len) as u64 ;
204
+
205
+ // FIXME #3169: This is a little odd but it arises due to a weird
206
+ // wrinkle in LLVM: it doesn't appear willing to let us call
207
+ // LLVMConstIntGetZExtValue on the size element of the slice, or
208
+ // seemingly any integer-const involving a sizeof() call. Despite
209
+ // that being "a const", it's not the kind of const you can ask
210
+ // for the integer-value of, evidently. This might be an LLVM
211
+ // bug, not sure. In any case, to work around this we drop down
212
+ // to the array-type level here and just ask how long the
213
+ // array-type itself is, ignoring the length we pulled out of the
214
+ // slice. This in turn only works because we picked out the
215
+ // original globalvar via const_deref and so can recover the
216
+ // array-size of the underlying array, and all this will hold
217
+ // together exactly as long as we _don't_ support const
218
+ // sub-slices (that is, slices that represent something other
219
+ // than a whole array). At that point we'll have more and uglier
220
+ // work to do here, but for now this should work.
221
+ //
222
+ // In the future, what we should be doing here is the
223
+ // moral equivalent of:
224
+ //
225
+ // let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
226
+ //
227
+ // but we might have to do substantially more magic to
228
+ // make it work. Or figure out what is causing LLVM to
229
+ // not want to consider sizeof() a constant expression
230
+ // we can get the value (as a number) out of.
231
+
232
+ let len = llvm:: LLVMGetArrayLength ( val_ty ( arr) ) as u64 ;
193
233
let len = match ty:: get ( bt) . struct {
194
234
ty:: ty_estr( * ) => { assert len > 0 ; len - 1 } ,
195
235
_ => len
196
236
} ;
197
237
if iv >= len {
198
- // Better late than never for reporting this?
238
+ // FIXME #3170: report this earlier on in the const-eval
239
+ // pass. Reporting here is a bit late.
199
240
cx. sess . span_err ( e. span ,
200
241
~"const index-expr is out of bounds") ;
201
242
}
@@ -292,8 +333,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
292
333
} ;
293
334
llvm:: LLVMSetInitializer ( gv, cv) ;
294
335
llvm:: LLVMSetGlobalConstant ( gv, True ) ;
295
- let p = llvm:: LLVMConstPointerCast ( gv, T_ptr ( llunitty) ) ;
296
-
336
+ let p = const_ptrcast ( cx, gv, llunitty) ;
297
337
C_struct ( ~[ p, sz] )
298
338
}
299
339
_ => cx. sess . span_bug ( e. span ,
0 commit comments