Skip to content

Commit f45a474

Browse files
committed
rustc_trans: add abi::CastTarget::ChunkedPrefix
1 parent 4d2d3fc commit f45a474

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

src/librustc_trans/abi.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
407407
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
408408
pub enum CastTarget {
409409
Uniform(Uniform),
410-
Pair(Reg, Reg)
410+
Pair(Reg, Reg),
411+
ChunkedPrefix { prefix: [RegKind; 8], chunk: Size, total: Size }
411412
}
412413

413414
impl From<Reg> for CastTarget {
@@ -429,7 +430,8 @@ impl CastTarget {
429430
CastTarget::Pair(a, b) => {
430431
(a.size.abi_align(a.align(cx)) + b.size)
431432
.abi_align(self.align(cx))
432-
}
433+
},
434+
CastTarget::ChunkedPrefix { total, .. } => total
433435
}
434436
}
435437

@@ -440,6 +442,12 @@ impl CastTarget {
440442
cx.data_layout().aggregate_align
441443
.max(a.align(cx))
442444
.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))
443451
}
444452
}
445453
}
@@ -452,6 +460,34 @@ impl CastTarget {
452460
a.llvm_type(cx),
453461
b.llvm_type(cx)
454462
], 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);
470+
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+
}
475+
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+
}
489+
490+
Type::struct_(cx, &args, false)
455491
}
456492
}
457493
}

0 commit comments

Comments
 (0)