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
}