]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_cranelift/src/pointer.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_codegen_cranelift / src / pointer.rs
CommitLineData
29967ef6
XL
1//! Defines [`Pointer`] which is used to improve the quality of the generated clif ir for pointer
2//! operations.
3
4use crate::prelude::*;
5
6use rustc_target::abi::Align;
7
8use cranelift_codegen::ir::immediates::Offset32;
9
10/// A pointer pointing either to a certain address, a certain stack slot or nothing.
11#[derive(Copy, Clone, Debug)]
12pub(crate) struct Pointer {
13 base: PointerBase,
14 offset: Offset32,
15}
16
17#[derive(Copy, Clone, Debug)]
18pub(crate) enum PointerBase {
19 Addr(Value),
20 Stack(StackSlot),
21 Dangling(Align),
22}
23
24impl Pointer {
25 pub(crate) fn new(addr: Value) -> Self {
6a06907d 26 Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
29967ef6
XL
27 }
28
29 pub(crate) fn stack_slot(stack_slot: StackSlot) -> Self {
6a06907d 30 Pointer { base: PointerBase::Stack(stack_slot), offset: Offset32::new(0) }
29967ef6
XL
31 }
32
6a06907d 33 pub(crate) fn const_addr(fx: &mut FunctionCx<'_, '_, '_>, addr: i64) -> Self {
29967ef6 34 let addr = fx.bcx.ins().iconst(fx.pointer_type, addr);
6a06907d 35 Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
29967ef6
XL
36 }
37
38 pub(crate) fn dangling(align: Align) -> Self {
6a06907d 39 Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
29967ef6
XL
40 }
41
cdc7bbd5 42 pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) {
29967ef6
XL
43 (self.base, self.offset)
44 }
45
6a06907d 46 pub(crate) fn get_addr(self, fx: &mut FunctionCx<'_, '_, '_>) -> Value {
29967ef6
XL
47 match self.base {
48 PointerBase::Addr(base_addr) => {
49 let offset: i64 = self.offset.into();
6a06907d 50 if offset == 0 { base_addr } else { fx.bcx.ins().iadd_imm(base_addr, offset) }
29967ef6
XL
51 }
52 PointerBase::Stack(stack_slot) => {
6a06907d
XL
53 fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset)
54 }
55 PointerBase::Dangling(align) => {
56 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
29967ef6 57 }
29967ef6
XL
58 }
59 }
60
6a06907d 61 pub(crate) fn offset(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Offset32) -> Self {
29967ef6
XL
62 self.offset_i64(fx, extra_offset.into())
63 }
64
6a06907d 65 pub(crate) fn offset_i64(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: i64) -> Self {
29967ef6 66 if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
6a06907d 67 Pointer { base: self.base, offset: new_offset }
29967ef6
XL
68 } else {
69 let base_offset: i64 = self.offset.into();
70 if let Some(new_offset) = base_offset.checked_add(extra_offset) {
71 let base_addr = match self.base {
72 PointerBase::Addr(addr) => addr,
73 PointerBase::Stack(stack_slot) => {
74 fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)
75 }
6a06907d
XL
76 PointerBase::Dangling(align) => {
77 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
78 }
29967ef6
XL
79 };
80 let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
6a06907d 81 Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
29967ef6
XL
82 } else {
83 panic!(
84 "self.offset ({}) + extra_offset ({}) not representable in i64",
85 base_offset, extra_offset
86 );
87 }
88 }
89 }
90
6a06907d 91 pub(crate) fn offset_value(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Value) -> Self {
29967ef6
XL
92 match self.base {
93 PointerBase::Addr(addr) => Pointer {
94 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
95 offset: self.offset,
96 },
97 PointerBase::Stack(stack_slot) => {
6a06907d 98 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
29967ef6
XL
99 Pointer {
100 base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
101 offset: Offset32::new(0),
102 }
103 }
104 PointerBase::Dangling(align) => {
6a06907d
XL
105 let addr =
106 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap());
29967ef6
XL
107 Pointer {
108 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
109 offset: self.offset,
110 }
111 }
112 }
113 }
114
6a06907d 115 pub(crate) fn load(self, fx: &mut FunctionCx<'_, '_, '_>, ty: Type, flags: MemFlags) -> Value {
29967ef6
XL
116 match self.base {
117 PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
6a06907d 118 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_load(ty, stack_slot, self.offset),
29967ef6
XL
119 PointerBase::Dangling(_align) => unreachable!(),
120 }
121 }
122
6a06907d 123 pub(crate) fn store(self, fx: &mut FunctionCx<'_, '_, '_>, value: Value, flags: MemFlags) {
29967ef6
XL
124 match self.base {
125 PointerBase::Addr(base_addr) => {
126 fx.bcx.ins().store(flags, value, base_addr, self.offset);
127 }
128 PointerBase::Stack(stack_slot) => {
6a06907d 129 fx.bcx.ins().stack_store(value, stack_slot, self.offset);
29967ef6
XL
130 }
131 PointerBase::Dangling(_align) => unreachable!(),
132 }
133 }
134}