Skip to content

Commit e1eca0a

Browse files
committed
Translate constants from MIR instead of going through trans::expr/consts.
1 parent 4639128 commit e1eca0a

13 files changed

+858
-151
lines changed

src/librustc_trans/consts.rs

+40-39
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
3939
use rustc::ty::{self, Ty, TyCtxt};
4040
use rustc::ty::cast::{CastTy,IntTy};
4141
use util::nodemap::NodeMap;
42-
use rustc_const_math::{ConstInt, ConstMathErr, ConstUsize, ConstIsize};
42+
use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
4343

4444
use rustc::hir;
4545

@@ -48,6 +48,7 @@ use std::borrow::Cow;
4848
use libc::c_uint;
4949
use syntax::ast::{self, LitKind};
5050
use syntax::attr::{self, AttrMetaMethods};
51+
use syntax::codemap::Span;
5152
use syntax::parse::token;
5253
use syntax::ptr::P;
5354

@@ -110,11 +111,11 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
110111
}
111112
}
112113

113-
fn addr_of_mut(ccx: &CrateContext,
114-
cv: ValueRef,
115-
align: machine::llalign,
116-
kind: &str)
117-
-> ValueRef {
114+
pub fn addr_of_mut(ccx: &CrateContext,
115+
cv: ValueRef,
116+
align: machine::llalign,
117+
kind: &str)
118+
-> ValueRef {
118119
unsafe {
119120
// FIXME: this totally needs a better name generation scheme, perhaps a simple global
120121
// counter? Also most other uses of gensym in trans.
@@ -158,13 +159,13 @@ pub fn addr_of(ccx: &CrateContext,
158159
}
159160

160161
/// Deref a constant pointer
161-
fn load_const(cx: &CrateContext, v: ValueRef, t: Ty) -> ValueRef {
162+
pub fn load_const(cx: &CrateContext, v: ValueRef, t: Ty) -> ValueRef {
162163
let v = match cx.const_unsized().borrow().get(&v) {
163164
Some(&v) => v,
164165
None => v
165166
};
166167
let d = unsafe { llvm::LLVMGetInitializer(v) };
167-
if t.is_bool() {
168+
if !d.is_null() && t.is_bool() {
168169
unsafe { llvm::LLVMConstTrunc(d, Type::i1(cx).to_ref()) }
169170
} else {
170171
d
@@ -466,16 +467,12 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
466467
Some(v) => v,
467468
None => return Ok(()),
468469
};
469-
match -cval {
470-
Ok(_) => return Ok(()),
471-
Err(err) => const_err(cx, e, Err(err), trueconst),
472-
}
473-
} else {
474-
Ok(())
470+
const_err(cx, e.span, (-cval).map_err(ErrKind::Math), trueconst)?;
475471
}
472+
Ok(())
476473
}
477474

478-
fn to_const_int(value: ValueRef, t: Ty, tcx: &TyCtxt) -> Option<ConstInt> {
475+
pub fn to_const_int(value: ValueRef, t: Ty, tcx: &TyCtxt) -> Option<ConstInt> {
479476
match t.sty {
480477
ty::TyInt(int_type) => const_to_opt_int(value).and_then(|input| match int_type {
481478
ast::IntTy::I8 => {
@@ -523,24 +520,21 @@ fn to_const_int(value: ValueRef, t: Ty, tcx: &TyCtxt) -> Option<ConstInt> {
523520
}
524521
}
525522

526-
fn const_err(cx: &CrateContext,
527-
e: &hir::Expr,
528-
result: Result<ConstInt, ConstMathErr>,
529-
trueconst: TrueConst)
530-
-> Result<(), ConstEvalFailure> {
523+
pub fn const_err<T>(cx: &CrateContext,
524+
span: Span,
525+
result: Result<T, ErrKind>,
526+
trueconst: TrueConst)
527+
-> Result<T, ConstEvalFailure> {
531528
match (result, trueconst) {
532-
(Ok(_), _) => {
533-
// We do not actually care about a successful result.
534-
Ok(())
535-
},
529+
(Ok(x), _) => Ok(x),
536530
(Err(err), TrueConst::Yes) => {
537-
let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) };
538-
cx.tcx().sess.span_err(e.span, &err.description());
531+
let err = ConstEvalErr{ span: span, kind: err };
532+
cx.tcx().sess.span_err(span, &err.description());
539533
Err(Compiletime(err))
540534
},
541535
(Err(err), TrueConst::No) => {
542-
let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) };
543-
cx.tcx().sess.span_warn(e.span, &err.description());
536+
let err = ConstEvalErr{ span: span, kind: err };
537+
cx.tcx().sess.span_warn(span, &err.description());
544538
Err(Runtime(err))
545539
},
546540
}
@@ -564,7 +558,8 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
564558
hir::BiShr => lhs >> rhs,
565559
_ => return Ok(()),
566560
};
567-
const_err(cx, e, result, trueconst)
561+
const_err(cx, e.span, result.map_err(ErrKind::Math), trueconst)?;
562+
Ok(())
568563
}
569564

570565
fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -719,8 +714,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
719714
if iv >= len {
720715
// FIXME #3170: report this earlier on in the const-eval
721716
// pass. Reporting here is a bit late.
722-
span_err!(cx.sess(), e.span, E0515,
723-
"const index-expr is out of bounds");
717+
const_err(cx, e.span, Err(ErrKind::IndexOutOfBounds), trueconst)?;
724718
C_undef(val_ty(arr).element_type())
725719
} else {
726720
const_get_elt(arr, &[iv as c_uint])
@@ -1128,6 +1122,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
11281122
};
11291123

11301124
ccx.instances().borrow_mut().insert(instance, g);
1125+
ccx.statics().borrow_mut().insert(g, def_id);
11311126
Datum::new(g, ty, Lvalue::new("static"))
11321127
}
11331128

@@ -1147,14 +1142,20 @@ pub fn trans_static(ccx: &CrateContext,
11471142
let def_id = ccx.tcx().map.local_def_id(id);
11481143
let datum = get_static(ccx, def_id);
11491144

1150-
let empty_substs = ccx.tcx().mk_substs(Substs::empty());
1151-
let (v, _) = const_expr(
1152-
ccx,
1153-
expr,
1154-
empty_substs,
1155-
None,
1156-
TrueConst::Yes,
1157-
).map_err(|e| e.into_inner())?;
1145+
let check_attrs = |attrs: &[ast::Attribute]| {
1146+
let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
1147+
let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
1148+
default_to_mir ^ attrs.iter().any(|item| item.check_name(invert))
1149+
};
1150+
let use_mir = check_attrs(ccx.tcx().map.attrs(id));
1151+
1152+
let v = if use_mir {
1153+
::mir::trans_static_initializer(ccx, def_id)
1154+
} else {
1155+
let empty_substs = ccx.tcx().mk_substs(Substs::empty());
1156+
const_expr(ccx, expr, empty_substs, None, TrueConst::Yes)
1157+
.map(|(v, _)| v)
1158+
}.map_err(|e| e.into_inner())?;
11581159

11591160
// boolean SSA values are i1, but they have to be stored in i8 slots,
11601161
// otherwise some LLVM optimization passes don't work as expected

src/librustc_trans/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ pub struct LocalCrateContext<'tcx> {
131131
/// Cache of external const values
132132
extern_const_values: RefCell<DefIdMap<ValueRef>>,
133133

134+
/// Mapping from static definitions to their DefId's.
135+
statics: RefCell<FnvHashMap<ValueRef, DefId>>,
136+
134137
impl_method_cache: RefCell<FnvHashMap<(DefId, ast::Name), DefId>>,
135138

136139
/// Cache of closure wrappers for bare fn's.
@@ -495,6 +498,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
495498
const_globals: RefCell::new(FnvHashMap()),
496499
const_values: RefCell::new(FnvHashMap()),
497500
extern_const_values: RefCell::new(DefIdMap()),
501+
statics: RefCell::new(FnvHashMap()),
498502
impl_method_cache: RefCell::new(FnvHashMap()),
499503
closure_bare_wrapper_cache: RefCell::new(FnvHashMap()),
500504
statics_to_rauw: RefCell::new(Vec::new()),
@@ -699,6 +703,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
699703
&self.local.extern_const_values
700704
}
701705

706+
pub fn statics<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, DefId>> {
707+
&self.local.statics
708+
}
709+
702710
pub fn impl_method_cache<'a>(&'a self)
703711
-> &'a RefCell<FnvHashMap<(DefId, ast::Name), DefId>> {
704712
&self.local.impl_method_cache

src/librustc_trans/diagnostics.rs

-15
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,4 @@ extern "platform-intrinsic" {
8282
unsafe { simd_add(i32x1(0), i32x1(1)); } // ok!
8383
```
8484
"##,
85-
86-
E0515: r##"
87-
A constant index expression was out of bounds. Erroneous code example:
88-
89-
```compile_fail
90-
let x = &[0, 1, 2][7]; // error: const index-expr is out of bounds
91-
```
92-
93-
Please specify a valid index (not inferior to 0 or superior to array length).
94-
Example:
95-
96-
```
97-
let x = &[0, 1, 2][2]; // ok
98-
```
99-
"##,
10085
}

src/librustc_trans/mir/block.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
114114
let discr = bcx.with_block(|bcx| base::to_immediate(bcx, discr, switch_ty));
115115
let switch = bcx.switch(discr, self.llblock(*otherwise), values.len());
116116
for (value, target) in values.iter().zip(targets) {
117-
let llval = self.trans_constval(&bcx, value, switch_ty).immediate();
117+
let constant = mir::Constant {
118+
literal: mir::Literal::Value {
119+
value: value.clone()
120+
},
121+
ty: switch_ty,
122+
span: terminator.span
123+
};
124+
let val = self.trans_constant(&bcx, &constant).immediate();
118125
let llbb = self.llblock(*target);
119-
build::AddCase(switch, llval, llbb)
126+
build::AddCase(switch, val, llbb)
120127
}
121128
}
122129

0 commit comments

Comments
 (0)