duskphantom_middle/ir/instruction/mod.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
17use super::*;
18pub mod binary_inst;
19pub mod extend_inst;
20pub mod head;
21pub mod memory_op_inst;
22pub mod misc_inst;
23pub mod terminator_inst;
24pub mod unary_inst;
25
26// pub type InstPtr = ObjPtr<Box<dyn Instruction>>;
27// impl Display for InstPtr {
28// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29// write!(f, "{}", self.as_ref())
30// }
31// }
32#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Debug)]
33pub struct InstPtr(ObjPtr<Box<dyn Instruction>>);
34
35impl Display for InstPtr {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{}", self.0.as_ref())
38 }
39}
40impl From<ObjPtr<Box<dyn Instruction>>> for InstPtr {
41 fn from(ptr: ObjPtr<Box<dyn Instruction>>) -> Self {
42 Self(ptr)
43 }
44}
45impl From<InstPtr> for ObjPtr<Box<dyn Instruction>> {
46 fn from(value: InstPtr) -> Self {
47 value.0
48 }
49}
50impl Deref for InstPtr {
51 type Target = Box<dyn Instruction>;
52 fn deref(&self) -> &Self::Target {
53 self.0.as_ref()
54 }
55}
56impl DerefMut for InstPtr {
57 fn deref_mut(&mut self) -> &mut Self::Target {
58 self.0.as_mut()
59 }
60}
61impl AsRef<Box<dyn Instruction>> for InstPtr {
62 fn as_ref(&self) -> &Box<dyn Instruction> {
63 self.0.as_ref()
64 }
65}
66
67use crate::{define_inst_type_enum, gen_common_code};
68use std::{
69 any::Any,
70 ops::{Deref, DerefMut},
71};
72
73define_inst_type_enum!(
74 // You will never get this type
75 Head,
76 // Binary Operations
77 Add,
78 FAdd,
79 Sub,
80 FSub,
81 Mul,
82 FMul,
83 UDiv,
84 SDiv,
85 FDiv,
86 URem,
87 SRem,
88 // FRem,
89 // Bitwise Binary Operations
90 Shl,
91 LShr,
92 AShr,
93 And,
94 Or,
95 Xor,
96 // Unary Operations
97 // FNeg,
98 // Terminator Instructions
99 Ret,
100 Br,
101 // Memory Access and Addressing Operations
102 Alloca,
103 Load,
104 Store,
105 GetElementPtr,
106 // Conversion Operations
107 ZextTo,
108 SextTo,
109 ItoFp,
110 FpToI,
111 // Other Operations
112 ICmp,
113 FCmp,
114 Phi,
115 Call
116);
117
118pub trait Instruction: Display {
119 /// # Safety
120 /// Don't call this method, use downcast_ref instead.
121 unsafe fn as_any(&self) -> &dyn Any;
122
123 /// # Safety
124 /// Don't call this method, use downcast_mut instead.
125 unsafe fn as_any_mut(&mut self) -> &mut dyn Any;
126
127 /// # Safety
128 /// Do not call this function directly
129 fn copy_self(&self) -> Box<dyn Instruction>;
130
131 /// Returns the type of current instruction.
132 fn get_type(&self) -> InstType;
133
134 /// Returns the manager of current instruction.
135 fn get_manager(&self) -> &InstManager;
136
137 /// Returns the manager of current instruction.
138 ///
139 /// # Safety
140 /// You should not use this function, because it may cause unknown errors.
141 unsafe fn get_manager_mut(&mut self) -> &mut InstManager;
142
143 /// Returns the instructions that use current instruction as operand.
144 #[inline]
145 fn get_user(&self) -> &[InstPtr] {
146 &self.get_manager().user
147 }
148
149 /// Returns the instructions that use current instruction as operand.
150 ///
151 /// # Safety
152 /// You should not use this function, because it may cause unknown errors.
153 #[inline]
154 unsafe fn get_user_mut(&mut self) -> &mut Vec<InstPtr> {
155 &mut self.get_manager_mut().user
156 }
157
158 /// Returns the operands of current instruction.
159 #[inline]
160 fn get_operand(&self) -> &[Operand] {
161 &self.get_manager().operand
162 }
163
164 /// Add an operand to the instruction.
165 fn add_operand(&mut self, operand: Operand) {
166 unsafe {
167 self.get_manager_mut().add_operand(operand);
168 }
169 }
170
171 /// Set the operand of cur inst by index and operand (safe and interface).
172 ///
173 /// # Panics
174 /// It will panic with index out of range!
175 #[inline]
176 fn set_operand(&mut self, index: usize, operand: Operand) {
177 unsafe {
178 self.get_manager_mut().set_operand(index, operand);
179 }
180 }
181
182 /// Replace all occurence of `from` to `to`.
183 #[inline]
184 fn replace_operand(&mut self, from: &Operand, to: &Operand) {
185 unsafe {
186 self.get_manager_mut().replace_operand(from, to);
187 }
188 }
189
190 /// Returns the operands of current instruction.
191 ///
192 /// # Safety
193 /// You should not use this function, because it may cause unknown errors.
194 #[inline]
195 unsafe fn get_operand_mut(&mut self) -> &mut Vec<Operand> {
196 &mut self.get_manager_mut().operand
197 }
198
199 /// Gets the previous instruction of current instruction.
200 /// If current instruction is the first instruction of the `BasicBlock`, it will return None.
201 ///
202 /// # Panics
203 /// Please make sure the current instruction is in the `BasicBlock`, otherwise it will panic.
204 #[inline]
205 fn get_prev(&self) -> Option<InstPtr> {
206 let prev = self.get_manager().prev.unwrap();
207 if let InstType::Head = prev.get_type() {
208 None
209 } else {
210 Some(prev)
211 }
212 }
213
214 /// Sets the previous instruction of current instruction.
215 ///
216 /// # Safety
217 /// You should not use this function, because it may cause unknown errors.
218 #[inline]
219 unsafe fn set_prev(&mut self, inst: InstPtr) {
220 self.get_manager_mut().prev = Some(inst);
221 }
222
223 /// Gets the next instruction of current instruction.
224 /// If current instruction is the last instruction of the `BasicBlock`, it will return None.
225 ///
226 /// # Panics
227 /// Please make sure the current instruction is in the `BasicBlock`, otherwise it will panic.
228 #[inline]
229 fn get_next(&self) -> Option<InstPtr> {
230 let next = self.get_manager().next.unwrap();
231 if let InstType::Head = next.get_type() {
232 None
233 } else {
234 Some(next)
235 }
236 }
237
238 /// Sets the next instruction of current instruction.
239 ///
240 /// # Safety
241 /// You should not use this function, because it may cause unknown errors.
242 #[inline]
243 unsafe fn set_next(&mut self, inst: InstPtr) {
244 self.get_manager_mut().next = Some(inst);
245 }
246
247 /// Returns the value type of current instruction.
248 #[inline]
249 fn get_value_type(&self) -> ValueType {
250 self.get_manager().value_type.clone()
251 }
252
253 /// Moves the current instruction out of the `BasicBlock`.
254 /// Please ensure that after moving out and inserting the current instruction into another `BasicBlock`,
255 /// the current instruction will not be used again.
256 ///
257 /// # Safety
258 /// This operation is not safe, use other methods instead.
259 /// For example: insert_before, insert_after and remove_self.
260 ///
261 /// # Panics
262 /// Only checked the error of having a predecessor but no successor, in which case it will panic.
263 /// But for the case of having a successor but no predecessor, it does not report an error.
264 unsafe fn move_self(&mut self) {
265 if let Some(mut prev) = self.get_manager().prev {
266 let mut next = self.get_manager().next.unwrap_or_else(|| {
267 panic!(
268 "move_self failed! inst {} has a prev ({}) but no next",
269 self.get_type(),
270 prev.get_type()
271 )
272 });
273 prev.set_next(next);
274 next.set_prev(prev);
275 }
276
277 let manager = self.get_manager_mut();
278 manager.prev = None;
279 manager.next = None;
280 manager.parent_bb = None;
281 }
282
283 /// Inserts a new instruction before the current instruction.
284 /// The operation will first remove the new instruction from the original `BasicBlock`
285 /// and then insert it into the specified position of the current `BasicBlock`.
286 ///
287 /// # Panics
288 /// You need to ensure that the current instruction is definitely in the `BasicBlock`,
289 /// otherwise it will panic.
290 fn insert_before(&mut self, mut inst: InstPtr) {
291 unsafe {
292 inst.move_self();
293 inst.set_parent_bb(self.get_parent_bb().unwrap())
294 }
295
296 let mut prev = self.get_manager().prev.unwrap();
297
298 // 无法通过self获得指向自己的InstPtr,只有通过这种丑陋的方法了
299 let mut self_ptr = prev.get_manager().next.unwrap();
300
301 unsafe {
302 prev.set_next(inst);
303 self_ptr.set_prev(inst);
304 inst.set_prev(prev);
305 inst.set_next(self_ptr);
306 }
307 }
308
309 /// Inserts a new instruction after the current instruction.
310 /// The operation will first remove the new instruction from the original `BasicBlock`
311 /// and then insert it into the specified position of the current `BasicBlock`.
312 ///
313 /// # Panics
314 /// You need to ensure that the current instruction is definitely in the `BasicBlock`,
315 /// otherwise it will panic.
316 fn insert_after(&mut self, mut inst: InstPtr) {
317 unsafe {
318 inst.move_self();
319 inst.set_parent_bb(self.get_parent_bb().unwrap());
320 }
321
322 unsafe {
323 let mut next = self.get_manager_mut().next.unwrap();
324 let mut self_ptr = next.get_manager_mut().prev.unwrap();
325 next.set_prev(inst);
326 self_ptr.set_next(inst);
327 inst.set_prev(self_ptr);
328 inst.set_next(next);
329 }
330 }
331
332 /// Remove current instruction from the `BasicBlock`.
333 /// This operation will remove the current instruction from the `BasicBlock` and clear the current operand.
334 /// # Panics
335 /// Same to move_self
336 fn remove_self(&mut self) {
337 unsafe {
338 let id = self.get_id();
339 self.move_self();
340
341 let manager = self.get_manager_mut();
342
343 manager.prev = None;
344 manager.next = None;
345 manager.operand.iter_mut().for_each(|op| match op {
346 Operand::Instruction(inst) => {
347 inst.get_user_mut().retain(|user| user.get_id() != id);
348 }
349 Operand::Global(gl) => {
350 gl.get_user_mut().retain(|user| user.get_id() != id);
351 }
352 Operand::Parameter(par) => {
353 par.get_user_mut().retain(|user| user.get_id() != id);
354 }
355 Operand::Constant(_) => {}
356 });
357 manager.operand.clear();
358 }
359 }
360
361 /// Replace current instruction with an operand.
362 /// This operation will call `remove_self`, but update all users to use the new operand.
363 fn replace_self(&mut self, operand: &Operand) {
364 let user = self.get_user().to_vec();
365 let self_operand = Operand::Instruction(self.get_manager().self_ptr.unwrap());
366 user.into_iter().for_each(|mut user| {
367 let operand_index = user
368 .get_operand()
369 .iter()
370 .position(|op| op == &self_operand)
371 .unwrap();
372 user.set_operand(operand_index, operand.clone());
373 });
374 self.remove_self();
375 }
376
377 /// Returns the `BasicBlock` that current instruction belongs to.
378 #[inline]
379 fn get_parent_bb(&self) -> Option<BBPtr> {
380 self.get_manager().parent_bb
381 }
382
383 /// Set the parent `BasicBlock` of current instruction.
384 ///
385 /// # Safety
386 /// You should not use this function, because it may cause unknown errors.
387 #[inline]
388 unsafe fn set_parent_bb(&mut self, bb: BBPtr) {
389 self.get_manager_mut().parent_bb = Some(bb);
390 }
391
392 /// Returns `True` if the current instruction is the last instruction in the `BasicBlock`.
393 ///
394 /// # Panics
395 /// Please make sure the current instruction is in the `BasicBlock`, otherwise it will panic.
396 #[inline]
397 fn is_last(&self) -> bool {
398 self.get_manager().next.unwrap().get_type() == InstType::Head
399 }
400
401 /// Returns `True` if the current instruction is the first instruction in the `BasicBlock`.
402 ///
403 /// # Panics
404 /// Please make sure the current instruction is in the `BasicBlock`, otherwise it will panic.
405 #[inline]
406 fn is_first(&self) -> bool {
407 self.get_manager().prev.unwrap().get_type() == InstType::Head
408 }
409
410 /// Returns the unique id of current instruction.
411 fn get_id(&self) -> usize {
412 self.get_manager().id.unwrap()
413 }
414
415 /// 将其生成相关的llvm ir
416 fn gen_llvm_ir(&self) -> String;
417}
418
419impl PartialEq for dyn Instruction {
420 fn eq(&self, other: &Self) -> bool {
421 self.get_id() == other.get_id()
422 }
423}
424
425impl Eq for dyn Instruction {}
426
427impl PartialOrd for dyn Instruction {
428 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
429 Some(self.get_id().cmp(&other.get_id()))
430 }
431}
432
433impl Ord for dyn Instruction {
434 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
435 self.get_id().cmp(&other.get_id())
436 }
437}
438
439/// Downcasts a `dyn instruction` to a `&T`, where `T` is a concrete `Instruction` type.
440///
441/// # Example
442/// ```
443/// # use duskphantom_middle::ir::instruction::{head::Head,downcast_ref};
444/// # use duskphantom_middle::ir::ir_builder::IRBuilder;
445/// # let mut ir_builder = IRBuilder::new();
446/// let dyn_head = ir_builder.new_head();
447/// let head = downcast_ref::<Head>(dyn_head.as_ref().as_ref());
448/// ```
449///
450/// # Panics
451/// If the downcast fails, this function will panic.
452pub fn downcast_ref<T>(inst: &dyn Instruction) -> &T
453where
454 T: 'static + Instruction,
455{
456 unsafe {
457 inst.as_any().downcast_ref::<T>().unwrap_or_else(|| {
458 panic!(
459 "downcast_ref failed! Try to get {} from {}",
460 std::any::type_name::<T>(),
461 inst.get_type()
462 )
463 })
464 }
465}
466
467/// Downcasts a `dyn instruction` to a `&mut T`, where `T` is a concrete `Instruction` type.
468///
469/// # Example
470/// ```
471/// # use duskphantom_middle::ir::instruction::{head::Head,downcast_mut};
472/// # use duskphantom_middle::ir::ir_builder::IRBuilder;
473/// # let mut ir_builder = IRBuilder::new();
474/// let mut dyn_head = ir_builder.new_head();
475/// let add_inst = downcast_mut::<Head>(dyn_head.as_mut());
476/// ```
477///
478/// # Panics
479/// If the downcast fails, this function will panic.
480pub fn downcast_mut<T>(inst: &mut dyn Instruction) -> &mut T
481where
482 T: 'static + Instruction,
483{
484 let inst_type = inst.get_type();
485 unsafe {
486 inst.as_any_mut().downcast_mut::<T>().unwrap_or_else(|| {
487 panic!(
488 "downcast_mut failed! Try to get {} from {}",
489 std::any::type_name::<T>(),
490 inst_type
491 )
492 })
493 }
494}
495
496/// Instruction Manager
497/// This struct is used to manage the instructions.
498/// Including def-use relationship, the relationship between instructions, etc.
499pub struct InstManager {
500 /// The unique id of current instruction.
501 id: Option<usize>,
502 /// The instructions that use current instruction as operand.
503 /// For example: `add a, b`
504 /// `a` and `b` are the operand of `add` instruction.
505 /// At this time, the `user` of `a` and `b` both have `add` instruction.
506 /// The order of `user` does not need to be considered.
507 user: Vec<InstPtr>,
508
509 /// The operand of current instruction.
510 /// For example: `add a, b`
511 /// At this time, the `add` instruction's operand has `a` and `b`.
512 /// The order of `operand` needs to be considered.
513 operand: Vec<Operand>,
514
515 /// Prev instruction of current instruction, if current instruction is not in a `BasicBlock`, it is None.
516 prev: Option<InstPtr>,
517
518 /// Next instruction of current instruction, if current instruction is not in a `BasicBlock`, it is None.
519 next: Option<InstPtr>,
520
521 /// The `BasicBlock` that current instruction belongs to.
522 parent_bb: Option<BBPtr>,
523
524 /// Value type of current instruction.
525 /// Default type is Void.
526 value_type: ValueType,
527
528 /// The ObjPtr of current instruction.
529 self_ptr: Option<InstPtr>,
530}
531
532impl InstManager {
533 pub fn new(value_type: ValueType) -> Self {
534 Self {
535 id: None,
536 user: vec![],
537 operand: vec![],
538 prev: None,
539 next: None,
540 parent_bb: None,
541 value_type,
542 self_ptr: None,
543 }
544 }
545}
546
547impl InstManager {
548 /// # Safety
549 ///
550 /// FIXME: explain why it is unsafe,and describe the safety requirements
551 pub unsafe fn set_operand(&mut self, index: usize, new_op: Operand) {
552 let old_op = std::mem::replace(&mut self.operand[index], new_op.clone());
553 match old_op {
554 Operand::Instruction(mut inst) => {
555 inst.get_user()
556 .iter()
557 .position(|x| x.get_id() == self.id.unwrap())
558 .map(|index| inst.get_user_mut().remove(index));
559 }
560 Operand::Parameter(mut param) => {
561 param
562 .get_user()
563 .iter()
564 .position(|x| x.get_id() == self.id.unwrap())
565 .map(|index| param.get_user_mut().remove(index));
566 }
567 Operand::Global(mut global) => {
568 global
569 .get_user()
570 .iter()
571 .position(|x| x.get_id() == self.id.unwrap())
572 .map(|index| global.get_user_mut().remove(index));
573 }
574 _ => {}
575 }
576 match new_op {
577 Operand::Instruction(mut inst) => {
578 inst.get_user_mut().push(self.self_ptr.unwrap());
579 }
580 Operand::Parameter(mut param) => {
581 param.add_user(self.self_ptr.unwrap());
582 }
583 Operand::Global(mut global) => {
584 global.add_user(self.self_ptr.unwrap());
585 }
586 _ => {}
587 }
588 }
589
590 /// # Safety
591 ///
592 /// FIXME: explain why it is unsafe,and describe the safety requirements
593 pub unsafe fn replace_operand(&mut self, from: &Operand, to: &Operand) {
594 match from {
595 Operand::Instruction(mut inst) => {
596 inst.get_user_mut().retain(|x| x != &self.self_ptr.unwrap());
597 }
598 Operand::Parameter(mut param) => {
599 param
600 .get_user_mut()
601 .retain(|x| x != &self.self_ptr.unwrap());
602 }
603 Operand::Global(mut global) => {
604 global
605 .get_user_mut()
606 .retain(|x| x != &self.self_ptr.unwrap());
607 }
608 _ => {}
609 }
610 match to {
611 Operand::Instruction(mut inst) => {
612 inst.get_user_mut().push(self.self_ptr.unwrap());
613 }
614 Operand::Parameter(mut param) => {
615 param.add_user(self.self_ptr.unwrap());
616 }
617 Operand::Global(mut global) => {
618 global.add_user(self.self_ptr.unwrap());
619 }
620 _ => {}
621 }
622 self.operand.iter_mut().for_each(|op| {
623 if op == from {
624 *op = to.clone();
625 }
626 });
627 }
628
629 /// # Safety
630 ///
631 /// FIXME: explain why it is unsafe,and describe the safety requirements
632 pub unsafe fn add_operand(&mut self, operand: Operand) {
633 match operand {
634 Operand::Instruction(mut inst) => {
635 inst.get_user_mut().push(self.self_ptr.unwrap());
636 }
637 Operand::Parameter(mut param) => {
638 param.add_user(self.self_ptr.unwrap());
639 }
640 Operand::Global(mut global) => {
641 global.add_user(self.self_ptr.unwrap());
642 }
643 _ => {}
644 }
645 self.operand.push(operand);
646 }
647
648 /// # Safety
649 ///
650 /// FIXME: explain why it is unsafe,and describe the safety requirements
651 pub unsafe fn remove_operand(&mut self, index: usize) {
652 let operand = self.operand.remove(index);
653 match operand {
654 Operand::Instruction(mut inst) => {
655 inst.get_user()
656 .iter()
657 .enumerate()
658 .find_map(|(index, x)| {
659 if x.get_id() == self.id.unwrap() {
660 Some(index)
661 } else {
662 None
663 }
664 })
665 .map(|index| Some(inst.get_user_mut().remove(index)));
666 }
667 Operand::Parameter(mut param) => {
668 param
669 .get_user()
670 .iter()
671 .enumerate()
672 .find_map(|(index, x)| {
673 if x.get_id() == self.id.unwrap() {
674 Some(index)
675 } else {
676 None
677 }
678 })
679 .map(|index| Some(param.get_user_mut().remove(index)));
680 }
681 Operand::Global(mut global) => {
682 global
683 .get_user()
684 .iter()
685 .enumerate()
686 .find_map(|(index, x)| {
687 if x.get_id() == self.id.unwrap() {
688 Some(index)
689 } else {
690 None
691 }
692 })
693 .map(|index| Some(global.get_user_mut().remove(index)));
694 }
695 _ => {}
696 }
697 }
698
699 /// # Safety
700 ///
701 /// FIXME: explain why it is unsafe,and describe the safety requirements
702 pub unsafe fn set_id(&mut self, id: usize) {
703 self.id = Some(id);
704 }
705
706 /// # Safety
707 ///
708 /// FIXME: explain why it is unsafe,and describe the safety requirements
709 pub unsafe fn set_self_ptr(&mut self, self_ptr: InstPtr) {
710 self.self_ptr = Some(self_ptr);
711 }
712}