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 field = self.layout.field(bx.cx(), i);
|
||||||
let offset = self.layout.fields.offset(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() {
|
let val = if field.is_zst() {
|
||||||
OperandValue::ZeroSized
|
OperandValue::ZeroSized
|
||||||
} else if field.size == self.layout.size {
|
} else if field.size == self.layout.size {
|
||||||
assert_eq!(offset.bytes(), 0);
|
assert_eq!(offset.bytes(), 0);
|
||||||
if let Some(field_val) = fx.codegen_transmute_operand(bx, *self, field) {
|
fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| {
|
||||||
field_val
|
bug!(
|
||||||
} else {
|
"Expected `codegen_transmute_operand` to handle equal-size \
|
||||||
// we have to go through memory for things like
|
field {i:?} projection from {self:?} to {field:?}"
|
||||||
// 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
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
|
let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
|
||||||
// Extract a scalar component from a pair.
|
// 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)
|
span_bug!(fx.mir.span, "OperandRef::extract_field({:?}): not applicable", self)
|
||||||
}
|
}
|
||||||
|
@ -415,14 +424,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||||
imm
|
imm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BackendRepr::Memory { sized: true } => {
|
BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { .. } => bug!(),
|
||||||
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!(),
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue