]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_cranelift/src/pointer.rs
New upstream version 1.70.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
29967ef6 33 pub(crate) fn dangling(align: Align) -> Self {
6a06907d 34 Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
29967ef6
XL
35 }
36
cdc7bbd5 37 pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) {
29967ef6
XL
38 (self.base, self.offset)
39 }
40
6a06907d 41 pub(crate) fn get_addr(self, fx: &mut FunctionCx<'_, '_, '_>) -> Value {
29967ef6
XL
42 match self.base {
43 PointerBase::Addr(base_addr) => {
44 let offset: i64 = self.offset.into();
6a06907d 45 if offset == 0 { base_addr } else { fx.bcx.ins().iadd_imm(base_addr, offset) }
29967ef6
XL
46 }
47 PointerBase::Stack(stack_slot) => {
6a06907d
XL
48 fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset)
49 }
50 PointerBase::Dangling(align) => {
51 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
29967ef6 52 }
29967ef6
XL
53 }
54 }
55
6a06907d 56 pub(crate) fn offset(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Offset32) -> Self {
29967ef6
XL
57 self.offset_i64(fx, extra_offset.into())
58 }
59
6a06907d 60 pub(crate) fn offset_i64(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: i64) -> Self {
29967ef6 61 if let Some(new_offset) = self.offset.try_add_i64(extra_offset) {
6a06907d 62 Pointer { base: self.base, offset: new_offset }
29967ef6
XL
63 } else {
64 let base_offset: i64 = self.offset.into();
65 if let Some(new_offset) = base_offset.checked_add(extra_offset) {
66 let base_addr = match self.base {
67 PointerBase::Addr(addr) => addr,
68 PointerBase::Stack(stack_slot) => {
69 fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0)
70 }
6a06907d
XL
71 PointerBase::Dangling(align) => {
72 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap())
73 }
29967ef6
XL
74 };
75 let addr = fx.bcx.ins().iadd_imm(base_addr, new_offset);
6a06907d 76 Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) }
29967ef6
XL
77 } else {
78 panic!(
79 "self.offset ({}) + extra_offset ({}) not representable in i64",
80 base_offset, extra_offset
81 );
82 }
83 }
84 }
85
6a06907d 86 pub(crate) fn offset_value(self, fx: &mut FunctionCx<'_, '_, '_>, extra_offset: Value) -> Self {
29967ef6
XL
87 match self.base {
88 PointerBase::Addr(addr) => Pointer {
89 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
90 offset: self.offset,
91 },
92 PointerBase::Stack(stack_slot) => {
6a06907d 93 let base_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, self.offset);
29967ef6
XL
94 Pointer {
95 base: PointerBase::Addr(fx.bcx.ins().iadd(base_addr, extra_offset)),
96 offset: Offset32::new(0),
97 }
98 }
99 PointerBase::Dangling(align) => {
6a06907d
XL
100 let addr =
101 fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(align.bytes()).unwrap());
29967ef6
XL
102 Pointer {
103 base: PointerBase::Addr(fx.bcx.ins().iadd(addr, extra_offset)),
104 offset: self.offset,
105 }
106 }
107 }
108 }
109
6a06907d 110 pub(crate) fn load(self, fx: &mut FunctionCx<'_, '_, '_>, ty: Type, flags: MemFlags) -> Value {
29967ef6
XL
111 match self.base {
112 PointerBase::Addr(base_addr) => fx.bcx.ins().load(ty, flags, base_addr, self.offset),
6a06907d 113 PointerBase::Stack(stack_slot) => fx.bcx.ins().stack_load(ty, stack_slot, self.offset),
29967ef6
XL
114 PointerBase::Dangling(_align) => unreachable!(),
115 }
116 }
117
6a06907d 118 pub(crate) fn store(self, fx: &mut FunctionCx<'_, '_, '_>, value: Value, flags: MemFlags) {
29967ef6
XL
119 match self.base {
120 PointerBase::Addr(base_addr) => {
121 fx.bcx.ins().store(flags, value, base_addr, self.offset);
122 }
123 PointerBase::Stack(stack_slot) => {
6a06907d 124 fx.bcx.ins().stack_store(value, stack_slot, self.offset);
29967ef6
XL
125 }
126 PointerBase::Dangling(_align) => unreachable!(),
127 }
128 }
129}