Skip to content

Commit 5ca1d35

Browse files
committed
Implement most of adjustment handling for consts.
Changes the ad-hoc closure adjustment into using adjustment info instead of being separately driven from types, and likewise for autoderef. Also takes care of autoref (the cases we should be seeing in consts, at least, since we can't be doing method calls which would need the ref-to-vec mode), which didn't quite work right previously. However, "dereference" of a newtype isn't handled yet....
1 parent 5571ca9 commit 5ca1d35

File tree

1 file changed

+53
-40
lines changed

1 file changed

+53
-40
lines changed

src/librustc/middle/trans/consts.rs

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use core::prelude::*;
1212

13+
use back::abi;
1314
use lib::llvm::{llvm, ValueRef, TypeRef, Bool, True, False};
1415
use metadata::csearch;
1516
use middle::const_eval;
@@ -117,22 +118,6 @@ pub fn const_deref(cx: @CrateContext, v: ValueRef) -> ValueRef {
117118
}
118119
}
119120

120-
pub fn const_autoderef(cx: @CrateContext, ty: ty::t, v: ValueRef)
121-
-> (ty::t, ValueRef) {
122-
let mut t1 = ty;
123-
let mut v1 = v;
124-
loop {
125-
// Only rptrs can be autoderef'ed in a const context.
126-
match ty::get(t1).sty {
127-
ty::ty_rptr(_, mt) => {
128-
t1 = mt.ty;
129-
v1 = const_deref(cx, v1);
130-
}
131-
_ => return (t1,v1)
132-
}
133-
}
134-
}
135-
136121
pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
137122
let mut def_id = def_id;
138123
if !ast_util::is_local(def_id) ||
@@ -153,15 +138,59 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
153138
}
154139

155140
pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
156-
let ety = ty::expr_ty_adjusted(cx.tcx, e);
157-
let llty = type_of::sizing_type_of(cx, ety);
158-
let llconst = const_expr_unchecked(cx, e);
141+
let mut llconst = const_expr_unadjusted(cx, e);
142+
let ety = ty::expr_ty(cx.tcx, e);
143+
match cx.tcx.adjustments.find(&e.id) {
144+
None => { }
145+
Some(@ty::AutoAddEnv(ty::re_static, ast::BorrowedSigil)) => {
146+
llconst = C_struct(~[llconst, C_null(T_opaque_box_ptr(cx))])
147+
}
148+
Some(@ty::AutoAddEnv(ref r, ref s)) => {
149+
cx.sess.span_bug(e.span, fmt!("unexpected const function: \
150+
region %? sigil %?", *r, *s))
151+
}
152+
Some(@ty::AutoDerefRef(ref adj)) => {
153+
for adj.autoderefs.times {
154+
llconst = const_deref(cx, llconst)
155+
}
156+
157+
match adj.autoref {
158+
None => { }
159+
Some(ref autoref) => {
160+
fail_unless!(autoref.region == ty::re_static);
161+
fail_unless!(autoref.mutbl != ast::m_mutbl);
162+
match autoref.kind {
163+
ty::AutoPtr => {
164+
llconst = const_addr_of(cx, llconst);
165+
}
166+
ty::AutoBorrowVec => {
167+
let base = const_addr_of(cx, llconst);
168+
let size = machine::llsize_of(cx,
169+
val_ty(llconst));
170+
fail_unless!(abi::slice_elt_base == 0);
171+
fail_unless!(abi::slice_elt_len == 1);
172+
llconst = C_struct(~[base, size]);
173+
}
174+
_ => {
175+
cx.sess.span_bug(e.span,
176+
fmt!("unimplemented const \
177+
autoref %?", autoref))
178+
}
179+
}
180+
}
181+
}
182+
}
183+
}
184+
185+
let ety_adjusted = ty::expr_ty_adjusted(cx.tcx, e);
186+
let llty = type_of::sizing_type_of(cx, ety_adjusted);
159187
let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
160188
let tsize = machine::llsize_of_alloc(cx, llty);
161189
if csize != tsize {
162190
unsafe {
191+
// XXX these values could use some context
163192
llvm::LLVMDumpValue(llconst);
164-
llvm::LLVMDumpValue(C_null(llty));
193+
llvm::LLVMDumpValue(C_undef(llty));
165194
}
166195
cx.sess.bug(fmt!("const %s of type %s has size %u instead of %u",
167196
expr_repr(cx.tcx, e), ty_to_str(cx.tcx, ety),
@@ -170,7 +199,7 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
170199
llconst
171200
}
172201

173-
fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
202+
fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
174203
unsafe {
175204
let _icx = cx.insn_ctxt("const_expr");
176205
return match /*bad*/copy e.node {
@@ -254,20 +283,18 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
254283
}
255284
}
256285
ast::expr_field(base, field, _) => {
257-
let bt = ty::expr_ty(cx.tcx, base);
286+
let bt = ty::expr_ty_adjusted(cx.tcx, base);
258287
let brepr = adt::represent_type(cx, bt);
259288
let bv = const_expr(cx, base);
260-
let (bt, bv) = const_autoderef(cx, bt, bv);
261289
do expr::with_field_tys(cx.tcx, bt, None) |discr, field_tys| {
262290
let ix = ty::field_idx_strict(cx.tcx, field, field_tys);
263291
adt::const_get_field(cx, brepr, bv, discr, ix)
264292
}
265293
}
266294

267295
ast::expr_index(base, index) => {
268-
let bt = ty::expr_ty(cx.tcx, base);
296+
let bt = ty::expr_ty_adjusted(cx.tcx, base);
269297
let bv = const_expr(cx, base);
270-
let (bt, bv) = const_autoderef(cx, bt, bv);
271298
let iv = match const_eval::eval_const_expr(cx.tcx, index) {
272299
const_eval::const_int(i) => i as u64,
273300
const_eval::const_uint(u) => u,
@@ -425,26 +452,12 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
425452
fail_unless!(pth.types.len() == 0);
426453
match cx.tcx.def_map.find(&e.id) {
427454
Some(ast::def_fn(def_id, _purity)) => {
428-
let f = if !ast_util::is_local(def_id) {
455+
if !ast_util::is_local(def_id) {
429456
let ty = csearch::get_type(cx.tcx, def_id).ty;
430457
base::trans_external_path(cx, def_id, ty)
431458
} else {
432459
fail_unless!(ast_util::is_local(def_id));
433460
base::get_item_val(cx, def_id.node)
434-
};
435-
let ety = ty::expr_ty_adjusted(cx.tcx, e);
436-
match ty::get(ety).sty {
437-
ty::ty_bare_fn(*) | ty::ty_ptr(*) => {
438-
llvm::LLVMConstPointerCast(f, T_ptr(T_i8()))
439-
}
440-
ty::ty_closure(*) => {
441-
C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
442-
}
443-
_ => {
444-
cx.sess.span_bug(e.span, fmt!(
445-
"unexpected const fn type: %s",
446-
ty_to_str(cx.tcx, ety)))
447-
}
448461
}
449462
}
450463
Some(ast::def_const(def_id)) => {

0 commit comments

Comments
 (0)