|
3 | 3 | use crate::prelude::*;
|
4 | 4 |
|
5 | 5 | use cranelift_codegen::ir::immediates::Offset32;
|
| 6 | +use cranelift_codegen::ir::{InstructionData, Opcode}; |
6 | 7 |
|
7 | 8 | fn codegen_field<'tcx>(
|
8 | 9 | fx: &mut FunctionCx<'_, '_, 'tcx>,
|
@@ -457,13 +458,15 @@ impl<'tcx> CPlace<'tcx> {
|
457 | 458 | }
|
458 | 459 | }
|
459 | 460 |
|
| 461 | + #[track_caller] |
460 | 462 | pub(crate) fn to_ptr(self) -> Pointer {
|
461 | 463 | match self.to_ptr_maybe_unsized() {
|
462 | 464 | (ptr, None) => ptr,
|
463 | 465 | (_, Some(_)) => bug!("Expected sized cplace, found {:?}", self),
|
464 | 466 | }
|
465 | 467 | }
|
466 | 468 |
|
| 469 | + #[track_caller] |
467 | 470 | pub(crate) fn to_ptr_maybe_unsized(self) -> (Pointer, Option<Value>) {
|
468 | 471 | match self.inner {
|
469 | 472 | CPlaceInner::Addr(ptr, extra) => (ptr, extra),
|
@@ -787,7 +790,36 @@ impl<'tcx> CPlace<'tcx> {
|
787 | 790 | index: Value,
|
788 | 791 | ) -> CPlace<'tcx> {
|
789 | 792 | let (elem_layout, ptr) = match self.layout().ty.kind() {
|
790 |
| - ty::Array(elem_ty, _) => (fx.layout_of(*elem_ty), self.to_ptr()), |
| 793 | + ty::Array(elem_ty, _) => { |
| 794 | + let elem_layout = fx.layout_of(*elem_ty); |
| 795 | + match self.inner { |
| 796 | + CPlaceInner::Var(local, var) => { |
| 797 | + // This is a hack to handle `vector_val.0[1]`. It doesn't allow dynamic |
| 798 | + // indexing. |
| 799 | + let lane_idx = match fx.bcx.func.dfg.insts |
| 800 | + [fx.bcx.func.dfg.value_def(index).unwrap_inst()] |
| 801 | + { |
| 802 | + InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => imm, |
| 803 | + _ => bug!( |
| 804 | + "Dynamic indexing into a vector type is not supported: {self:?}[{index}]" |
| 805 | + ), |
| 806 | + }; |
| 807 | + return CPlace { |
| 808 | + inner: CPlaceInner::VarLane( |
| 809 | + local, |
| 810 | + var, |
| 811 | + lane_idx.bits().try_into().unwrap(), |
| 812 | + ), |
| 813 | + layout: elem_layout, |
| 814 | + }; |
| 815 | + } |
| 816 | + CPlaceInner::Addr(addr, None) => (elem_layout, addr), |
| 817 | + CPlaceInner::Addr(_, Some(_)) |
| 818 | + | CPlaceInner::VarPair(_, _, _) |
| 819 | + | CPlaceInner::VarLane(_, _, _) => bug!("Can't index into {self:?}"), |
| 820 | + } |
| 821 | + // FIXME use VarLane in case of Var with simd type |
| 822 | + } |
791 | 823 | ty::Slice(elem_ty) => (fx.layout_of(*elem_ty), self.to_ptr_maybe_unsized().0),
|
792 | 824 | _ => bug!("place_index({:?})", self.layout().ty),
|
793 | 825 | };
|
|
0 commit comments