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.

code_emission.rs 5.43 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Copyright 2017 The Australian National University
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
16
17
18
#![allow(dead_code)]

use compiler::CompilerPass;
use ast::ir::*;
qinsoon's avatar
qinsoon committed
19
use vm::VM;
20
use compiler::backend::emit_code;
qinsoon's avatar
qinsoon committed
21
22
use std::any::Any;

qinsoon's avatar
qinsoon committed
23
24
25
use std::path;
use std::io::prelude::*;
use std::fs::File;
26
use std::collections::HashMap;
qinsoon's avatar
qinsoon committed
27

28
29
pub const EMIT_MUIR : bool = true;
pub const EMIT_MC_DOT : bool = true;
qinsoon's avatar
qinsoon committed
30
31
32
33
34
35
36
37
38

pub fn create_emit_directory(vm: &VM) {
    use std::fs;
    match fs::create_dir(&vm.vm_options.flag_aot_emit_dir) {
        Ok(_) => {},
        Err(_) => {}
    }
}

39
#[allow(dead_code)]
40
pub fn emit_mu_types(suffix: &str, vm: &VM) {
41
42
43
44
45
    if EMIT_MUIR {
        create_emit_directory(vm);

        let mut file_path = path::PathBuf::new();
        file_path.push(&vm.vm_options.flag_aot_emit_dir);
46
        file_path.push("___types".to_string() + suffix + ".muty");
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        let mut file = match File::create(file_path.as_path()) {
            Err(why) => panic!("couldn't create mu types file {}: {}", file_path.to_str().unwrap(), why),
            Ok(file) => file
        };

        {
            use ast::types::*;

            let ty_guard = vm.types().read().unwrap();
            let struct_map = STRUCT_TAG_MAP.read().unwrap();
            let hybrid_map = HYBRID_TAG_MAP.read().unwrap();

            for ty in ty_guard.values() {
                if ty.is_struct() {
61
                    write!(file, "{}", ty).unwrap();
62
63

                    let struct_ty = struct_map.get(&ty.get_struct_hybrid_tag().unwrap()).unwrap();
64
65
                    writeln!(file, " -> {}", struct_ty).unwrap();
                    writeln!(file, "  {}", vm.get_backend_type_info(ty.id())).unwrap();
66
                } else if ty.is_hybrid() {
67
                    write!(file, "{}", ty).unwrap();
68
                    let hybrid_ty = hybrid_map.get(&ty.get_struct_hybrid_tag().unwrap()).unwrap();
69
70
                    writeln!(file, " -> {}", hybrid_ty).unwrap();
                    writeln!(file, "  {}", vm.get_backend_type_info(ty.id())).unwrap();
71
                } else {
qinsoon's avatar
qinsoon committed
72
                    // we only care about struct
73
74
75
76
77
78
79
80
                }
            }
        }


    }
}

81
82
83
84
fn create_emit_file(name: String, vm: &VM) -> File {
    let mut file_path = path::PathBuf::new();
    file_path.push(&vm.vm_options.flag_aot_emit_dir);
    file_path.push(name);
qinsoon's avatar
qinsoon committed
85

86
87
88
    match File::create(file_path.as_path()) {
        Err(why) => panic!("couldn't create emit file {}: {}", file_path.to_str().unwrap(), why),
        Ok(file) => file
qinsoon's avatar
qinsoon committed
89
90
    }
}
qinsoon's avatar
qinsoon committed
91

92
93
pub struct CodeEmission {
    name: &'static str
qinsoon's avatar
qinsoon committed
94
95
}

96
97
98
99
impl CodeEmission {
    pub fn new() -> CodeEmission {
        CodeEmission {
            name: "Code Emission"
100
        }
qinsoon's avatar
qinsoon committed
101
    }
102
103
}

104
fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
105
    let func_name = func.name();
106
107
108

    // create emit directory/file
    create_emit_directory(vm);
109
    let mut file = create_emit_file(func_name.clone() + ".mc.dot", &vm);
110
111

    // diagraph func {
112
    writeln!(file, "digraph {} {{", mangle_name(func_name)).unwrap();
113
    // node shape: rect
114
    writeln!(file, "node [shape=rect];").unwrap();
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

    let compiled_funcs = vm.compiled_funcs().read().unwrap();
    let cf = compiled_funcs.get(&func.id()).unwrap().read().unwrap();
    let mc = cf.mc();

    let blocks = mc.get_all_blocks();

    type DotID = usize;
    let name_id_map : HashMap<MuName, DotID> = {
        let mut ret = HashMap::new();
        let mut index = 0;

        for block_name in blocks.iter() {
            ret.insert(block_name.clone(), index);
            index += 1;
        }

        ret
    };
    let id = |x: MuName| name_id_map.get(&x).unwrap();

    for block_name in blocks.iter() {
        // BB [label = "
138
        write!(file, "{} [label = \"{}:\\l\\l", id(block_name.clone()), block_name).unwrap();
139
140

        for inst in mc.get_block_range(&block_name).unwrap() {
141
142
            file.write_all(&mc.emit_inst(inst)).unwrap();
            write!(file, "\\l").unwrap();
143
144
145
        }

        // "];
146
        writeln!(file, "\"];").unwrap();
147
148
149
150
151
152
    }

    for block_name in blocks.iter() {
        let end_inst = mc.get_block_range(block_name).unwrap().end;

        for succ in mc.get_succs(mc.get_last_inst(end_inst).unwrap()).into_iter() {
153
                match mc.get_block_for_inst(*succ) {
154
155
156
                Some(target) => {
                    let source_id = id(block_name.clone());
                    let target_id = id(target.clone());
157
                    writeln!(file, "{} -> {};", source_id, target_id).unwrap();
158
159
                }
                None => {
160
                    panic!("cannot find succesor {} for block {}", succ, block_name);
161
162
163
164
165
                }
            }
        }
    }

166
    writeln!(file, "}}").unwrap();
167
168
}

169
170
171
172
impl CompilerPass for CodeEmission {
    fn name(&self) -> &'static str {
        self.name
    }
qinsoon's avatar
qinsoon committed
173

qinsoon's avatar
qinsoon committed
174
175
176
177
    fn as_any(&self) -> &Any {
        self
    }

qinsoon's avatar
qinsoon committed
178
179
    fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
        emit_code(func, vm);
qinsoon's avatar
qinsoon committed
180

181
182
183
        if EMIT_MC_DOT {
            emit_mc_dot(func, vm);
        }
184
    }
qinsoon's avatar
qinsoon committed
185
}