Rollup merge of #137361 - scottmcm:mcp-838-prep, r=compiler-errors
Refactor `OperandRef::extract_field` to prep for MCP838 cc https://github.com/rust-lang/compiler-team/issues/838 This still supports exactly the same cases as it did before, just rearranged a bit to better emphasize what doesn't work.
This commit is contained in:
commit
b012356475
1 changed files with 24 additions and 22 deletions
|
@ -358,19 +358,33 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
let field = self.layout.field(bx.cx(), i);
|
||||
let offset = self.layout.fields.offset(i);
|
||||
|
||||
if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) {
|
||||
if let BackendRepr::Vector { count, .. } = self.layout.backend_repr
|
||||
&& let BackendRepr::Memory { sized: true } = field.backend_repr
|
||||
&& count.is_power_of_two()
|
||||
{
|
||||
assert_eq!(field.size, self.layout.size);
|
||||
// This is being deprecated, but for now stdarch still needs it for
|
||||
// Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
|
||||
let place = PlaceRef::alloca(bx, field);
|
||||
self.val.store(bx, place.val.with_type(self.layout));
|
||||
return bx.load_operand(place);
|
||||
} else {
|
||||
// Part of https://github.com/rust-lang/compiler-team/issues/838
|
||||
bug!("Non-ref type {self:?} cannot project to ref field type {field:?}");
|
||||
}
|
||||
}
|
||||
|
||||
let val = if field.is_zst() {
|
||||
OperandValue::ZeroSized
|
||||
} else if field.size == self.layout.size {
|
||||
assert_eq!(offset.bytes(), 0);
|
||||
if let Some(field_val) = fx.codegen_transmute_operand(bx, *self, field) {
|
||||
field_val
|
||||
} else {
|
||||
// we have to go through memory for things like
|
||||
// Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
|
||||
let place = PlaceRef::alloca(bx, field);
|
||||
self.val.store(bx, place.val.with_type(self.layout));
|
||||
bx.load_operand(place).val
|
||||
}
|
||||
fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| {
|
||||
bug!(
|
||||
"Expected `codegen_transmute_operand` to handle equal-size \
|
||||
field {i:?} projection from {self:?} to {field:?}"
|
||||
)
|
||||
})
|
||||
} else {
|
||||
let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
|
||||
// Extract a scalar component from a pair.
|
||||
|
@ -385,11 +399,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
}
|
||||
}
|
||||
|
||||
// `#[repr(simd)]` types are also immediate.
|
||||
(OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
|
||||
(None, bx.extract_element(llval, bx.cx().const_usize(i as u64)))
|
||||
}
|
||||
|
||||
_ => {
|
||||
span_bug!(fx.mir.span, "OperandRef::extract_field({:?}): not applicable", self)
|
||||
}
|
||||
|
@ -415,14 +424,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
|||
imm
|
||||
}
|
||||
}
|
||||
BackendRepr::Memory { sized: true } => {
|
||||
span_bug!(
|
||||
fx.mir.span,
|
||||
"Projecting into a simd type with padding doesn't work; \
|
||||
See <https://github.com/rust-lang/rust/issues/137108>",
|
||||
);
|
||||
}
|
||||
BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(),
|
||||
BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { .. } => bug!(),
|
||||
})
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue