WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit c075b1e4 authored by Javad Ebrahimian Amiri's avatar Javad Ebrahimian Amiri
Browse files

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

parent 6e1f7e47
......@@ -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