Commit 8aa7ba36 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Merge branch 'develop' of gitlab.anu.edu.au:mu/mu-impl-fast into develop

parents 18d3368e b92de713
......@@ -26,16 +26,19 @@ doctest = false
default = ["aot"]
aot = []
jit = []
sel4-rumprun = []
sel4-rumprun-target-side = []
[build-dependencies]
gcc = "*"
built = "0.1"
#built = "0.1"
[dependencies]
mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"}
mu_gc = {path = "src/gc"}
#mu_gc = {path = "src/gc"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../rodal_test/rodal", version = ">= 0.0.5" }
libc="*"
field-offset = "*"
......@@ -55,4 +58,21 @@ docopt = "*"
petgraph = "*"
extprim = "*"
num-traits = "*"
#built = "0.1"
[target.x86_64-unknown-linux-gnu.dependencies]
mu_gc = { path = "src/gc", default-features = false}
built = "0.1"
[target.x86_64-apple-darwin.dependencies]
mu_gc = { path = "src/gc", default-features = false}
built = "0.1"
[target.x86_64-rumprun-netbsd.dependencies]
mu_gc = { path = "src/gc", default-features = false, features = ["sel4-rumprun-target-side"], target = "x86_64-rumprun-netbsd"}
[target.x86_64-unknown-linux-gnu.build-dependencies]
built = "0.1"
[target.x86_64-apple-darwin.build-dependencies]
built = "0.1"
......@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[cfg(not(feature = "sel4-rumprun-target-side"))]
extern crate built;
extern crate gcc;
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")]
fn main() {
......@@ -29,6 +32,7 @@ fn main() {
built();
}
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")]
fn main() {
......@@ -43,6 +47,34 @@ fn main() {
built();
}
#[cfg(not(feature = "sel4-rumprun-target-side"))]
fn built() {
built::write_built_file().expect("Failed to acquire build-time information");
}
#[cfg(feature = "sel4-rumprun-target-side")]
#[cfg(target_arch = "x86_64")]
fn main() {
use std::path::Path;
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_x64_sel4_rumprun_sysv.c")
.compile("libruntime_c.a");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_asm_x64_sel4_rumprun_sysv.S")
.compile("libruntime_asm.a");
gcc::Config::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("zebu_c_helpers.c")
.compile("libzebu_c_helpers.a");
}
#!/usr/bin/env bash
export ZEBU_TARGET=x86_64-rumprun-netbsd
cd ././../rumprun-sel4/
bash clean_and_build.sh
\ No newline at end of file
......@@ -26,3 +26,4 @@ lazy_static = "*"
log = "*"
simple_logger = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
......@@ -3574,6 +3574,7 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
}
}
use std::collections::HashMap;
pub fn emit_context_with_reloc(
......
......@@ -15,6 +15,7 @@
#![allow(unused_variables)]
use compiler::backend::AOT_EMIT_CONTEXT_FILE;
use compiler::backend::AOT_EMIT_SYM_TABLE_FILE;
use compiler::backend::RegGroup;
use utils::ByteSize;
use utils::Address;
......@@ -3792,6 +3793,7 @@ fn write_const_align(f: &mut File) {
}
/// writes alignment in bytes for linux
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
......@@ -3801,6 +3803,7 @@ fn write_align(f: &mut File, align: ByteSize) {
/// writes alignment for macos. For macos, .align is followed by exponent
/// (e.g. 16 bytes is 2^4, writes .align 4 on macos)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
......@@ -3815,6 +3818,14 @@ fn write_align(f: &mut File, align: ByteSize) {
f.write_fmt(format_args!("\t.align {}\n", n)).unwrap();
}
/// writes alignment in bytes for sel4-rumprun, which is exactly the same as Linux
#[cfg(feature = "sel4-rumprun")]
fn write_align(f: &mut File, align: ByteSize) {
use std::io::Write;
f.write_fmt(format_args!("\t.align {}\n", check_align(align)))
.unwrap();
}
/// writes a constant to assembly output
fn write_const(f: &mut File, constant: P<Value>, loc: P<Value>) {
use std::io::Write;
......@@ -3901,6 +3912,149 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
}
}
#[cfg(not(feature = "sel4-rumprun"))]
pub fn emit_sym_table(vm: &VM) {
debug!("Currently nothing to emit for --!");
}
fn mangle_all(name_vec: &mut Vec<String>) {
for i in 0..name_vec.len() {
name_vec[i] = name_vec[i]
.replace('.', "Zd")
.replace('-', "Zh")
.replace(':', "Zc")
.replace('#', "Za");
name_vec[i] = "__mu_".to_string() + &name_vec[i];
}
}
#[cfg(feature = "sel4-rumprun")]
pub fn emit_sym_table(vm: &VM) {
use std::path;
use std::io::Write;
// Here goes the code to generate an asm file to resolve symbol addresses at link time
// in this stage, a single sym_file is generated for the test
// these sym_files will be compiled in build.rs in the parent directory of sel4 side
//**************************************************
// first create the asm file in the correct path
// _st added file name and path stands for _SymTable
//*************************************************
debug!("Going to emit Sym table for sel4-rumprun");
let mut file_path_st = path::PathBuf::new();
file_path_st.push(&vm.vm_options.flag_aot_emit_dir);
// vm file name is: "mu_sym_table.s"
file_path_st.push(format!("{}", AOT_EMIT_SYM_TABLE_FILE));
let mut file_st = match File::create(file_path_st.as_path()) {
Err(why) => {
panic!(
"couldn't create SYM TABLE file {}: {}",
file_path_st.to_str().unwrap(),
why
)
}
Ok(file) => file
};
// **************************************************
// mu_sym_table.s content generation
// *************************************************
// Code for exporting all of the required symbols \
// in vm, using the following fields:
// compiled_funcs.CompiledFunction.start
// compiled_funcs.CompiledFunction.end
// compiled_funcs.CompiledFunction.Frame. \
// exception_callsites[iter](src,_)
// compiled_funcs.CompiledFunction.Frame. \
// exception_callsites[iter](_,dest)
// ret
// *************************************************
let mut sym_vec: Vec<String> = Vec::new();
let compiled_funcs: &HashMap<_, _> = &vm.compiled_funcs().read().unwrap();
for (theID, theCFs) in compiled_funcs.iter() {
let theCF: &CompiledFunction = &theCFs.read().unwrap();
match theCF.start {
// CF.start can only be relocatable , otherwise panic
ValueLocation::Relocatable(_, ref symbol) => {
// debug!("theCF.start, symbol = {}\n", *symbol);
sym_vec.push((*symbol).clone());
}
// CF.start can't reach this state
_ => {
panic!(
"Sym_Table_start: expecting Relocatable location, found {}",
theCF.start
)
}
}
match theCF.end {
// CF.start can only be relocatable , otherwise panic
ValueLocation::Relocatable(_, ref symbol) => {
// debug!("theCF.end, symbol = {}\n", *symbol);
sym_vec.push((*symbol).clone());
}
// CF.end can't reach this state
_ => {
panic!(
"Sym_Table_end: expecting Relocatable location, found {}",
theCF.end
)
}
}
// for &(ref callsite, ref dest) in theCF.frame.get_exception_callsites().iter(){
// match *callsite {
// ValueLocation::Relocatable(_, ref symbol) => {
// sym_vec.push((*symbol).clone());
// },
// // can't reach this state
// _ => panic!("Sym_Table_callsite: expecting Relocatable location, found {}",
// callsite)
// }
// match *dest {
// ValueLocation::Relocatable(_, ref symbol) => {
// sym_vec.push((*symbol).clone());
// },
// // can't reach this state
// _ => panic!("Sym_Table_callsite: expecting Relocatable location, found {}",
// dest)
// }
// }
}
mangle_all(&mut sym_vec);
file_st.write("\t.data\n".as_bytes()).unwrap();
file_st
.write_fmt(format_args!(
"\t{}\n",
directive_globl("mu_sym_table".to_string())
))
.unwrap();
file_st.write_fmt(format_args!("mu_sym_table:\n")).unwrap();
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec.len()))
.unwrap();
for i in 0..sym_vec.len() {
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec[i].len()))
.unwrap();
file_st
.write_fmt(format_args!(".ascii \"{}\"\n", sym_vec[i]))
.unwrap();
file_st
.write_fmt(format_args!(".quad {}\n", sym_vec[i]))
.unwrap();
}
}
use std::collections::HashMap;
use compiler::backend::code_emission::emit_mu_types;
......@@ -4094,6 +4248,8 @@ pub fn emit_context_with_reloc(
dumper.finish();
emit_sym_table(vm);
debug!("---finish---");
}
......@@ -4142,27 +4298,43 @@ fn directive_comm(name: String, size: ByteSize, align: ByteSize) -> String {
}
/// returns symbol for a string (on linux, returns the same string)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")]
pub fn symbol(name: String) -> String {
name
}
/// returns symbol for a string (on macos, prefixes it with a understore (_))
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")]
pub fn symbol(name: String) -> String {
format!("_{}", name)
}
/// returns symbol for a string (on sel4-rumprun, returns the same string)
#[cfg(feature = "sel4-rumprun")]
pub fn symbol(name: String) -> String {
name
}
/// returns a position-indepdent symbol for a string (on linux, postfixes it with @GOTPCREL)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")]
pub fn pic_symbol(name: String) -> String {
format!("{}@GOTPCREL", name)
}
/// returns a position-indepdent symbol for a string (on macos, returns the same string)
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")]
pub fn pic_symbol(name: String) -> String {
symbol(name)
}
/// returns a position-indepdent symbol for a string (on sel4-rumprun, postfixes it with @GOTPCREL)
#[cfg(feature = "sel4-rumprun")]
pub fn pic_symbol(name: String) -> String {
format!("{}@GOTPCREL", name)
}
use compiler::machine_code::CompiledFunction;
/// rewrites the machine code of a function version for spilling.
......
......@@ -4729,7 +4729,11 @@ impl<'a> InstructionSelection {
&Constant::FuncRef(func_id) => {
// our code for linux has one more level of indirection
// so we need a load for linux
if cfg!(target_os = "macos") {
// sel4-rumprun is the same as Linux here
if cfg!(feature = "sel4-rumprun") {
let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_mov_r_mem(&tmp, &mem);
} else if cfg!(target_os = "macos") {
let mem = self.get_mem_for_funcref(func_id, vm);
self.backend.emit_lea_r64(&tmp, &mem);
} else if cfg!(target_os = "linux") {
......@@ -4957,7 +4961,33 @@ impl<'a> InstructionSelection {
unimplemented!()
} else {
// symbolic
if cfg!(target_os = "macos") {
if cfg!(feature = "sel4-rumprun") {
// Same as Linux:
// for a(%RIP), we need to load its address from a@GOTPCREL(%RIP)
// then load from the address.
// asm_backend will emit a@GOTPCREL(%RIP) for a(%RIP)
let got_loc = P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: pv.ty.clone(),
v: Value_::Memory(MemoryLocation::Symbolic {
base: Some(x86_64::RIP.clone()),
label: pv.name(),
is_global: true,
is_native: false
})
});
// mov (got_loc) -> actual_loc
let actual_loc = self.make_temporary(f_context, pv.ty.clone(), vm);
self.emit_move_value_to_value(&actual_loc, &got_loc);
self.make_memory_op_base_offset(
&actual_loc,
0,
pv.ty.get_referent_ty().unwrap(),
vm
)
} else if cfg!(target_os = "macos") {
P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: pv.ty.get_referent_ty().unwrap(),
......@@ -5823,7 +5853,8 @@ impl<'a> InstructionSelection {
};
self.current_constants.insert(id, val.clone());
self.current_constants_locs.insert(id, const_mem_val.clone());
self.current_constants_locs
.insert(id, const_mem_val.clone());
const_mem_val
}
......
......@@ -34,6 +34,8 @@ use num::integer::lcm;
#[cfg(feature = "aot")]
pub const AOT_EMIT_CONTEXT_FILE: &'static str = "context.S";
pub const AOT_EMIT_SYM_TABLE_FILE: &'static str = "mu_sym_table.S";
// type alias to make backend code more readable
pub type Reg<'a> = &'a P<Value>;
pub type Mem<'a> = &'a P<Value>;
......
......@@ -24,6 +24,8 @@ crate-type = ["rlib"]
[features]
default = []
use-sidemap = []
sel4-rumprun = []
sel4-rumprun-target-side = []
[build-dependencies]
gcc = "*"
......@@ -38,3 +40,4 @@ aligned_alloc = "*"
crossbeam = "*"
field-offset = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
#rodal = { path = "../../../rodal_test/rodal", version = ">= 0.0.5" }
......@@ -16,19 +16,49 @@ extern crate gcc;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")]
fn main() {
fn build_libgc() {
gcc::compile_library("libgc_clib_x64.a", &["src/heap/gc/clib_x64.c"]);
}
#[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")]
fn main() {
fn build_libgc() {
gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]);
}
// This is here to enable cross compiling from windows/x86_64 to linux/aarch64
#[cfg(target_os = "windows")]
#[cfg(target_arch = "x86_64")]
fn main() {
fn build_libgc() {
gcc::compile_library("libgc_clib_aarch64.a", &["src/heap/gc/clib_aarch64.S"]);
}
// Due to bugs, it is currently not possible to use conditional compilation \
// using features or target_..., so instead we use env variables
fn main() {
use std::env;
// For this variable: 1 means rumprun-sel4 and 0 means others
let mut gc_target = 0;
for (key, value) in env::vars() {
if key == "ZEBU_TARGET" {
if value == "x86_64-rumprun-netbsd" {
gc_target = 1;
break;
} else {
gc_target = 0;
break;
}
}
}
// for sel4-rumprun, do (if)
// otherwise, call the related target function
if gc_target == 1 {
use std::path::Path;
let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new().flag("-O3").flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("src/heap/gc/clib_x64_sel4_rumprun.c")
.compile("libgc_clib_x64.a");
} else { build_libgc(); }
}
// 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.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
void* malloc_zero(size_t size) {
void* ret = malloc(size);
memset(ret, 0, size);
return ret;
}
uintptr_t immmix_get_stack_ptr() {
uintptr_t rsp;
// get current rsp, rbp (this C func frame)
__asm__(
"mov %%rsp, %0 \n"
: "=rm" (rsp)
);
return rsp;
}
int get_registers_count() {
return 16;
}
uintptr_t* get_registers () {
uintptr_t rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
__asm__(
"mov %%rax, %0 \n"
"mov %%rbx, %1 \n"
"mov %%rcx, %2 \n"
"mov %%rdx, %3 \n"
"mov %%rbp, %4 \n"
"mov %%rsp, %5 \n"
"mov %%rsi, %5 \n"
"mov %%rdi, %6 \n"
"mov %%r8, %7 \n"
"mov %%r9, %8 \n"
"mov %%r10, %10\n"
"mov %%r11, %11\n"
"mov %%r12, %12\n"
"mov %%r13, %13\n"
"mov %%r14, %14\n"
"mov %%r15, %15\n"
: "=m" (rax),
"=m" (rbx),
"=m" (rcx),
"=m" (rdx),
"=m" (rbp),
"=m" (rsp),
"=m" (rsi),
"=m" (rdi),
"=m" (r8),
"=m" (r9),
"=m" (r10),
"=m" (r11),
"=m" (r12),
"=m" (r13),
"=m" (r14),
"=m" (r15)
:
:
);
uintptr_t* ret = (uintptr_t*) malloc(sizeof(uintptr_t) * 16);
ret[0] = rax;
ret[1] = rbx;
ret[2] = rcx;
ret[3] = rdx;
ret[4] = rbp;
ret[5] = rsp;
ret[6] = rsi;
ret[7] = rdi;
ret[8] = r8;
ret[9] = r9;
ret[10] = r10;
ret[11] = r11;
ret[12] = r12;
ret[13] = r13;
ret[14] = r14;
ret[15] = r15;
return ret;
}
// __thread uintptr_t low_water_mark;
int lwm_initialized = 0;
static pthread_key_t low_water_mark;
void set_low_water_mark () {
uintptr_t rsp;
if(lwm_initialized == 0){
lwm_initialized = 1;
int result = pthread_key_create(&low_water_mark, NULL);
if(result != 0){
printf("set_low_water_mark(): PThread key create failed with error code = %d\n", result);
assert(0);
}
}
// get current rsp, rbp (this C func frame)
__asm__(
"mov %%rsp, %0 \n"
: "=rm" (rsp)
);
int result = pthread_setspecific(low_water_mark, (const void *) rsp);
if(result != 0){
printf("set_low_water_mark(): PThread set specific failed with error code = %d\n", result);
assert(0);
}
}
uintptr_t get_low_water_mark() {
if(lwm_initialized == 0){
printf("get_low_water_mark(): PThread key MUST be initialized before first use!!\n");
}
void * result = pthread_getspecific(low_water_mark);
if(result == NULL){
printf("get_low_water_mark(): NO pthread key found for current thread!!\n");
assert(0);
}
return (uintptr_t) result;
}
......@@ -12,6 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod test_gc_harness;
pub mod test_gc_harness;
mod test_gcbench;
mod test_gc_linked_list;
......@@ -65,7 +65,7 @@ const FIXSIZE_REFx1_ENCODE : u64 = 0xb000000000000001u64;
#[test]
fn test_exhaust_alloc() {
pub fn test_exhaust_alloc() {
gc::gc_init(IMMIX_SPACE_SIZE, LO_SPACE_SIZE, 8, false);
let mut mutator = gc::new_mutator();
......
......@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate time;
use linkutils::*;
use ast::ir::MuName;
use runtime;
......@@ -20,6 +22,8 @@ use compiler::backend;
use std::path::PathBuf;
use std::process::Command;
use std::process::Stdio;
use std::process::Output;
/// links generated code for the given functions, static library of Zebu,
/// and a main function to produce an executable of the given name
......@@ -78,6 +82,63 @@ pub fn link_primordial(funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
)
}
/// links generated code for the given test's functions, static library of Zebu,
/// and a main function to produce an executable of the given name
pub fn link_test_primordial(funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
let emit_dir = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
// prepare a list of files that need to be compiled and linked together
let files: Vec<PathBuf> = {
use std::fs;
let mut ret = vec![];
// all interested mu funcs
for func in funcs {
ret.push(get_path_for_mu_func(func, vm));
}
// mu context
ret.push(get_path_for_mu_context(vm));
// copy primoridal entry
let source = get_path_under_zebu(runtime::PRIMORDIAL_ENTRY);
let dest = {
let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
ret.push("main_test.c");
ret
};
trace!("copying from {:?} to {:?}", source, dest);
match fs::copy(source.as_path(), dest.as_path()) {
Ok(_) => {}
Err(e) => panic!("failed to copy: {}", e)
}
// include the primordial C main
ret.push(dest);
// include mu static lib