duskphantom_middle/ir/
macros.rs

1// Copyright 2024 Duskphantom Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17#[macro_export]
18macro_rules! define_graph_iterator {
19    ($name:ident, $collection:ty, $pop_method:ident, $bb_update_method:ident) => {
20        pub struct $name {
21            container: $collection,
22            visited: HashSet<BBPtr>,
23        }
24
25        impl Iterator for $name {
26            type Item = BBPtr;
27            fn next(&mut self) -> Option<Self::Item> {
28                while let Some(bb) = self.container.$pop_method() {
29                    if !self.visited.contains(&bb) {
30                        self.visited.insert(bb);
31                        self.container.extend(bb.$bb_update_method());
32                        return Some(bb);
33                    }
34                }
35                None
36            }
37        }
38
39        impl From<BBPtr> for $name {
40            fn from(bb: BBPtr) -> Self {
41                Self {
42                    container: vec![bb].into(),
43                    visited: HashSet::new(),
44                }
45            }
46        }
47    };
48}
49
50/// Use this macro to generate some code for instruction to simplify the codesize.
51/// Make sure to use this macro in the impl Instruction block
52/// and the Instruction struct must have a field named manager
53/// which is an instance of InstManager.
54#[macro_export]
55macro_rules! gen_common_code {
56    ($type:ty,$id:ident) => {
57        #[inline]
58        unsafe fn as_any(&self) -> &dyn Any {
59            self
60        }
61        #[inline]
62        unsafe fn as_any_mut(&mut self) -> &mut dyn Any {
63            self
64        }
65        #[inline]
66        fn get_type(&self) -> InstType {
67            InstType::$id
68        }
69        #[inline]
70        fn get_manager(&self) -> &InstManager {
71            &self.manager
72        }
73        #[inline]
74        unsafe fn get_manager_mut(&mut self) -> &mut InstManager {
75            &mut self.manager
76        }
77    };
78}
79
80/// impl InstType enum automatically.
81#[macro_export]
82macro_rules! define_inst_type_enum {
83    ($( $variant:ident ),*) => {
84        #[derive(Clone, Copy, Eq, PartialEq, Hash)]
85        pub enum InstType {
86            $( $variant ),*
87        }
88
89        impl InstType {
90            #[inline]
91            fn get_name(&self) -> String {
92                match self {
93                    $( InstType::$variant => stringify!($variant).to_lowercase(), )*
94                }
95            }
96        }
97
98        impl std::fmt::Display for InstType {
99            #[inline]
100            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101                write!(f, "{}", self.get_name())
102            }
103        }
104
105        impl std::fmt::Debug for InstType {
106            #[inline]
107            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108                write!(f, "{}", self.get_name())
109            }
110        }
111    };
112}
113
114/// impl BinaryInst trait automatically.
115#[macro_export]
116macro_rules! impl_binary_inst {
117    ($type:ident, $operand_type:expr,$func: ident, $lhs:ident, $rhs: ident, $value_type: ident) => {
118        /// If you want to make a new binary inst,
119        /// please use the IRBuilder to create it.
120        pub struct $type {
121            manager: InstManager,
122        }
123        impl BinaryInst for $type {
124            #[inline]
125            fn get_lhs(&self) -> &Operand {
126                &self.manager.operand[0]
127            }
128
129            #[inline]
130            fn set_lhs(&mut self, lhs: Operand) {
131                unsafe { self.get_manager_mut().set_operand(0, lhs) };
132            }
133
134            #[inline]
135            fn get_rhs(&self) -> &Operand {
136                &self.manager.operand[1]
137            }
138
139            #[inline]
140            fn set_rhs(&mut self, rhs: Operand) {
141                unsafe { self.get_manager_mut().set_operand(1, rhs) };
142            }
143        }
144
145        impl Instruction for $type {
146            gen_common_code!($type, $type);
147            fn copy_self(&self) -> Box<dyn Instruction> {
148                Box::new($type {
149                    manager: InstManager::new($value_type),
150                })
151            }
152            #[inline]
153            fn gen_llvm_ir(&self) -> String {
154                format!(
155                    "{} = {} {} {}, {}",
156                    self,
157                    self.get_type(),
158                    $operand_type,
159                    self.get_lhs(),
160                    self.get_rhs()
161                )
162            }
163        }
164
165        impl Display for $type {
166            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167                write!(f, "%{}_{}", stringify!($type), self.get_id())
168            }
169        }
170
171        impl IRBuilder {
172            /// Get a new inst instruction with operands.
173            pub fn $func(&mut self, $lhs: Operand, $rhs: Operand) -> InstPtr {
174                let mut inst = self.new_instruction(Box::new($type {
175                    manager: InstManager::new($value_type),
176                }));
177                unsafe {
178                    inst.get_manager_mut().add_operand($lhs);
179                    inst.get_manager_mut().add_operand($rhs);
180                }
181                inst
182            }
183        }
184    };
185}