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}