#[derive(Copy, Clone, Debug)]
pub struct Pointer {
- base_addr: Value,
+ base: PointerBase,
offset: Offset32,
}
+#[derive(Copy, Clone, Debug)]
+enum PointerBase {
+ Addr(Value),
+ Stack(StackSlot),
+}
+
impl Pointer {
pub fn new(addr: Value) -> Self {
Pointer {
- base_addr: addr,
+ base: PointerBase::Addr(addr),
+ offset: Offset32::new(0),
+ }
+ }
+
+ pub fn stack_slot(stack_slot: StackSlot) -> Self {
+ Pointer {
+ base: PointerBase::Stack(stack_slot),
offset: Offset32::new(0),
}
}
pub fn const_addr<'a, 'tcx>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, addr: i64) -> Self {
let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
Pointer {
- base_addr: addr,
+ base: PointerBase::Addr(addr),
offset: Offset32::new(0),
}
}
pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
- let offset: i64 = self.offset.into();
- if offset == 0 {
- self.base_addr
- } else {
- fx.bcx.ins().iadd_imm(self.base_addr, offset)
+ match self.base {
+ PointerBase::Addr(base_addr) => {
+ let offset: i64 = self.offset.into();
+ if offset == 0 {
+ base_addr
+ } else {
+ fx.bcx.ins().iadd_imm(base_addr, offset)
+ }
+ }
+ PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset),
}
}
- pub fn get_addr_and_offset(self) -> (Value, Offset32) {
- (self.base_addr, self.offset)
+ pub fn try_get_addr_and_offset(self) -> Option<(Value, Offset32)> {
+ match self.base {
+ PointerBase::Addr(addr) => Some((addr, self.offset)),
+ PointerBase::Stack(_) => None,
+ }
}
pub fn offset<'a, 'tcx>(
) -> Self {
if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
Pointer {
- base_addr: self.base_addr,
+ base: self.base,
offset: new_offset,
}
} else {
let base_offset: i64 = self.offset.into();
if let Some(new_offset) = base_offset.checked_add(extra_offset){
- let addr = fx.bcx.ins().iadd_imm(self.base_addr, new_offset);
+ let base_addr = match self.base {
+ PointerBase::Addr(addr) => addr,
+ PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0),
+ };
+ let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
Pointer {
- base_addr: addr,
+ base: PointerBase::Addr(addr),
offset: Offset32::new(0),
}
} else {
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
extra_offset: Value,
) -> Self {
- let base_addr = fx.bcx.ins().iadd(self.base_addr, extra_offset);
- Pointer {
- base_addr,
- offset: self.offset,
+ match self.base {
+ PointerBase::Addr(addr) => Pointer {
+ base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
+ offset: self.offset,
+ },
+ PointerBase::Stack(stack_slot) => {
+ let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
+ Pointer {
+ base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
+ offset: Offset32::new(0),
+ }
+ }
}
}
ty: Type,
flags: MemFlags,
) -> Value {
- fx.bcx.ins().load(ty, flags, self.base_addr, self.offset)
+ match self.base {
+ PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
+ PointerBase::Stack(stack_slot) => if ty == types::I128 {
+ // WORKAROUND for stack_load.i128 not being implemented
+ let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
+ fx.bcx.ins().load(ty, flags, base_addr, self.offset)
+ } else {
+ fx.bcx.ins().stack_load(ty, stack_slot, self.offset)
+ }
+ }
}
pub fn store<'a, 'tcx>(
value: Value,
flags: MemFlags,
) {
- fx.bcx.ins().store(flags, value, self.base_addr, self.offset);
+ match self.base {
+ PointerBase::Addr(base_addr) => {
+ fx.bcx.ins().store(flags, value, base_addr, self.offset);
+ }
+ PointerBase::Stack(stack_slot) => if fx.bcx.func.dfg.value_type(value) == types::I128 {
+ // WORKAROUND for stack_load.i128 not being implemented
+ let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0);
+ fx.bcx.ins().store(flags, value, base_addr, self.offset);
+ } else {
+ fx.bcx.ins().stack_store(value, stack_slot, self.offset);
+ }
+ }
}
}
pub fn try_to_addr(self) -> Option<Value> {
match self.0 {
CValueInner::ByRef(ptr) => {
- let (base_addr, offset) = ptr.get_addr_and_offset();
- if offset == Offset32::new(0) {
- Some(base_addr)
+ if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() {
+ if offset == Offset32::new(0) {
+ Some(base_addr)
+ } else {
+ None
+ }
} else {
None
}
CValue::by_ref(ptr, layout)
}
CPlaceInner::Stack(stack_slot) => CValue::by_ref(
- Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)),
+ Pointer::stack_slot(stack_slot),
layout,
),
CPlaceInner::NoPlace => CValue::by_ref(
match self.inner {
CPlaceInner::Addr(ptr, extra) => (ptr, extra),
CPlaceInner::Stack(stack_slot) => (
- Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)),
+ Pointer::stack_slot(stack_slot),
None,
),
CPlaceInner::NoPlace => {
return;
}
CPlaceInner::Addr(ptr, None) => ptr,
- CPlaceInner::Stack(stack_slot) => {
- Pointer::new(fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0))
- }
+ CPlaceInner::Stack(stack_slot) => Pointer::stack_slot(stack_slot),
CPlaceInner::NoPlace => {
if dst_layout.abi != Abi::Uninhabited {
assert_eq!(dst_layout.size.bytes(), 0, "{:?}", dst_layout);