Skip to content

Commit f529af0

Browse files
committed
auto merge of #4844 : jld/rust/const-index-fix, r=graydon
Fixes #3169 and uses that to fix const array indexing, which I broke (in a way that doesn't break tests but will greatly confuse users) while trying to fix const enum vectors.
2 parents ee93fb2 + 9318bab commit f529af0

File tree

2 files changed

+11
-41
lines changed

2 files changed

+11
-41
lines changed

src/librustc/middle/trans/consts.rs

+2-31
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
254254
~"index is not an integer-constant \
255255
expression")
256256
};
257-
let (arr, _len) = match ty::get(bt).sty {
257+
let (arr, len) = match ty::get(bt).sty {
258258
ty::ty_evec(_, vstore) | ty::ty_estr(vstore) =>
259259
match vstore {
260260
ty::vstore_fixed(u) =>
@@ -278,36 +278,7 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
278278
a vector or string type")
279279
};
280280

281-
// FIXME #3169: This is a little odd but it arises due to a
282-
// weird wrinkle in LLVM: it doesn't appear willing to let us
283-
// call LLVMConstIntGetZExtValue on the size element of the
284-
// slice, or seemingly any integer-const involving a sizeof()
285-
// call. Despite that being "a const", it's not the kind of
286-
// const you can ask for the integer-value of, evidently. This
287-
// might be an LLVM bug, not sure. In any case, to work around
288-
// this we obtain the initializer and count how many elements it
289-
// has, ignoring the length we pulled out of the slice. (Note
290-
// that the initializer might be a struct rather than an array,
291-
// if enums are involved.) This only works because we picked out
292-
// the original globalvar via const_deref and so can recover the
293-
// array-size of the underlying array (or the element count of
294-
// the underlying struct), and all this will hold together
295-
// exactly as long as we _don't_ support const sub-slices (that
296-
// is, slices that represent something other than a whole
297-
// array). At that point we'll have more and uglier work to do
298-
// here, but for now this should work.
299-
//
300-
// In the future, what we should be doing here is the
301-
// moral equivalent of:
302-
//
303-
// let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
304-
//
305-
// but we might have to do substantially more magic to
306-
// make it work. Or figure out what is causing LLVM to
307-
// not want to consider sizeof() a constant expression
308-
// we can get the value (as a number) out of.
309-
310-
let len = llvm::LLVMGetNumOperands(arr) as u64;
281+
let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
311282
let len = match ty::get(bt).sty {
312283
ty::ty_estr(*) => {assert len > 0; len - 1},
313284
_ => len

src/librustc/middle/trans/machine.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,16 @@ pub fn llbitsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
126126
}
127127
}
128128

129-
// Returns the "default" size of t, which is calculated by casting null to a
130-
// *T and then doing gep(1) on it and measuring the result. Really, look in
131-
// the LLVM sources. It does that. So this is likely similar to the ABI size
132-
// (i.e. including alignment-padding), but goodness knows which alignment it
133-
// winds up using. Probably the ABI one? Not recommended.
129+
/// Returns the size of the type as an LLVM constant integer value.
134130
pub fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
135-
unsafe {
136-
return llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t),
137-
cx.int_type,
138-
False);
139-
}
131+
// Once upon a time, this called LLVMSizeOf, which does a
132+
// getelementptr(1) on a null pointer and casts to an int, in
133+
// order to obtain the type size as a value without requiring the
134+
// target data layout. But we have the target data layout, so
135+
// there's no need for that contrivance. The instruction
136+
// selection DAG generator would flatten that GEP(1) node into a
137+
// constant of the type's alloc size, so let's save it some work.
138+
return C_uint(cx, llsize_of_alloc(cx, t));
140139
}
141140

142141
// Returns the "default" size of t (see above), or 1 if the size would

0 commit comments

Comments
 (0)