3 use rustc_target::abi::Align;
5 use cranelift_codegen::ir::immediates::Offset32;
7 #[derive(Copy, Clone, Debug)]
8 pub(crate) struct Pointer {
13 #[derive(Copy, Clone, Debug)]
14 pub(crate) enum PointerBase {
21 pub(crate) fn new(addr: Value) -> Self {
23 base: PointerBase::Addr(addr),
24 offset: Offset32::new(0),
28 pub(crate) fn stack_slot(stack_slot: StackSlot) -> Self {
30 base: PointerBase::Stack(stack_slot),
31 offset: Offset32::new(0),
35 pub(crate) fn const_addr<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, addr: i64) -> Self {
36 let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
38 base: PointerBase::Addr(addr),
39 offset: Offset32::new(0),
43 pub(crate) fn dangling(align: Align) -> Self {
45 base: PointerBase::Dangling(align),
46 offset: Offset32::new(0),
50 #[cfg(debug_assertions)]
51 pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) {
52 (self.base, self.offset)
55 pub(crate) fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
57 PointerBase::Addr(base_addr) => {
58 let offset: i64 = self.offset.into();
62 fx.bcx.ins().iadd_imm(base_addr, offset)
65 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset),
66 PointerBase::Dangling(align) => {
67 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
72 pub(crate) fn offset<'a, 'tcx>(
74 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
75 extra_offset: Offset32,
77 self.offset_i64(fx, extra_offset.into())
80 pub(crate) fn offset_i64<'a, 'tcx>(
82 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
85 if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
91 let base_offset: i64 = self.offset.into();
92 if let Some(new_offset) = base_offset.checked_add(extra_offset){
93 let base_addr = match self.base {
94 PointerBase::Addr(addr) => addr,
95 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
96 PointerBase::Dangling(align) => fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap()),
98 let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
100 base: PointerBase::Addr(addr),
101 offset: Offset32::new(0),
104 panic!("self.offset ({}) + extra_offset ({}) not representable in i64", base_offset, extra_offset);
109 pub(crate) fn offset_value<'a, 'tcx>(
111 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
115 PointerBase::Addr(addr) => Pointer {
116 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
119 PointerBase::Stack(stack_slot) => {
120 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
122 base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
123 offset: Offset32::new(0),
126 PointerBase::Dangling(align) => {
127 let addr = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap());
129 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
136 pub(crate) fn load<'a, 'tcx>(
138 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
143 PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
144 PointerBase::Stack(stack_slot) => if ty == types::I128 || ty.is_vector() {
145 // WORKAROUND for stack_load.i128 and stack_load.iXxY not being implemented
146 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
147 fx.bcx.ins().load(ty, flags, base_addr, self.offset)
149 fx.bcx.ins().stack_load(ty, stack_slot, self.offset)
151 PointerBase::Dangling(_align) => unreachable!(),
155 pub(crate) fn store<'a, 'tcx>(
157 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
162 PointerBase::Addr(base_addr) => {
163 fx.bcx.ins().store(flags, value, base_addr, self.offset);
165 PointerBase::Stack(stack_slot) => {
166 let val_ty = fx.bcx.func.dfg.value_type(value);
167 if val_ty == types::I128 || val_ty.is_vector() {
168 // WORKAROUND for stack_store.i128 and stack_store.iXxY not being implemented
169 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
170 fx.bcx.ins().store(flags, value, base_addr, self.offset);
172 fx.bcx.ins().stack_store(value, stack_slot, self.offset);
175 PointerBase::Dangling(_align) => unreachable!(),