3 use cranelift_codegen::ir::immediates::Offset32;
5 #[derive(Copy, Clone, Debug)]
11 #[derive(Copy, Clone, Debug)]
12 pub enum PointerBase {
18 pub fn new(addr: Value) -> Self {
20 base: PointerBase::Addr(addr),
21 offset: Offset32::new(0),
25 pub fn stack_slot(stack_slot: StackSlot) -> Self {
27 base: PointerBase::Stack(stack_slot),
28 offset: Offset32::new(0),
32 pub fn const_addr<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, addr: i64) -> Self {
33 let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
35 base: PointerBase::Addr(addr),
36 offset: Offset32::new(0),
40 pub fn base_and_offset(self) -> (PointerBase, Offset32) {
41 (self.base, self.offset)
44 pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
46 PointerBase::Addr(base_addr) => {
47 let offset: i64 = self.offset.into();
51 fx.bcx.ins().iadd_imm(base_addr, offset)
54 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset),
58 pub fn try_get_addr_and_offset(self) -> Option<(Value, Offset32)> {
60 PointerBase::Addr(addr) => Some((addr, self.offset)),
61 PointerBase::Stack(_) => None,
65 pub fn offset<'a, 'tcx>(
67 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
68 extra_offset: Offset32,
70 self.offset_i64(fx, extra_offset.into())
73 pub fn offset_i64<'a, 'tcx>(
75 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
78 if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
84 let base_offset: i64 = self.offset.into();
85 if let Some(new_offset) = base_offset.checked_add(extra_offset){
86 let base_addr = match self.base {
87 PointerBase::Addr(addr) => addr,
88 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
90 let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
92 base: PointerBase::Addr(addr),
93 offset: Offset32::new(0),
96 panic!("self.offset ({}) + extra_offset ({}) not representable in i64", base_offset, extra_offset);
101 pub fn offset_value<'a, 'tcx>(
103 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
107 PointerBase::Addr(addr) => Pointer {
108 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
111 PointerBase::Stack(stack_slot) => {
112 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
114 base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
115 offset: Offset32::new(0),
121 pub fn load<'a, 'tcx>(
123 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
128 PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
129 PointerBase::Stack(stack_slot) => if ty == types::I128 {
130 // WORKAROUND for stack_load.i128 not being implemented
131 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
132 fx.bcx.ins().load(ty, flags, base_addr, self.offset)
134 fx.bcx.ins().stack_load(ty, stack_slot, self.offset)
139 pub fn store<'a, 'tcx>(
141 fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
146 PointerBase::Addr(base_addr) => {
147 fx.bcx.ins().store(flags, value, base_addr, self.offset);
149 PointerBase::Stack(stack_slot) => if fx.bcx.func.dfg.value_type(value) == types::I128 {
150 // WORKAROUND for stack_load.i128 not being implemented
151 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
152 fx.bcx.ins().store(flags, value, base_addr, self.offset);
154 fx.bcx.ins().stack_store(value, stack_slot, self.offset);