WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

tree_gen.rs 5.17 KB
Newer Older
1
2
3
use ast::ir::*;
use ast::ir_semantics::*;
use vm::context::VMContext;
4
5
use compiler::CompilerPass;

qinsoon's avatar
qinsoon committed
6
pub struct TreeGen {
7
    name: &'static str
qinsoon's avatar
qinsoon committed
8
} 
9

qinsoon's avatar
qinsoon committed
10
11
12
impl TreeGen {
    pub fn new() -> TreeGen {
        TreeGen{name: "Tree Geenration"}
13
14
15
    }
}

16
17
18
19
fn is_movable(expr: &Instruction_) -> bool {
    !has_side_effect(expr)
}

qinsoon's avatar
qinsoon committed
20
impl CompilerPass for TreeGen {
qinsoon's avatar
qinsoon committed
21
22
    fn name(&self) -> &'static str {
        self.name
23
    }
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    
    fn execute(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
        debug!("---CompilerPass {} for {}---", self.name(), func.fn_name);
        
        for entry in func.content.as_mut().unwrap().blocks.iter_mut() {
            let label : MuTag = entry.0;
            let ref mut block : &mut Block = &mut entry.1;
            
            // take its content, we will need to put it back
            let mut content = block.content.take().unwrap();
            let body = content.body;
            
            let mut new_body = vec![];
            
            trace!("check block {}", label);
            trace!("");
            
            for node in body.into_iter() {
42
                trace!("check inst: {}", node);
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
                match &node.v {
                    &TreeNode_::Instruction(ref inst) => {
                        // check if any operands can be replaced by expression
                        {
                            trace!("check if we can replace any operand with inst");
                            
                            let mut ops = inst.ops.borrow_mut();
                            for index in 0..ops.len() {
                                let possible_ssa_id = ops[index].extract_ssa_id();
                                if possible_ssa_id.is_some() {
                                    let entry_value = func.context.get_value_mut(possible_ssa_id.unwrap()).unwrap();
                                    
                                    if entry_value.expr.is_some() {
                                        // replace the node with its expr
                                        let expr = entry_value.expr.take().unwrap();
                                        
59
                                        trace!("{} replaced by {}", ops[index], expr);
60
61
62
                                        ops[index] = TreeNode::new_inst(expr);
                                    }
                                } else {
63
                                    trace!("{} cant be replaced", ops[index]);
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
                                }
                            }
                        }
                        
                        // check if left hand side of an assignment has a single use
                        trace!("check if we should fold the inst");
                        if inst.value.is_some() {
                            let left = inst.value.as_ref().unwrap();
                            
                            // if left is _one_ variable that is used once
                            // we can put the expression as a child node to its use
                            if left.len() == 1 {
                                let lhs = func.context.get_value_mut(left[0].extract_ssa_id().unwrap()).unwrap(); 
                                if lhs.use_count.get() == 1{
                                    if is_movable(&inst.v) {
                                        lhs.expr = Some(inst.clone()); // FIXME: should be able to move the inst here 
                                        
                                        trace!("yes");
                                        trace!("");
                                        continue;
                                    } else {
                                        trace!("no, not movable");
                                    }
                                } else {
                                    trace!("no, use count more than 1");
                                }
                            } else {
                                trace!("no, yields more than 1 SSA var");
                            }
                        } else {
                            trace!("no, no value yielded");
                        }
                    },
                    _ => panic!("expected an instruction node here")
                }
                
100
                trace!("add {} back to block {}", node, label);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
                trace!("");
                new_body.push(node);
            }
            
            content.body = new_body;
            trace!("block {} has {} insts", label, content.body.len());
            trace!("");
                        
            // put the content back
            block.content = Some(content);
        }
        
        self.finish_function(vm_context, func);
        
        debug!("---finish---");
    }
    
    #[allow(unused_variables)]
    fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
        debug!("check depth tree for {}", func.fn_name);
        
        for entry in func.content.as_ref().unwrap().blocks.iter() {
            debug!("block {}", entry.0);
            
            for inst in entry.1.content.as_ref().unwrap().body.iter() {
126
                debug!("{}", inst);
127
128
129
            }
        }
    }
130
}