Skip to content

Commit a30e836

Browse files
committed
Fix some simd intrinsics
1 parent ec72e17 commit a30e836

File tree

5 files changed

+85
-24
lines changed

5 files changed

+85
-24
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -684,24 +684,24 @@ impl<Tag: Copy, Extra: Default> Allocation<Tag, Extra> {
684684
offset: Size,
685685
size: Size,
686686
) -> EvalResult<'tcx> {
687-
if self.relocations(hdl, offset, size)?.len() != 0 {
687+
if self.relocations(hdl, offset, size).len() != 0 {
688688
err!(ReadPointerAsBytes)
689689
} else {
690690
Ok(())
691691
}
692692
}
693693

694-
pub fn relocations(
694+
fn relocations(
695695
&self,
696696
hdl: impl HasDataLayout,
697697
offset: Size,
698698
size: Size,
699-
) -> EvalResult<'tcx, &[(Size, (Tag, AllocId))]> {
699+
) -> &[(Size, (Tag, AllocId))] {
700700
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
701701
// the beginning of this range.
702-
let start = offset.bytes().saturating_sub(hdl.pointer_size().bytes() - 1);
702+
let start = offset.bytes().saturating_sub(hdl.data_layout().pointer_size.bytes() - 1);
703703
let end = offset + size; // this does overflow checking
704-
Ok(self.relocations.range(Size::from_bytes(start)..end))
704+
self.relocations.range(Size::from_bytes(start)..end)
705705
}
706706

707707
pub fn get_bytes(
@@ -736,22 +736,23 @@ impl<Tag: Copy, Extra: Default> Allocation<Tag, Extra> {
736736
&self,
737737
hdl: impl HasDataLayout,
738738
offset: Size,
739+
size: Size,
740+
align: Align,
739741
) -> EvalResult<'tcx, Scalar<Tag>> {
740-
let size = hdl.data_layout().pointer_size;
741-
let required_align = hdl.data_layout().pointer_align;
742-
self.check_align(offset, required_align)?;
742+
self.check_align(offset, align)?;
743743
self.check_bounds(offset, size, true)?;
744744
self.check_defined(offset, size)?;
745745
let bytes = self.bytes_ignoring_relocations_and_undef(offset, size);
746-
let offset = read_target_uint(hdl.data_layout().endian, &bytes).unwrap();
747-
let offset = Size::from_bytes(offset as u64);
748-
if let Some(&(tag, alloc_id)) = self.relocations.get(&offset) {
749-
Ok(Pointer::new_with_tag(alloc_id, offset, tag).into())
750-
} else {
751-
Ok(Scalar::Bits {
752-
bits: offset.bytes() as u128,
746+
let int = read_target_uint(hdl.data_layout().endian, &bytes).unwrap();
747+
match self.relocations(hdl, offset, size) {
748+
&[(_, (tag, alloc_id))] if size == hdl.data_layout().pointer_size => {
749+
Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(int as u64), tag).into())
750+
},
751+
&[] => Ok(Scalar::Bits {
752+
bits: int,
753753
size: size.bytes() as u8,
754-
})
754+
}),
755+
_ => err!(ReadPointerAsBytes),
755756
}
756757
}
757758

src/librustc/mir/interpret/value.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ impl<'tcx> ConstValue<'tcx> {
7575
hdl: impl HasDataLayout,
7676
) -> Option<Pointer> {
7777
let (_, alloc, offset) = self.try_as_by_ref()?;
78-
alloc.read_scalar(hdl, offset).ok()?.to_ptr().ok()
78+
let size = hdl.data_layout().pointer_size;
79+
let required_align = hdl.data_layout().pointer_align;
80+
alloc.read_scalar(hdl, offset, size, required_align).ok()?.to_ptr().ok()
7981
}
8082

8183
/// e.g. for vtables, fat pointers or single pointers

src/librustc/mir/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2487,7 +2487,9 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const<'_>) -> fmt::Resu
24872487
},
24882488
// print string literals
24892489
Ref(_, &ty::TyS { sty: Str, .. }, _) => {
2490-
let ptr = ty::tls::with(|tcx| alloc.read_scalar(tcx, offset));
2490+
let ptr = ty::tls::with(|tcx| alloc.read_scalar(
2491+
tcx, offset, tcx.data_layout.pointer_size, tcx.data_layout.pointer_align,
2492+
));
24912493
let ptr = ptr.and_then(Scalar::to_ptr);
24922494
if let Ok(ptr) = ptr {
24932495
let len = ty::tls::with(|tcx| alloc.read_bits(

src/librustc_codegen_llvm/mir/constant.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
181181
constant
182182
.and_then(|c| {
183183
let field_ty = c.ty.builtin_index().unwrap();
184+
let layout = bx.cx.layout_of(field_ty);
184185
let fields = match c.ty.sty {
185186
ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
186187
ref other => bug!("invalid simd shuffle type: {}", other),
@@ -195,8 +196,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
195196
c,
196197
)?;
197198
// FIXME(oli-obk): are these indices always usize?
198-
if let Some(prim) = field.val.try_to_usize(bx.tcx()) {
199-
let layout = bx.cx.layout_of(field_ty);
199+
if let Some(prim) = field.val.try_to_bits(bx.tcx(), layout) {
200200
let scalar = match layout.abi {
201201
layout::Abi::Scalar(ref x) => x,
202202
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout)

src/librustc_codegen_llvm/mir/operand.rs

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc::mir;
1313
use rustc::ty;
1414
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
1515
use rustc_data_structures::sync::Lrc;
16+
use syntax_pos::Span;
1617

1718
use base;
1819
use common::{CodegenCx, C_undef, C_usize};
@@ -25,6 +26,7 @@ use glue;
2526
use std::fmt;
2627

2728
use super::{FunctionCx, LocalRef};
29+
use super::constant::scalar_to_llvm;
2830
use super::place::PlaceRef;
2931

3032
/// The representation of a Rust value. The enum variant is in fact
@@ -77,6 +79,7 @@ impl OperandRef<'ll, 'tcx> {
7779
}
7880

7981
pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
82+
span: Span,
8083
val: &'tcx ty::Const<'tcx>)
8184
-> Result<OperandRef<'ll, 'tcx>, Lrc<ConstEvalErr<'tcx>>> {
8285
let layout = bx.cx.layout_of(val.ty);
@@ -85,12 +88,65 @@ impl OperandRef<'ll, 'tcx> {
8588
return Ok(OperandRef::new_zst(bx.cx, layout));
8689
}
8790

88-
match val.val {
91+
let econv = |err| ConstEvalErr {
92+
error: err,
93+
stacktrace: Vec::new(),
94+
span,
95+
};
96+
97+
let val = match val.val {
8998
ConstValue::Unevaluated(..) => bug!(),
9099
ConstValue::ByRef(_, alloc, offset) => {
91-
Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx))
100+
// FIXME: the first two arms are needed for simd_simple_float_intrinsic which reads
101+
// the constants back from llvm values. We can probably do better.
102+
match layout.abi {
103+
layout::Abi::Scalar(ref scalar) => {
104+
let x = alloc.read_scalar(
105+
bx.tcx(), offset, layout.size, layout.align,
106+
).map_err(econv)?;
107+
let llval = scalar_to_llvm(
108+
bx.cx,
109+
x,
110+
scalar,
111+
layout.immediate_llvm_type(bx.cx),
112+
);
113+
OperandValue::Immediate(llval)
114+
},
115+
layout::Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
116+
let a_size = a_scalar.value.size(bx.tcx());
117+
let a = alloc.read_scalar(
118+
bx.tcx(), offset, a_size, a_scalar.value.align(bx.tcx()),
119+
).map_err(econv)?;
120+
let b_align = b_scalar.value.align(bx.tcx());
121+
let b_offset = offset + a_size.abi_align(b_align);
122+
let b_size = b_scalar.value.size(bx.tcx());
123+
let b = alloc.read_scalar(
124+
bx.tcx(), b_offset, b_size, b_align,
125+
).map_err(econv)?;
126+
let a_llval = scalar_to_llvm(
127+
bx.cx,
128+
a,
129+
a_scalar,
130+
layout.scalar_pair_element_llvm_type(bx.cx, 0, true),
131+
);
132+
let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true);
133+
let b_llval = scalar_to_llvm(
134+
bx.cx,
135+
b,
136+
b_scalar,
137+
b_layout,
138+
);
139+
OperandValue::Pair(a_llval, b_llval)
140+
},
141+
_ => return Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx)),
142+
}
92143
},
93-
}
144+
};
145+
146+
Ok(OperandRef {
147+
val,
148+
layout
149+
})
94150
}
95151

96152
/// Asserts that this operand refers to a scalar and returns
@@ -383,7 +439,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
383439
mir::Operand::Constant(ref constant) => {
384440
let ty = self.monomorphize(&constant.ty);
385441
self.eval_mir_constant(bx, constant)
386-
.and_then(|c| OperandRef::from_const(bx, c))
442+
.and_then(|c| OperandRef::from_const(bx, constant.span, c))
387443
.unwrap_or_else(|err| {
388444
err.report_as_error(
389445
bx.tcx().at(constant.span),

0 commit comments

Comments
 (0)