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
use inkwell::basic_block::BasicBlock;
use inkwell::module::Module;
use inkwell::values::{FunctionValue, GlobalValue, InstructionValue};

/// Convenient iterator for enumerating functions.
pub struct FunctionIterator<'a, 'ctx> {
    module: &'a Module<'ctx>,
    func: Option<FunctionValue<'ctx>>,
}

impl<'a, 'ctx> FunctionIterator<'a, 'ctx> {
    /// Create a new [`FunctionIterator`] from a [`Module`].
    pub fn new(module: &'a Module<'ctx>) -> Self {
        Self { module, func: None }
    }
}

impl<'a, 'ctx> Iterator for FunctionIterator<'a, 'ctx> {
    type Item = FunctionValue<'ctx>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(func) = self.func {
            self.func = func.get_next_function();
            return self.func;
        }

        self.func = Some(self.module.get_first_function()?);
        self.func
    }
}

/// Convenient iterator for enumerating globals.
pub struct GlobalIterator<'a, 'ctx> {
    module: &'a Module<'ctx>,
    global: Option<GlobalValue<'ctx>>,
}

impl<'a, 'ctx> GlobalIterator<'a, 'ctx> {
    /// Create a new [`GlobalIterator`] from a [`Module`].
    pub fn new(module: &'a Module<'ctx>) -> Self {
        Self {
            module,
            global: None,
        }
    }
}

impl<'a, 'ctx> Iterator for GlobalIterator<'a, 'ctx> {
    type Item = GlobalValue<'ctx>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(global) = self.global {
            self.global = global.get_next_global();
            return self.global;
        }

        self.global = Some(self.module.get_first_global()?);
        self.global
    }
}

/// Convenient iterator for enumerating globals.
pub struct InstructionIterator<'a, 'ctx> {
    bb: &'a BasicBlock<'ctx>,
    instr: Option<InstructionValue<'ctx>>,
}

impl<'a, 'ctx> InstructionIterator<'a, 'ctx> {
    /// Create a new [`InstructionIterator`] from a [`BasicBlock`].
    pub fn new(bb: &'a BasicBlock<'ctx>) -> Self {
        Self { bb, instr: None }
    }
}

impl<'a, 'ctx> Iterator for InstructionIterator<'a, 'ctx> {
    type Item = InstructionValue<'ctx>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(instr) = self.instr {
            self.instr = instr.get_next_instruction();
            return self.instr;
        }

        self.instr = Some(self.bb.get_first_instruction()?);
        self.instr
    }
}