1st draft of merging with develop branch: Hopefully the first to pass CI tests

parent 6e1f7e47
Pipeline #824 failed with stages
in 31 minutes and 53 seconds
......@@ -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,28 @@ fn main() {
built();
}
#[cfg(not(feature = "sel4-rumprun-target-side"))]
fn built() {
built::write_built_file().expect("Failed to acquire build-time information");
}
\ No newline at end of file
}
#[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");
}
......@@ -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" }
......@@ -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;
......@@ -3723,6 +3724,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;
......@@ -3732,6 +3734,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;
......@@ -3746,6 +3749,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;
......@@ -3832,6 +3843,129 @@ 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)
// }
// }
}
// **************************************************
// Generate the following code:
// .data
// .globl mu_sym_table
// mu_sym_table:
// for each symbol {
// .quad "symbol_name".length()
// __symbol_name:
// .ascii "symbol_name"
// .quad 0
// }
// *************************************************
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;
......@@ -4024,7 +4158,9 @@ pub fn emit_context_with_reloc(
dumper.dump("HYBRID_TAG_MAP", hybrid_tag_map);
dumper.finish();
emit_sym_table(vm);
debug!("---finish---");
}
......@@ -4073,27 +4209,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.
......
......@@ -4663,7 +4663,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") {
......@@ -4891,7 +4895,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(),
......
......@@ -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>;
......
......@@ -40,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" }
This diff is collapsed.
......@@ -102,13 +102,22 @@ fn exec_cmd_nocheck(mut cmd: Command) -> Output {
}
/// returns a name for dynamic library
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "macos")]
pub fn get_dylib_name(name: &'static str) -> String {
format!("lib{}.dylib", name)
}
/// returns a name for dynamic library
#[cfg(not(feature = "sel4-rumprun"))]
#[cfg(target_os = "linux")]
pub fn get_dylib_name(name: &'static str) -> String {
format!("lib{}.so", name)
}
/// returns a name for dynamic library
/// Must not be used for sel4-rumprun
#[cfg(feature = "sel4-rumprun")]
pub fn get_dylib_name(name: &'static str) -> String {
format!("lib{}.UNKNOWN", name)
}
\ No newline at end of file
......@@ -16,16 +16,23 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <assert.h>
extern void* vm;
extern void mu_main(char*, int, char**);
extern void* RODAL_END;
extern void mu_main(void*, void*, int, char**);
extern void rodal_init_deallocate(void);
extern void rodal_free(void*);
extern void* rodal_realloc(void*, size_t);
extern int32_t c_check_result();
extern uint32_t mu_retval;
int main(int argc, char** argv) {
char* serialize_vm = (char*) &vm;
mu_main(serialize_vm, argc, argv);
assert(c_check_result() == 0);
rodal_init_deallocate();
mu_main(&RODAL_END, &vm, argc, argv);
assert(mu_retval == 0);
return (int)mu_retval;
}
void free(void* ptr) { return rodal_free(ptr); };
void* realloc(void* ptr, size_t s) { return rodal_realloc(ptr, s); };
......@@ -27,6 +27,8 @@ use std::ffi::CStr;
use std::sync::Arc;
use rodal;
use libc::c_void;
/// memory management: allocation, reclamation
/// (the actual code is in src/gc, which gets re-exported in mm module)
pub mod mm;
......@@ -74,6 +76,7 @@ pub fn get_function_info(function_addr: Address) -> (CName, Address) {
/// returns address for a given symbol, e.g. function name
#[cfg(not(feature = "sel4-rumprun-target-side"))]
pub fn resolve_symbol(symbol: MuName) -> Address {
use std::ptr;
......@@ -95,6 +98,48 @@ pub fn resolve_symbol(symbol: MuName) -> Address {
Address::from_ptr(ret)
}
use std::os::raw::c_char;
//use std::os::raw::c_void;
// This function is specific to sel4-rumprun platform
// it replaces the resolve_symbol function provided by Linux and Mac
// all other platforms (except sel4-rumprun) already provide this function
#[cfg(feature = "sel4-rumprun-target-side")]
#[link(name="zebu_c_helpers")]
extern "C" {
fn c_resolve_symbol(symbol: *const c_char) -> *const c_void;
}
// Although it is possible to directly \
// compile, call and check results of Mu test functions \
// in Linux and Mac, but in-order to unify testing styles \
// I will use this C function to check the correctness of results
// *************************************************
// #[link(name="runtime")]
// extern "C" {
// fn c_check_result() -> c_long;
// }
//
// pub fn check_result() -> c_long {
// let result = unsafe { c_check_result() };
// result
// }
// *************************************************
// This code has been moved to thread.rs \
// due to the linkage with libruntime.a happenning there once
// TODO
// resolve symbol is different from the one used for Linux and Mac
#[cfg(feature = "sel4-rumprun-target-side")]
pub fn resolve_symbol(symbol: String) -> Address {
debug!("Going to resolve Symbol -{}-", symbol);
let ret = unsafe { c_resolve_symbol(CString::new(symbol.clone()).unwrap().as_ptr()) };
if ret.is_null() {
panic!("failed to resolve symbol: {}", symbol.clone());
}
debug!("Symbol -{}- resolved", symbol);
Address::from_ptr(ret)
}
/// ValueLocation represents the runtime location for a value.
/// The purpose of this data structure is to refer to a location in a unified way
/// for both compile time (usually talking about symbols) and run time (talking about addresses)
......@@ -191,6 +236,10 @@ impl ValueLocation {
/// 3. returns the return value set by SetRetval
pub const PRIMORDIAL_ENTRY: &'static str = "src/runtime/main.c";
/// a C wrapper as main function for executable test boot images"
/// in addition to normal main.c, it checks the returned results of tests
pub const TEST_PRIMORDIAL_ENTRY : &'static str = "src/runtime/main_test.c";
/// starts trace level logging, this function will be called from C
#[no_mangle]
pub extern "C" fn mu_trace_level_log() {
......
# 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 "asm_common_x64_sel4_rumprun.S.inc"
# swap_stack_to(new_sp: Address, entry: Address, old_sp_loc: Address)
# %rdi %rsi %rdx
begin_func swap_to_mu_stack
# -- on old stack --
# C calling convention
pushq %rbp
movq %rsp, %rbp
# other callee-saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save sp to %rbx
movq %rsp, 0(%rdx)
# switch to new stack
movq %rdi, %rsp
# save entry function in %rax
movq %rsi, %rax
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
popq %r9
popq %r8
popq %rcx
popq %rdx
popq %rsi
popq %rdi
movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0
add $64, %rsp
# at this point new stack is clean (no intermediate values)
movq %rsp, %rbp
# push an empty pointer to stack, if entry fucntion tries to return, it causes a segfault
pushq $0
# push entry function and start it
pushq %rax
ret
end_func swap_to_mu_stack
# _swap_back_to_native_stack(sp_loc: Address)
# %rdi
begin_func muentry_swap_back_to_native_stack
movq 0(%rdi), %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbx
popq %rbp
ret
end_func muentry_swap_back_to_native_stack
# _get_current_frame_bp() -> Address
begin_func get_current_frame_bp
movq %rbp, %rax
ret
end_func get_current_frame_bp
# muentry_throw_exception(obj: Address)
# %rdi
begin_func muentry_throw_exception
# save all callee-saved
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# %rsp points to %rbx, pass this as 2nd argument
movq %rbp, %rsi
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore
movq 0(%rsi), %rbp
movq -8(%rsi),%rbx
movq -16(%rsi),%r12
movq -24(%rsi),%r13
movq -32(%rsi),%r14
movq -40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
end_func exception_restore
\ No newline at end of file
......@@ -75,12 +75,10 @@ void* resolve_symbol(const char* sym) {
return dlsym(RTLD_DEFAULT, sym);
}
int32_t mu_retval;
void muentry_set_retval(int32_t x) {
mu_retval = x;
}
int32_t c_check_result() {
return mu_retval;
}
\ No newline at end of file
}
char * alloc_mem(size_t size){
return (char *) malloc(size);
}
......@@ -32,6 +32,14 @@ void muentry_set_retval(uint32_t x) {
mu_retval = x;
}
int32_t c_check_result() {
return mu_retval;
}
char * alloc_mem(size_t size){
return (char *) malloc(size);
}
void set_thread_local(void* thread) {
// printf("Thread%p: setting mu_tls to %p\n", (void*) pthread_self(), thread);
mu_tls = thread;
......@@ -46,17 +54,3 @@ void* resolve_symbol(const char* sym) {
// printf("%s\n", sym);
return dlsym(RTLD_DEFAULT, sym);
}
int32_t mu_retval;
void muentry_set_retval(int32_t x) {
mu_retval = x;
}
int32_t c_check_result() {
return mu_retval;
}
char * alloc_mem(size_t size){
return (char *) malloc(size);
}
......@@ -70,4 +70,8 @@ int32_t muentry_get_retval() {
int32_t c_check_result() {
return mu_retval;
}
\ No newline at end of file
}
char * alloc_mem(size_t size){
return (char *) malloc(size);
}
......@@ -34,7 +34,11 @@ use std::sync::Arc;
use std::fmt;
/// a 4mb Mu stack
#[cfg(not(feature = "sel4-rumprun"))]
pub const STACK_SIZE: ByteSize = (4 << 20); // 4mb
/// a .25mb Mu stack for sel4-rumprun
#[cfg(feature = "sel4-rumprun")]
pub const STACK_SIZE : ByteSize = (4 << 16); // 256kb
/// operating system page size
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
......@@ -356,6 +360,9 @@ impl fmt::Display for MuThread {
}
}
use std::os::raw::c_int;
#[cfg(not(feature = "sel4-rumprun-target-side"))]