]> git.lizzy.rs Git - rust.git/blobdiff - src/pointer.rs
Merge commit 'c19edfd71a1d0ddef86c2c67fdb40718d40a72b4' into sync_cg_clif-2022-07-25
[rust.git] / src / pointer.rs
index f47d5e9be9ba1c795703a25c4d51ce79c14201af..31d827f83bfab94543e32a1ffbe0f3918b6d62fd 100644 (file)
+//! Defines [`Pointer`] which is used to improve the quality of the generated clif ir for pointer
+//! operations.
+
 use crate::prelude::*;
 
-use cranelift::codegen::ir::immediates::Offset32;
+use rustc_target::abi::Align;
+
+use cranelift_codegen::ir::immediates::Offset32;
 
+/// A pointer pointing either to a certain address, a certain stack slot or nothing.
 #[derive(Copy, Clone, Debug)]
-pub struct Pointer {
+pub(crate) struct Pointer {
     base: PointerBase,
     offset: Offset32,
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum PointerBase {
+pub(crate) enum PointerBase {
     Addr(Value),
     Stack(StackSlot),
+    Dangling(Align),
 }
 
 impl Pointer {
-    pub fn new(addr: Value) -> Self {
-        Pointer {
-            base: PointerBase::Addr(addr),
-            offset: Offset32::new(0),
-        }
+    pub(crate) fn new(addr: Value) -> Self {
+        Pointer { 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(crate) 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 {
+    pub(crate) fn const_addr(fx: &mut FunctionCx<'_, '_, '_>, addr: i64) -> Self {
         let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
-        Pointer {
-            base: PointerBase::Addr(addr),
-            offset: Offset32::new(0),
-        }
+        Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
+    }
+
+    pub(crate) fn dangling(align: Align) -> Self {
+        Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
     }
 
-    pub fn base_and_offset(self) -> (PointerBase, Offset32) {
+    pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) {
         (self.base, self.offset)
     }
 
-    pub fn get_addr<'a, 'tcx>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> Value {
+    pub(crate) fn get_addr(self, fx: &mut FunctionCx<'_, '_, '_>) -> Value {
         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)
-                }
+                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)
+            }
+            PointerBase::Dangling(align) => {
+                fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
             }
-            PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 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,
-        fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
-        extra_offset: Offset32,
-    ) -> Self {
+    pub(crate) fn offset(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Offset32) -> Self {
         self.offset_i64(fx, extra_offset.into())
     }
 
-    pub fn offset_i64<'a, 'tcx>(
-        self,
-        fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
-        extra_offset: i64,
-    ) -> Self {
+    pub(crate) fn offset_i64(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: i64) -> Self {
         if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
-            Pointer {
-                base: self.base,
-                offset: new_offset,
-            }
+            Pointer { 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){
+            if let Some(new_offset) = base_offset.checked_add(extra_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),
+                    PointerBase::Stack(stack_slot) => {
+                        fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)
+                    }
+                    PointerBase::Dangling(align) => {
+                        fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
+                    }
                 };
                 let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
-                Pointer {
-                    base: PointerBase::Addr(addr),
-                    offset: Offset32::new(0),
-                }
+                Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
             } else {
-                panic!("self.offset ({}) + extra_offset ({}) not representable in i64", base_offset, extra_offset);
+                panic!(
+                    "self.offset ({}) + extra_offset ({}) not representable in i64",
+                    base_offset, extra_offset
+                );
             }
         }
     }
 
-    pub fn offset_value<'a, 'tcx>(
-        self,
-        fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
-        extra_offset: Value,
-    ) -> Self {
+    pub(crate) fn offset_value(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Value) -> Self {
         match self.base {
             PointerBase::Addr(addr) => Pointer {
                 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
@@ -115,44 +101,34 @@ pub fn offset_value<'a, 'tcx>(
                     offset: Offset32::new(0),
                 }
             }
+            PointerBase::Dangling(align) => {
+                let addr =
+                    fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap());
+                Pointer {
+                    base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
+                    offset: self.offset,
+                }
+            }
         }
     }
 
-    pub fn load<'a, 'tcx>(
-        self,
-        fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
-        ty: Type,
-        flags: MemFlags,
-    ) -> Value {
+    pub(crate) fn load(self, fx: &mut FunctionCx<'_, '_, '_>, ty: Type, flags: MemFlags) -> Value {
         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)
-            }
+            PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_load(ty, stack_slot, self.offset),
+            PointerBase::Dangling(_align) => unreachable!(),
         }
     }
 
-    pub fn store<'a, 'tcx>(
-        self,
-        fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
-        value: Value,
-        flags: MemFlags,
-    ) {
+    pub(crate) fn store(self, fx: &mut FunctionCx<'_, '_, '_>, value: Value, flags: MemFlags) {
         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 {
+            PointerBase::Stack(stack_slot) => {
                 fx.bcx.ins().stack_store(value, stack_slot, self.offset);
             }
+            PointerBase::Dangling(_align) => unreachable!(),
         }
     }
 }