GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

aot.rs 4.03 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 13 14 15 16 17 18 19 20 21

fn link_executable_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
    let mut gcc = Command::new(get_test_clang_path());

    for file in files {
        println!("link with {:?}", file.as_path());
        gcc.arg(file.as_path());
    }

    println!("output as {:?}", out.as_path());
    if cfg!(target_os = "linux") {
        gcc.arg("-ldl");
qinsoon's avatar
qinsoon committed
22 23
        gcc.arg("-lrt");
        gcc.arg("-lm");
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
        gcc.arg("-lpthread");
    }
    // so we can find symbols in itself
    gcc.arg("-rdynamic");
    gcc.arg("-o");
    gcc.arg(out.as_os_str());

    assert!(exec(gcc).status.success());

    out
}

fn link_dylib_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
    let mut object_files : Vec<PathBuf> = vec![];

    for file in files {
        let mut gcc = Command::new(get_test_clang_path());

        gcc.arg("-c");
43
        gcc.arg("-fPIC");
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

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

        gcc.arg(file.as_os_str());
        gcc.arg("-o");
        gcc.arg(out.as_os_str());

        object_files.push(out);
        exec(gcc);
    }

    let mut gcc = Command::new(get_test_clang_path());
    gcc.arg("-shared");
    gcc.arg("-Wl");
    gcc.arg("-undefined");
    gcc.arg("dynamic_lookup");
    for obj in object_files {
        gcc.arg(obj.as_os_str());
    }
64

65 66 67 68 69 70 71 72
    gcc.arg("-o");
    gcc.arg(out.as_os_str());

    exec(gcc);

    out
}

qinsoon's avatar
qinsoon committed
73 74
fn get_path_for_mu_func (f: MuName, vm: &VM) -> PathBuf {
    let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
75 76 77 78 79 80
    ret.push(f);
    ret.set_extension("s");

    ret
}

qinsoon's avatar
qinsoon committed
81 82
fn get_path_for_mu_context (vm: &VM) -> PathBuf {
    let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
83 84 85 86
    ret.push(backend::AOT_EMIT_CONTEXT_FILE);
    ret
}

qinsoon's avatar
qinsoon committed
87 88
pub fn link_primordial (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
    let emit_dir = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
89 90 91 92 93 94 95 96

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

        let mut ret = vec![];

        // all interested mu funcs
        for func in funcs {
qinsoon's avatar
qinsoon committed
97
            ret.push(get_path_for_mu_func(func, vm));
98 99 100
        }

        // mu context
qinsoon's avatar
qinsoon committed
101
        ret.push(get_path_for_mu_context(vm));
102 103 104

        // copy primoridal entry
        let source   = PathBuf::from(runtime::PRIMORDIAL_ENTRY);
qinsoon's avatar
qinsoon committed
105
        let mut dest = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
        dest.push("main.c");
        fs::copy(source.as_path(), dest.as_path()).unwrap();
        // include the primordial C main
        ret.push(dest);

        // include mu static lib
        let libmu = PathBuf::from("target/debug/libmu.a");
        ret.push(libmu);

        ret
    };

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

    link_executable_internal(files, out_path)
}

qinsoon's avatar
qinsoon committed
124 125 126 127 128 129
pub fn execute(executable: PathBuf) -> Output {
    let run = Command::new(executable.as_os_str());
    exec(run)
}

pub fn execute_nocheck(executable: PathBuf) -> Output {
130
    let run = Command::new(executable.as_os_str());
qinsoon's avatar
qinsoon committed
131
    exec_nocheck(run)
132 133
}

qinsoon's avatar
qinsoon committed
134
pub fn link_dylib (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
135 136 137 138
    let files = {
        let mut ret = vec![];

        for func in funcs {
qinsoon's avatar
qinsoon committed
139
            ret.push(get_path_for_mu_func(func, vm));
140 141
        }

qinsoon's avatar
qinsoon committed
142
        ret.push(get_path_for_mu_context(vm));
143 144 145 146

        ret
    };

qinsoon's avatar
qinsoon committed
147
    let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
148 149
    out_path.push(out);

150 151 152
    link_dylib_internal(files, out_path)
}

qinsoon's avatar
qinsoon committed
153
pub fn link_dylib_with_extra_srcs(funcs: Vec<MuName>, srcs: Vec<String>, out: &str, vm: &VM) -> PathBuf{
154 155 156 157
    let files = {
        let mut ret = vec![];

        for func in funcs {
qinsoon's avatar
qinsoon committed
158
            ret.push(get_path_for_mu_func(func, vm));
159 160 161
        }

        for src in srcs {
John Zhang's avatar
fix  
John Zhang committed
162
            ret.push(PathBuf::from(src));
163 164
        }

qinsoon's avatar
qinsoon committed
165
        ret.push(get_path_for_mu_context(vm));
166 167 168 169

        ret
    };

qinsoon's avatar
qinsoon committed
170
    let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
171 172
    out_path.push(out);

173
    link_dylib_internal(files, out_path)
174
}