1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/// Builtin interfaces.
///
/// This module provides builtin interfaces for regions, values, successors.
///
/// These interfaces can be derived with the macro and are mandatory for all
/// operations.
use crate::{ArenaPtr, Context, Region, RegionKind, Successor, TyObj, Value};

/// Builtin region interface.
///
/// This trait provides methods to interact with regions. This is set to be a
/// mandatory interface for all operations for performance reasons.
pub trait RegionInterface {
    /// Get the number of regions.
    fn num_regions(&self) -> usize;

    /// Get the region at the given index.
    fn get_region(&self, index: usize) -> Option<ArenaPtr<Region>>;

    /// Set the region at the given index and return the old region (if any).
    fn set_region(&mut self, index: usize, region: ArenaPtr<Region>) -> Option<ArenaPtr<Region>>;

    /// Get all regions.
    fn regions(&self) -> Vec<ArenaPtr<Region>> {
        (0..self.num_regions())
            .filter_map(|index| self.get_region(index))
            .collect()
    }

    /// Get the region kind at the given index.
    fn get_region_kind(&self, ctx: &Context, index: usize) -> RegionKind {
        self.get_region(index).unwrap().deref(&ctx.regions).kind()
    }

    /// Check if the region has SSA dominance.
    fn has_ssa_dominance(&self, ctx: &Context, index: usize) -> bool {
        self.get_region_kind(ctx, index) == RegionKind::SsaCfg
    }
}

/// Builtin value interface.
///
/// This trait provides methods to interact with values. This is set to be a
/// mandatory interface for all operations for performance reasons.
pub trait DataFlow {
    /// Get the number of operands.
    ///
    /// This is also the number of uses of the operation.
    fn num_operands(&self) -> usize;

    /// Get the number of results.
    ///
    /// This is also the number of definitions of the operation.
    fn num_results(&self) -> usize;

    /// Get the operand at the given index.
    fn get_operand(&self, index: usize) -> Option<ArenaPtr<Value>>;

    /// Get the result at the given index.
    fn get_result(&self, index: usize) -> Option<ArenaPtr<Value>>;

    /// Set the operand at the given index and return the old operand (if any).
    fn set_operand(&mut self, index: usize, operand: ArenaPtr<Value>) -> Option<ArenaPtr<Value>>;

    /// Set the result at the given index and return the old result (if any).
    fn set_result(&mut self, index: usize, result: ArenaPtr<Value>) -> Option<ArenaPtr<Value>>;

    /// Get all operands.
    fn operands(&self) -> Vec<ArenaPtr<Value>> {
        (0..self.num_operands())
            .filter_map(|index| self.get_operand(index))
            .collect()
    }

    /// Get all results.
    fn results(&self) -> Vec<ArenaPtr<Value>> {
        (0..self.num_results())
            .filter_map(|index| self.get_result(index))
            .collect()
    }

    /// Get all operand types.
    fn operand_tys(&self, ctx: &Context) -> Vec<ArenaPtr<TyObj>> {
        self.operands()
            .iter()
            .map(|operand| operand.deref(&ctx.values).ty(ctx))
            .collect()
    }

    /// Get all result types.
    fn result_tys(&self, ctx: &Context) -> Vec<ArenaPtr<TyObj>> {
        self.results()
            .iter()
            .map(|result| result.deref(&ctx.values).ty(ctx))
            .collect()
    }
}

/// Builtin type interface.
///
/// This trait provides methods to interact with types. This is set to be a
/// mandatory interface for all operations for performance reasons.
pub trait ControlFlow {
    /// Get the number of successors.
    fn num_successors(&self) -> usize;

    /// Get the successor at the given index.
    fn get_successor(&self, index: usize) -> Option<&Successor>;

    /// Set the successor at the given index and return the old successor (if
    /// any).
    fn set_successor(&mut self, index: usize, successor: Successor) -> Option<Successor>;

    /// Get all successors.
    fn successors(&self) -> Vec<&Successor> {
        (0..self.num_successors())
            .filter_map(|index| self.get_successor(index))
            .collect()
    }
}