Skip to content

Commit 07b8500

Browse files
authored
Merge pull request rust-lang#57 from oli-obk/master
fix enum down casting and backtrace panics
2 parents c1ae916 + 75ccfd5 commit 07b8500

File tree

6 files changed

+362
-173
lines changed

6 files changed

+362
-173
lines changed

src/interpreter/mod.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -907,9 +907,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
907907
Downcast(_, variant) => {
908908
use rustc::ty::layout::Layout::*;
909909
match *base_layout {
910-
General { discr, .. } => {
910+
General { ref variants, .. } => {
911911
return Ok(Lvalue {
912-
ptr: base.ptr.offset(discr.size().bytes() as isize),
912+
ptr: base.ptr.offset(variants[variant].field_offset(1).bytes() as isize),
913913
extra: LvalueExtra::DowncastVariant(variant),
914914
});
915915
}
@@ -1188,13 +1188,7 @@ fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
11881188
ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[])
11891189
}
11901190
}
1191-
let inst = Instance(def_id, substs);
1192-
match ::std::panic::catch_unwind(|| {
1193-
format!("inside call to {}", inst)
1194-
}) {
1195-
Ok(msg) => err.span_note(span, &msg),
1196-
Err(_) => err.span_note(span, &format!("ppaux::parameterized failed: {:?}, {:?}", def_id, substs)),
1197-
};
1191+
err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
11981192
}
11991193
err.emit();
12001194
}
+251
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
use rustc::hir::def_id::DefId;
2+
use rustc::mir::repr as mir;
3+
use rustc::ty::layout::Layout;
4+
use rustc::ty::subst::Substs;
5+
use rustc::ty;
6+
7+
use error::{EvalError, EvalResult};
8+
use memory::Pointer;
9+
use interpreter::EvalContext;
10+
use primval;
11+
12+
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13+
pub(super) fn call_intrinsic(
14+
&mut self,
15+
def_id: DefId,
16+
substs: &'tcx Substs<'tcx>,
17+
args: &[mir::Operand<'tcx>],
18+
dest: Pointer,
19+
dest_layout: &'tcx Layout,
20+
) -> EvalResult<'tcx, ()> {
21+
// TODO(solson): We can probably remove this _to_ptr easily.
22+
let args_res: EvalResult<Vec<Pointer>> = args.iter()
23+
.map(|arg| self.eval_operand_to_ptr(arg))
24+
.collect();
25+
let args_ptrs = args_res?;
26+
let pointer_size = self.memory.pointer_size();
27+
28+
match &self.tcx.item_name(def_id).as_str()[..] {
29+
"add_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Add, &args[0], &args[1], dest, dest_layout)?,
30+
"sub_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Sub, &args[0], &args[1], dest, dest_layout)?,
31+
"mul_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Mul, &args[0], &args[1], dest, dest_layout)?,
32+
33+
"arith_offset" => {
34+
let ptr = self.memory.read_ptr(args_ptrs[0])?;
35+
let offset = self.memory.read_int(args_ptrs[1], pointer_size)?;
36+
let new_ptr = ptr.offset(offset as isize);
37+
self.memory.write_ptr(dest, new_ptr)?;
38+
}
39+
40+
"assume" => {
41+
if !self.memory.read_bool(args_ptrs[0])? {
42+
return Err(EvalError::AssumptionNotHeld);
43+
}
44+
}
45+
46+
"breakpoint" => unimplemented!(), // halt miri
47+
48+
"copy" |
49+
"copy_nonoverlapping" => {
50+
// FIXME: check whether overlapping occurs
51+
let elem_ty = substs.type_at(0);
52+
let elem_size = self.type_size(elem_ty);
53+
let elem_align = self.type_align(elem_ty);
54+
let src = self.memory.read_ptr(args_ptrs[0])?;
55+
let dest = self.memory.read_ptr(args_ptrs[1])?;
56+
let count = self.memory.read_isize(args_ptrs[2])?;
57+
self.memory.copy(src, dest, count as usize * elem_size, elem_align)?;
58+
}
59+
60+
"ctpop" => {
61+
let elem_ty = substs.type_at(0);
62+
let elem_size = self.type_size(elem_ty);
63+
let num = self.memory.read_uint(args_ptrs[0], elem_size)?.count_ones();
64+
self.memory.write_uint(dest, num.into(), elem_size)?;
65+
}
66+
67+
"ctlz" => {
68+
let elem_ty = substs.type_at(0);
69+
let elem_size = self.type_size(elem_ty);
70+
let num = self.memory.read_uint(args_ptrs[0], elem_size)?.leading_zeros();
71+
self.memory.write_uint(dest, num.into(), elem_size)?;
72+
}
73+
74+
"discriminant_value" => {
75+
let ty = substs.type_at(0);
76+
let adt_ptr = self.memory.read_ptr(args_ptrs[0])?;
77+
let discr_val = self.read_discriminant_value(adt_ptr, ty)?;
78+
self.memory.write_uint(dest, discr_val, 8)?;
79+
}
80+
81+
"fabsf32" => {
82+
let f = self.memory.read_f32(args_ptrs[0])?;
83+
self.memory.write_f32(dest, f.abs())?;
84+
}
85+
86+
"fabsf64" => {
87+
let f = self.memory.read_f64(args_ptrs[0])?;
88+
self.memory.write_f64(dest, f.abs())?;
89+
}
90+
91+
"fadd_fast" => {
92+
let ty = substs.type_at(0);
93+
let a = self.read_primval(args_ptrs[0], ty)?;
94+
let b = self.read_primval(args_ptrs[0], ty)?;
95+
let result = primval::binary_op(mir::BinOp::Add, a, b)?;
96+
self.memory.write_primval(dest, result.0)?;
97+
}
98+
99+
"likely" |
100+
"unlikely" |
101+
"forget" => {}
102+
103+
"init" => self.memory.write_repeat(dest, 0, dest_layout.size(&self.tcx.data_layout).bytes() as usize)?,
104+
105+
"min_align_of" => {
106+
let elem_ty = substs.type_at(0);
107+
let elem_align = self.type_align(elem_ty);
108+
self.memory.write_uint(dest, elem_align as u64, pointer_size)?;
109+
}
110+
111+
"pref_align_of" => {
112+
let ty = substs.type_at(0);
113+
let layout = self.type_layout(ty);
114+
let align = layout.align(&self.tcx.data_layout).pref();
115+
self.memory.write_uint(dest, align, pointer_size)?;
116+
}
117+
118+
"move_val_init" => {
119+
let ty = substs.type_at(0);
120+
let ptr = self.memory.read_ptr(args_ptrs[0])?;
121+
self.move_(args_ptrs[1], ptr, ty)?;
122+
}
123+
124+
"needs_drop" => {
125+
let ty = substs.type_at(0);
126+
self.memory.write_bool(dest, self.tcx.type_needs_drop_given_env(ty, &self.tcx.empty_parameter_environment()))?;
127+
}
128+
129+
"offset" => {
130+
let pointee_ty = substs.type_at(0);
131+
let pointee_size = self.type_size(pointee_ty) as isize;
132+
let ptr_arg = args_ptrs[0];
133+
let offset = self.memory.read_isize(args_ptrs[1])?;
134+
135+
match self.memory.read_ptr(ptr_arg) {
136+
Ok(ptr) => {
137+
let result_ptr = ptr.offset(offset as isize * pointee_size);
138+
self.memory.write_ptr(dest, result_ptr)?;
139+
}
140+
Err(EvalError::ReadBytesAsPointer) => {
141+
let addr = self.memory.read_isize(ptr_arg)?;
142+
let result_addr = addr + offset * pointee_size as i64;
143+
self.memory.write_isize(dest, result_addr)?;
144+
}
145+
Err(e) => return Err(e),
146+
}
147+
}
148+
149+
"overflowing_sub" => {
150+
self.intrinsic_overflowing(mir::BinOp::Sub, &args[0], &args[1], dest)?;
151+
}
152+
153+
"overflowing_mul" => {
154+
self.intrinsic_overflowing(mir::BinOp::Mul, &args[0], &args[1], dest)?;
155+
}
156+
157+
"overflowing_add" => {
158+
self.intrinsic_overflowing(mir::BinOp::Add, &args[0], &args[1], dest)?;
159+
}
160+
161+
"powif32" => {
162+
let f = self.memory.read_f32(args_ptrs[0])?;
163+
let i = self.memory.read_int(args_ptrs[1], 4)?;
164+
self.memory.write_f32(dest, f.powi(i as i32))?;
165+
}
166+
167+
"powif64" => {
168+
let f = self.memory.read_f32(args_ptrs[0])?;
169+
let i = self.memory.read_int(args_ptrs[1], 4)?;
170+
self.memory.write_f32(dest, f.powi(i as i32))?;
171+
}
172+
173+
"sqrtf32" => {
174+
let f = self.memory.read_f32(args_ptrs[0])?;
175+
self.memory.write_f32(dest, f.sqrt())?;
176+
}
177+
178+
"sqrtf64" => {
179+
let f = self.memory.read_f64(args_ptrs[0])?;
180+
self.memory.write_f64(dest, f.sqrt())?;
181+
}
182+
183+
"size_of" => {
184+
let ty = substs.type_at(0);
185+
let size = self.type_size(ty) as u64;
186+
self.memory.write_uint(dest, size, pointer_size)?;
187+
}
188+
189+
"size_of_val" => {
190+
let ty = substs.type_at(0);
191+
if self.type_is_sized(ty) {
192+
let size = self.type_size(ty) as u64;
193+
self.memory.write_uint(dest, size, pointer_size)?;
194+
} else {
195+
match ty.sty {
196+
ty::TySlice(_) | ty::TyStr => {
197+
let elem_ty = ty.sequence_element_type(self.tcx);
198+
let elem_size = self.type_size(elem_ty) as u64;
199+
let ptr_size = self.memory.pointer_size() as isize;
200+
let n = self.memory.read_usize(args_ptrs[0].offset(ptr_size))?;
201+
self.memory.write_uint(dest, n * elem_size, pointer_size)?;
202+
}
203+
204+
_ => return Err(EvalError::Unimplemented(format!("unimplemented: size_of_val::<{:?}>", ty))),
205+
}
206+
}
207+
}
208+
// FIXME: wait for eval_operand_to_ptr to be gone
209+
/*
210+
"type_name" => {
211+
let ty = substs.type_at(0);
212+
let ty_name = ty.to_string();
213+
let s = self.str_to_value(&ty_name)?;
214+
self.memory.write_ptr(dest, s)?;
215+
}*/
216+
"type_id" => {
217+
let ty = substs.type_at(0);
218+
let n = self.tcx.type_id_hash(ty);
219+
self.memory.write_uint(dest, n, 8)?;
220+
}
221+
222+
"transmute" => {
223+
let ty = substs.type_at(0);
224+
self.move_(args_ptrs[0], dest, ty)?;
225+
}
226+
227+
"try" => unimplemented!(),
228+
229+
"uninit" => self.memory.mark_definedness(dest, dest_layout.size(&self.tcx.data_layout).bytes() as usize, false)?,
230+
231+
"volatile_load" => {
232+
let ty = substs.type_at(0);
233+
let ptr = self.memory.read_ptr(args_ptrs[0])?;
234+
self.move_(ptr, dest, ty)?;
235+
}
236+
237+
"volatile_store" => {
238+
let ty = substs.type_at(0);
239+
let dest = self.memory.read_ptr(args_ptrs[0])?;
240+
self.move_(args_ptrs[1], dest, ty)?;
241+
}
242+
243+
name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))),
244+
}
245+
246+
// Since we pushed no stack frame, the main loop will act
247+
// as if the call just completed and it's returning to the
248+
// current frame.
249+
Ok(())
250+
}
251+
}

0 commit comments

Comments
 (0)