diff options
| author | James Cowgill <jcowgill@debian.org> | 2018-02-14 12:47:38 +0000 |
|---|---|---|
| committer | James Cowgill <jcowgill@debian.org> | 2018-02-14 14:38:55 +0000 |
| commit | 05d66dc7a4ff053b5cbfa5ddafa890af291f4fc2 (patch) | |
| tree | b656c0202d7288fcb048f43983670e55eaddf53f | |
| parent | 68042ba0d35f16d66dadf62334ca6bbf20d97268 (diff) | |
| download | rust-05d66dc7a4ff053b5cbfa5ddafa890af291f4fc2.tar.gz rust-05d66dc7a4ff053b5cbfa5ddafa890af291f4fc2.zip | |
rustc_trans: add chunked prefix fields to CastTarget
| -rw-r--r-- | src/librustc_trans/abi.rs | 138 | ||||
| -rw-r--r-- | src/librustc_trans/cabi_x86_64.rs | 2 |
2 files changed, 53 insertions, 87 deletions
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 60f3105170b..ee0f2415bd8 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -40,7 +40,7 @@ use rustc::ty::layout::{self, Align, Size, TyLayout}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; use libc::c_uint; -use std::{cmp, iter}; +use std::cmp; pub use syntax::abi::Abi; pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; @@ -279,30 +279,6 @@ impl Uniform { pub fn align(&self, cx: &CodegenCx) -> Align { self.unit.align(cx) } - - pub fn llvm_type(&self, cx: &CodegenCx) -> Type { - let llunit = self.unit.llvm_type(cx); - - if self.total <= self.unit.size { - return llunit; - } - - let count = self.total.bytes() / self.unit.size.bytes(); - let rem_bytes = self.total.bytes() % self.unit.size.bytes(); - - if rem_bytes == 0 { - return Type::array(&llunit, count); - } - - // Only integers can be really split further. - assert_eq!(self.unit.kind, RegKind::Integer); - - let args: Vec<_> = (0..count).map(|_| llunit) - .chain(iter::once(Type::ix(cx, rem_bytes * 8))) - .collect(); - - Type::struct_(cx, &args, false) - } } pub trait LayoutExt<'tcx> { @@ -405,91 +381,81 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum CastTarget { - Uniform(Uniform), - Pair(Reg, Reg), - ChunkedPrefix { prefix: [RegKind; 8], chunk: Size, total: Size } +pub struct CastTarget { + pub prefix: [Option<RegKind>; 8], + pub prefix_chunk: Size, + pub rest: Uniform, } impl From<Reg> for CastTarget { fn from(unit: Reg) -> CastTarget { - CastTarget::Uniform(Uniform::from(unit)) + CastTarget::from(Uniform::from(unit)) } } impl From<Uniform> for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget::Uniform(uniform) + CastTarget { + prefix: [None; 8], + prefix_chunk: Size::from_bytes(0), + rest: uniform + } } } impl CastTarget { - pub fn size(&self, cx: &CodegenCx) -> Size { - match *self { - CastTarget::Uniform(u) => u.total, - CastTarget::Pair(a, b) => { - (a.size.abi_align(a.align(cx)) + b.size) - .abi_align(self.align(cx)) - }, - CastTarget::ChunkedPrefix { total, .. } => total + pub fn pair(a: Reg, b: Reg) -> CastTarget { + CastTarget { + prefix: [Some(a.kind), None, None, None, None, None, None, None], + prefix_chunk: a.size, + rest: Uniform::from(b) } } + pub fn size(&self, cx: &CodegenCx) -> Size { + (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) + .abi_align(self.rest.align(cx)) + self.rest.total + } + pub fn align(&self, cx: &CodegenCx) -> Align { - match *self { - CastTarget::Uniform(u) => u.align(cx), - CastTarget::Pair(a, b) => { - cx.data_layout().aggregate_align - .max(a.align(cx)) - .max(b.align(cx)) - }, - CastTarget::ChunkedPrefix { chunk, .. } => { - cx.data_layout().aggregate_align - .max(Reg { kind: RegKind::Integer, size: chunk }.align(cx)) - .max(Reg { kind: RegKind::Float, size: chunk }.align(cx)) - .max(Reg { kind: RegKind::Vector, size: chunk }.align(cx)) - } - } + self.prefix.iter() + .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx))) + .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), + |acc, align| acc.max(align)) } pub fn llvm_type(&self, cx: &CodegenCx) -> Type { - match *self { - CastTarget::Uniform(u) => u.llvm_type(cx), - CastTarget::Pair(a, b) => { - Type::struct_(cx, &[ - a.llvm_type(cx), - b.llvm_type(cx) - ], false) - }, - CastTarget::ChunkedPrefix { prefix, chunk, total } => { - let total_chunks = total.bytes() / chunk.bytes(); - let rem_bytes = total.bytes() % chunk.bytes(); - let prefix_chunks = total_chunks.min(prefix.len() as u64); - - let int_ll_type = Reg { kind: RegKind::Integer, size: chunk }.llvm_type(cx); + let rest_ll_unit = self.rest.unit.llvm_type(cx); + let rest_count = self.rest.total.bytes() / self.rest.unit.size.bytes(); + let rem_bytes = self.rest.total.bytes() % self.rest.unit.size.bytes(); + + if self.prefix.iter().all(|x| x.is_none()) { + // Simplify to a single unit when there is no prefix and size <= unit size + if self.rest.total <= self.rest.unit.size { + return rest_ll_unit; + } - // Simple cases simplify to an array - if rem_bytes == 0 && prefix.into_iter().all(|&kind| kind == RegKind::Integer) { - return Type::array(&int_ll_type, total_chunks); - } + // Simplify to array when all chunks are the same size and type + if rem_bytes == 0 { + return Type::array(&rest_ll_unit, rest_count); + } + } - // The final structure is made up of: - // Up to 8 chunks of the type specified in the prefix - // Any other complete chunks as integers - // One final integer needed to make up the total structure size - let mut args: Vec<_> = - prefix.into_iter().take(prefix_chunks as usize) - .map(|&kind| Reg { kind: kind, size: chunk }.llvm_type(cx)) - .chain((0..total_chunks - prefix_chunks).map(|_| int_ll_type)) - .collect(); - - if rem_bytes > 0 { - args.push(Type::ix(cx, rem_bytes * 8)); - } + // Create list of fields in the main structure + let mut args: Vec<_> = + self.prefix.iter().flat_map(|option_kind| option_kind.map( + |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx))) + .chain((0..rest_count).map(|_| rest_ll_unit)) + .collect(); - Type::struct_(cx, &args, false) - } + // Append final integer + if rem_bytes != 0 { + // Only integers can be really split further. + assert_eq!(self.rest.unit.kind, RegKind::Integer); + args.push(Type::ix(cx, rem_bytes * 8)); } + + Type::struct_(cx, &args, false) } } diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index b8144a3ca7a..7eadaa7f493 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -171,7 +171,7 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget { let mut target = CastTarget::from(lo); if size > offset { if let Some(hi) = reg_component(cls, &mut i, size - offset) { - target = CastTarget::Pair(lo, hi); + target = CastTarget::pair(lo, hi); } } assert_eq!(reg_component(cls, &mut i, Size::from_bytes(0)), None); |
