Skip to content

Commit 05d66dc

Browse files
committed
rustc_trans: add chunked prefix fields to CastTarget
1 parent 68042ba commit 05d66dc

File tree

2 files changed

+53
-87
lines changed

2 files changed

+53
-87
lines changed

src/librustc_trans/abi.rs

+52-86
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use rustc::ty::layout::{self, Align, Size, TyLayout};
4040
use rustc::ty::layout::{HasDataLayout, LayoutOf};
4141

4242
use libc::c_uint;
43-
use std::{cmp, iter};
43+
use std::cmp;
4444

4545
pub use syntax::abi::Abi;
4646
pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
@@ -279,30 +279,6 @@ impl Uniform {
279279
pub fn align(&self, cx: &CodegenCx) -> Align {
280280
self.unit.align(cx)
281281
}
282-
283-
pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
284-
let llunit = self.unit.llvm_type(cx);
285-
286-
if self.total <= self.unit.size {
287-
return llunit;
288-
}
289-
290-
let count = self.total.bytes() / self.unit.size.bytes();
291-
let rem_bytes = self.total.bytes() % self.unit.size.bytes();
292-
293-
if rem_bytes == 0 {
294-
return Type::array(&llunit, count);
295-
}
296-
297-
// Only integers can be really split further.
298-
assert_eq!(self.unit.kind, RegKind::Integer);
299-
300-
let args: Vec<_> = (0..count).map(|_| llunit)
301-
.chain(iter::once(Type::ix(cx, rem_bytes * 8)))
302-
.collect();
303-
304-
Type::struct_(cx, &args, false)
305-
}
306282
}
307283

308284
pub trait LayoutExt<'tcx> {
@@ -405,91 +381,81 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
405381
}
406382

407383
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
408-
pub enum CastTarget {
409-
Uniform(Uniform),
410-
Pair(Reg, Reg),
411-
ChunkedPrefix { prefix: [RegKind; 8], chunk: Size, total: Size }
384+
pub struct CastTarget {
385+
pub prefix: [Option<RegKind>; 8],
386+
pub prefix_chunk: Size,
387+
pub rest: Uniform,
412388
}
413389

414390
impl From<Reg> for CastTarget {
415391
fn from(unit: Reg) -> CastTarget {
416-
CastTarget::Uniform(Uniform::from(unit))
392+
CastTarget::from(Uniform::from(unit))
417393
}
418394
}
419395

420396
impl From<Uniform> for CastTarget {
421397
fn from(uniform: Uniform) -> CastTarget {
422-
CastTarget::Uniform(uniform)
398+
CastTarget {
399+
prefix: [None; 8],
400+
prefix_chunk: Size::from_bytes(0),
401+
rest: uniform
402+
}
423403
}
424404
}
425405

426406
impl CastTarget {
427-
pub fn size(&self, cx: &CodegenCx) -> Size {
428-
match *self {
429-
CastTarget::Uniform(u) => u.total,
430-
CastTarget::Pair(a, b) => {
431-
(a.size.abi_align(a.align(cx)) + b.size)
432-
.abi_align(self.align(cx))
433-
},
434-
CastTarget::ChunkedPrefix { total, .. } => total
407+
pub fn pair(a: Reg, b: Reg) -> CastTarget {
408+
CastTarget {
409+
prefix: [Some(a.kind), None, None, None, None, None, None, None],
410+
prefix_chunk: a.size,
411+
rest: Uniform::from(b)
435412
}
436413
}
437414

415+
pub fn size(&self, cx: &CodegenCx) -> Size {
416+
(self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
417+
.abi_align(self.rest.align(cx)) + self.rest.total
418+
}
419+
438420
pub fn align(&self, cx: &CodegenCx) -> Align {
439-
match *self {
440-
CastTarget::Uniform(u) => u.align(cx),
441-
CastTarget::Pair(a, b) => {
442-
cx.data_layout().aggregate_align
443-
.max(a.align(cx))
444-
.max(b.align(cx))
445-
},
446-
CastTarget::ChunkedPrefix { chunk, .. } => {
447-
cx.data_layout().aggregate_align
448-
.max(Reg { kind: RegKind::Integer, size: chunk }.align(cx))
449-
.max(Reg { kind: RegKind::Float, size: chunk }.align(cx))
450-
.max(Reg { kind: RegKind::Vector, size: chunk }.align(cx))
451-
}
452-
}
421+
self.prefix.iter()
422+
.filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx)))
423+
.fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)),
424+
|acc, align| acc.max(align))
453425
}
454426

455427
pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
456-
match *self {
457-
CastTarget::Uniform(u) => u.llvm_type(cx),
458-
CastTarget::Pair(a, b) => {
459-
Type::struct_(cx, &[
460-
a.llvm_type(cx),
461-
b.llvm_type(cx)
462-
], false)
463-
},
464-
CastTarget::ChunkedPrefix { prefix, chunk, total } => {
465-
let total_chunks = total.bytes() / chunk.bytes();
466-
let rem_bytes = total.bytes() % chunk.bytes();
467-
let prefix_chunks = total_chunks.min(prefix.len() as u64);
468-
469-
let int_ll_type = Reg { kind: RegKind::Integer, size: chunk }.llvm_type(cx);
428+
let rest_ll_unit = self.rest.unit.llvm_type(cx);
429+
let rest_count = self.rest.total.bytes() / self.rest.unit.size.bytes();
430+
let rem_bytes = self.rest.total.bytes() % self.rest.unit.size.bytes();
431+
432+
if self.prefix.iter().all(|x| x.is_none()) {
433+
// Simplify to a single unit when there is no prefix and size <= unit size
434+
if self.rest.total <= self.rest.unit.size {
435+
return rest_ll_unit;
436+
}
470437

471-
// Simple cases simplify to an array
472-
if rem_bytes == 0 && prefix.into_iter().all(|&kind| kind == RegKind::Integer) {
473-
return Type::array(&int_ll_type, total_chunks);
474-
}
438+
// Simplify to array when all chunks are the same size and type
439+
if rem_bytes == 0 {
440+
return Type::array(&rest_ll_unit, rest_count);
441+
}
442+
}
475443

476-
// The final structure is made up of:
477-
// Up to 8 chunks of the type specified in the prefix
478-
// Any other complete chunks as integers
479-
// One final integer needed to make up the total structure size
480-
let mut args: Vec<_> =
481-
prefix.into_iter().take(prefix_chunks as usize)
482-
.map(|&kind| Reg { kind: kind, size: chunk }.llvm_type(cx))
483-
.chain((0..total_chunks - prefix_chunks).map(|_| int_ll_type))
484-
.collect();
485-
486-
if rem_bytes > 0 {
487-
args.push(Type::ix(cx, rem_bytes * 8));
488-
}
444+
// Create list of fields in the main structure
445+
let mut args: Vec<_> =
446+
self.prefix.iter().flat_map(|option_kind| option_kind.map(
447+
|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)))
448+
.chain((0..rest_count).map(|_| rest_ll_unit))
449+
.collect();
489450

490-
Type::struct_(cx, &args, false)
491-
}
451+
// Append final integer
452+
if rem_bytes != 0 {
453+
// Only integers can be really split further.
454+
assert_eq!(self.rest.unit.kind, RegKind::Integer);
455+
args.push(Type::ix(cx, rem_bytes * 8));
492456
}
457+
458+
Type::struct_(cx, &args, false)
493459
}
494460
}
495461

src/librustc_trans/cabi_x86_64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget {
171171
let mut target = CastTarget::from(lo);
172172
if size > offset {
173173
if let Some(hi) = reg_component(cls, &mut i, size - offset) {
174-
target = CastTarget::Pair(lo, hi);
174+
target = CastTarget::pair(lo, hi);
175175
}
176176
}
177177
assert_eq!(reg_component(cls, &mut i, Size::from_bytes(0)), None);

0 commit comments

Comments
 (0)