GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

aot.rs 5.53 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
use testutil::*;
2 3
use ast::ir::MuName;
use runtime;
qinsoon's avatar
qinsoon committed
4
use vm::VM;
5
use compiler::backend;
qinsoon's avatar
qinsoon committed
6

7 8
use std::path::PathBuf;
use std::process::Command;
qinsoon's avatar
qinsoon committed
9
use std::process::Output;
10

11 12
fn link_executable_internal (files: Vec<PathBuf>, lib: &Vec<String>, libpath: &Vec<String>, out: PathBuf) -> PathBuf {
    let mut cc = Command::new(get_test_clang_path());
13 14

    for file in files {
15
        info!("link with {:?}", file.as_path());
16 17 18 19 20 21 22 23 24
        cc.arg(file.as_path());
    }

    // external libs
    for path in libpath.iter() {
        cc.arg(format!("-L{}", path));
    }
    for l in lib.iter() {
        cc.arg(format!("-l{}", l));
25 26
    }

27
    info!("output as {:?}", out.as_path());
28
    if cfg!(target_os = "linux") {
29 30 31 32
        cc.arg("-ldl");
        cc.arg("-lrt");
        cc.arg("-lm");
        cc.arg("-lpthread");
33
    }
34

35
    // so we can find symbols in itself
36 37 38
    cc.arg("-rdynamic");
    cc.arg("-o");
    cc.arg(out.as_os_str());
39

40
    assert!(exec(cc).status.success());
41 42 43 44

    out
}

45
fn link_dylib_internal (files: Vec<PathBuf>, lib: &Vec<String>, libpath: &Vec<String>, out: PathBuf) -> PathBuf {
46 47 48
    let mut object_files : Vec<PathBuf> = vec![];

    for file in files {
49
        let mut cc = Command::new(get_test_clang_path());
50

51 52
        cc.arg("-c");
        cc.arg("-fPIC");
53 54 55 56

        let mut out = file.clone();
        out.set_extension("o");

57 58 59
        cc.arg(file.as_os_str());
        cc.arg("-o");
        cc.arg(out.as_os_str());
60 61

        object_files.push(out);
62 63 64 65 66
        exec(cc);
    }

    let mut cc = Command::new(get_test_clang_path());

67 68 69 70 71 72 73 74 75
    // include mu static lib
    let libmu_path = if cfg!(debug_assertions) {
        "target/debug/libmu.a"
    } else {
        "target/release/libmu.a"
    };
    let libmu = get_path_under_mu(libmu_path);
    cc.arg(format!("{}", libmu.to_str().unwrap()));

76 77 78 79 80 81
    // external libs
    for path in libpath.iter() {
        cc.arg(format!("-L{}", path));
    }
    for l in lib.iter() {
        cc.arg(format!("-l{}", l));
82 83
    }

84 85 86 87 88
    cc.arg("-shared");
    cc.arg("-fPIC");
    cc.arg("-Wl");
    cc.arg("-undefined");
    cc.arg("dynamic_lookup");
89
    for obj in object_files {
90
        cc.arg(obj.as_os_str());
91
    }
92

93 94
    cc.arg("-o");
    cc.arg(out.as_os_str());
95

96
    exec(cc);
97 98 99 100

    out
}

qinsoon's avatar
qinsoon committed
101 102
fn get_path_for_mu_func (f: MuName, vm: &VM) -> PathBuf {
    let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
103 104 105 106 107 108
    ret.push(f);
    ret.set_extension("s");

    ret
}

qinsoon's avatar
qinsoon committed
109 110
fn get_path_for_mu_context (vm: &VM) -> PathBuf {
    let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
111 112 113 114
    ret.push(backend::AOT_EMIT_CONTEXT_FILE);
    ret
}

qinsoon's avatar
qinsoon committed
115 116
pub fn link_primordial (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
    let emit_dir = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
117 118 119 120 121 122 123 124

    let files : Vec<PathBuf> = {
        use std::fs;

        let mut ret = vec![];

        // all interested mu funcs
        for func in funcs {
qinsoon's avatar
qinsoon committed
125
            ret.push(get_path_for_mu_func(func, vm));
126 127 128
        }

        // mu context
qinsoon's avatar
qinsoon committed
129
        ret.push(get_path_for_mu_context(vm));
130 131

        // copy primoridal entry
132 133 134 135 136 137 138 139 140
        let source   = get_path_under_mu(runtime::PRIMORDIAL_ENTRY);
        let dest = {
            let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
            ret.push("main.c");

            ret
        };

        trace!("copying from {:?} to {:?}", source, dest);
141 142 143 144
        match fs::copy(source.as_path(), dest.as_path()) {
            Ok(_)  => {},
            Err(e) => panic!("failed to copy: {}", e)
        }
145

146 147 148 149
        // include the primordial C main
        ret.push(dest);

        // include mu static lib
150 151 152 153 154 155
        let libmu_path = if cfg!(debug_assertions) {
            "target/debug/libmu.a"
        } else {
            "target/release/libmu.a"
        };
        let libmu = get_path_under_mu(libmu_path);
156 157 158 159 160 161 162 163
        ret.push(libmu);

        ret
    };

    let mut out_path = emit_dir.clone();
    out_path.push(out);

164 165 166 167
    link_executable_internal(files,
                             &vm.vm_options.flag_bootimage_external_lib,
                             &vm.vm_options.flag_bootimage_external_libpath,
                             out_path)
168 169
}

qinsoon's avatar
qinsoon committed
170 171 172 173 174 175
pub fn execute(executable: PathBuf) -> Output {
    let run = Command::new(executable.as_os_str());
    exec(run)
}

pub fn execute_nocheck(executable: PathBuf) -> Output {
176
    let run = Command::new(executable.as_os_str());
qinsoon's avatar
qinsoon committed
177
    exec_nocheck(run)
178 179
}

qinsoon's avatar
qinsoon committed
180
pub fn link_dylib (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
181 182 183 184
    let files = {
        let mut ret = vec![];

        for func in funcs {
qinsoon's avatar
qinsoon committed
185
            ret.push(get_path_for_mu_func(func, vm));
186 187
        }

qinsoon's avatar
qinsoon committed
188
        ret.push(get_path_for_mu_context(vm));
189 190 191 192

        ret
    };

qinsoon's avatar
qinsoon committed
193
    let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
194 195
    out_path.push(out);

196 197 198 199
    link_dylib_internal(files,
                        &vm.vm_options.flag_bootimage_external_lib,
                        &vm.vm_options.flag_bootimage_external_libpath,
                        out_path)
200 201
}

qinsoon's avatar
qinsoon committed
202
pub fn link_dylib_with_extra_srcs(funcs: Vec<MuName>, srcs: Vec<String>, out: &str, vm: &VM) -> PathBuf{
203 204 205 206
    let files = {
        let mut ret = vec![];

        for func in funcs {
qinsoon's avatar
qinsoon committed
207
            ret.push(get_path_for_mu_func(func, vm));
208 209 210
        }

        for src in srcs {
John Zhang's avatar
John Zhang committed
211
            ret.push(PathBuf::from(src));
212 213
        }

qinsoon's avatar
qinsoon committed
214
        ret.push(get_path_for_mu_context(vm));
215 216 217 218

        ret
    };

qinsoon's avatar
qinsoon committed
219
    let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
220 221
    out_path.push(out);

222 223 224 225
    link_dylib_internal(files,
                        &vm.vm_options.flag_bootimage_external_lib,
                        &vm.vm_options.flag_bootimage_external_libpath,
                        out_path)
226
}