...
 
Commits (102)
.gitignore
**/target/*
**/__pycache__/*
**/.cache/*
**/emit/*
Cargo.lock
*.pyc
*.o
*.dylib
**mu-client-pypy**
**RPySOM**
*.so
......@@ -7,49 +7,61 @@ stages:
before_script:
- export MU_ZEBU=$CI_PROJECT_DIR
- export ZEBU_BUILD=release
- export ZEBU_CARGO_ARG="--release"
- export CARGO_HOME=.cargo
- export CC=clang
- export LD_LIBRARY_PATH=$MU_ZEBU/target/$ZEBU_BUILD:$LD_LIBRARY_PATH
- export CXX=clang++
- export RUST_TEST_THREADS=1
- export LD_LIBRARY_PATH=$MU_ZEBU/target/$ZEBU_BUILD/deps/:$LD_LIBRARY_PATH
- export PYTHONPATH=mu-client-pypy
- source /home/gitlab-runner/ci/bin/activate
build:
stage: build
script:
- rustc --version
- time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test -j6 --release --no-run --color=always
- rustup run 1.35.0-x86_64-unknown-linux-gnu rustc --version
- rustup run 1.35.0-x86_64-unknown-linux-gnu cargo clean
- time rustup run 1.35.0-x86_64-unknown-linux-gnu cargo test -j6 $ZEBU_CARGO_ARG --no-run --color=always
artifacts:
paths:
- target/release/libmu.so
- target/release/libmu.a
- target/release/lib-*
- target/debug/deps/libmu.so
- target/debug/deps/libmu.a
- target/debug/deps/lib-*
- target/release/deps/libmu.so
- target/release/deps/libmu.a
- target/release/deps/lib-*
test:cargo:api:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_api 2> /dev/null
- rustup run 1.35.0-x86_64-unknown-linux-gnu cargo test test_api $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:ir:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_ir 2> /dev/null
- rustup run 1.35.0-x86_64-unknown-linux-gnu cargo test test_ir $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:compiler:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_compiler 2> /dev/null
- rustup run 1.35.0-x86_64-unknown-linux-gnu cargo test test_compiler $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:runtime:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_runtime 2> /dev/null
- rustup run 1.35.0-x86_64-unknown-linux-gnu cargo test test_runtime $ZEBU_CARGO_ARG 2> /dev/null
.build_muc: &build_muc |
if [ -d "tests/test_muc/mu-tool-compiler" ]; then rm -Rf tests/test_muc/mu-tool-compiler; fi
cd tests/test_muc
git clone https://gitlab.anu.edu.au/mu/mu-tool-compiler
cd mu-tool-compiler
export ANTLR_HOME=/home/gitlab-runner/antlr4/runtime/Cpp/run
mkdir lib
ln -s $MU_ZEBU/target/release/libmu.so lib/
cp -r $ANTLR_HOME/usr/local/lib/* $PWD/lib/
cp -r $MU_ZEBU/target/$ZEBU_BUILD/deps/* $PWD/lib/
export CC=clang
export CXX=clang++
make
cd ..
......@@ -153,6 +165,7 @@ testjit:som:
mubench:
stage: mubench
script:
- cp $MU_ZEBU/target/$ZEBU_BUILD/deps/libmu.so ./target/$ZEBU_BUILD/libmu.so
- deactivate
- git clone https://gitlab.anu.edu.au/mu/mu-perf-benchmarks.git
- git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git
......@@ -167,9 +180,9 @@ mubench:
- mkdir ci
- mubench local ./mu-perf-benchmarks/ci/*.yml --dump /home/gitlab-runner/results/$(git log -1 --pretty="%h_%at") --pipeline ""
- rsync -a /home/gitlab-runner/results/* squirrel:~/mu-impl-fast/angus
rustfmt:
stage: rustfmt
script:
- cargo-fmt -- --write-mode=diff --verbose -- src/lib.rs src/ast/src/lib.rs src/gc/src/lib.rs src/utils/src/lib.rs
- cargo-fmt +nightly -- --check --verbose -- src/lib.rs src/ast/src/lib.rs src/gc/src/lib.rs src/utils/src/lib.rs
allow_failure: true
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 14)
#set(triple x86_64-pc-linux-gnu)
#set(CMAKE_C_COMPILER gcc)
#set(CMAKE_C_COMPILER_TARGET ${triple})
#set(CMAKE_CXX_COMPILER g++)
#set(CMAKE_CXX_COMPILER_TARGET ${triple})
project(cmake_zebu_runtime_helpers)
add_library(runtime_c_x64 STATIC src/runtime/runtime_c_x64_sysv.c)
add_library(runtime_asm_x64 STATIC src/runtime/runtime_asm_x64_sysv.S)
set_target_properties(runtime_asm_x64 PROPERTIES LINKER_LANGUAGE C)
add_library(runtime_c_aarch64 STATIC src/runtime/runtime_c_aarch64_sysv.c)
add_library(runtime_asm_aarch64 STATIC src/runtime/runtime_asm_aarch64_sysv.S)
set_target_properties(runtime_asm_aarch64 PROPERTIES LINKER_LANGUAGE C)
# 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.
[package]
name = "mu"
version = "0.0.1"
authors = [ "Your name <you@example.com>" ]
build = "build.rs"
[lib]
crate-type = ["staticlib", "rlib", "dylib"]
doctest = false
[features]
default = ["aot"]
aot = []
jit = []
sel4-rumprun = []
sel4-rumprun-target-side = []
[build-dependencies]
gcc = "*"
#built = "0.1"
[dependencies]
mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"}
#mu_gc = {path = "src/gc"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "new", version = "^0.1.13" }
#rodal = { path = "./rodal", version = "*" }
libc="*"
field-offset = "*"
libloading = "*"
lazy_static = "*"
log = "*"
stderrlog = "*"
num = "*"
hprof = "*"
memmap = "*"
memsec = "0.1.9"
serde = "*"
serde_derive = "*"
time = "*"
maplit = "*"
docopt = "*"
petgraph = "*"
extprim = "*"
num-traits = "*"
#built = "0.1"
[target.aarch64-unknown-linux-gnu.dependencies]
mu_gc = { path = "src/gc", default-features = false}
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.aarch64-unknown-linux-gnu.build-dependencies]
built = "0.1"
[target.x86_64-unknown-linux-gnu.build-dependencies]
built = "0.1"
[target.x86_64-apple-darwin.build-dependencies]
built = "0.1"
# 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.
[package]
name = "mu"
version = "0.0.1"
authors = [ "Your name <you@example.com>", "Javad Amiri <javad.amiri@anu.edu.au>" ]
build = "build.rs"
[lib]
crate-type = ["staticlib", "rlib", "dylib"]
doctest = false
[features]
default = ["aot"]
aot = []
jit = []
realtime = ["mu_ast/realtime", "mu_utils/realtime", "mu_gc/realtime"]
[build-dependencies]
cc = "*"
built = "*"
[dependencies]
mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "master", version = "^0.4.0" }
libc="*"
field-offset = "*"
libloading = "*"
lazy_static = "*"
log = "*"
stderrlog = "*"
num = "*"
hprof = "*"
memmap = "*"
memsec = "*"
serde = { version = "*", features = ["derive"]}
bincode = "*"
serde_derive = "*"
time = "*"
maplit = "*"
docopt = "*"
petgraph = "*"
extprim = "*"
num-traits = "*"
built = "*"
mu_gc = { path = "src/gc"}
cfg-if = "*"
rand = "*"
rusty-asm = "*"
timer = "*"
chrono = "*"
......@@ -29,11 +29,16 @@ are not compliant to Mu spec.
## Building
You will need:
* rust version 1.19 (0ade33941 2017-07-17)
* rust version 1.28.0 or newer (2018-08-02)
* clang 4.0+
* cmake 3.8+ (we do not depend on cmake, but some Rust crates use it)
* internet connection (as Rust will download dependencies)
We have tested these specific versions:
* rust `stable-2018-11-08` and `nightly-2019-02-15`
* clang `6.0.0`
* cmake `3.10.2`
To build Zebu with release build,
```
cd path/to/zebu
......@@ -97,6 +102,7 @@ Running pytest (you will need Python 2.7 with pytest module)
export SPAWN_PROC=1
python2 -m pytest test*.py -v
```
* We only tested python `2.7.15-rc1` successfully.
## Using Zebu for your language implementation
......
......@@ -12,22 +12,20 @@
// 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;
extern crate cc;
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")]
fn main() {
gcc::Build::new()
cc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_c_x64_sysv.c")
.compile("libruntime_c.a");
gcc::Build::new()
cc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_asm_x64_sysv.S")
......@@ -36,17 +34,16 @@ fn main() {
built();
}
#[cfg(not(feature = "sel4-rumprun-target-side"))]
#[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")]
fn main() {
gcc::Build::new()
cc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_c_aarch64_sysv.c")
.compile("libruntime_c.a");
gcc::Build::new()
cc::Build::new()
.flag("-O3")
.flag("-c")
.file("src/runtime/runtime_asm_aarch64_sysv.S")
......@@ -55,34 +52,7 @@ 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::Build::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::Build::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::Build::new()
.flag("-O3")
.flag("-c")
.compiler(Path::new(compiler_name.as_str()))
.file("zebu_c_helpers.c")
.compile("libzebu_c_helpers.a");
built::write_built_file()
.expect("Failed to acquire build-time information");
}
#!/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
......@@ -18,7 +18,7 @@ export MU_LOG_LEVEL=none
export RUST_TEST_THREADS=1
export RUST_BACKTRACE=0
export PYTHONPATH="$MU_ZEBU/tests/test_jit/mu-client-pypy/:$MU_ZEBU/tests/test_jit/RPySOM/src"
export LD_LIBRARY_PATH="$MU_ZEBU/target/$ZEBU_BUILD:$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit/emit/:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="$MU_ZEBU/target/$ZEBU_BUILD/deps/:$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit/emit/:$LD_LIBRARY_PATH"
export ZEBU_BUILD=release
rm -rf $MU_ZEBU/emit
......
#!/bin/sh
export MU_ZEBU=$PWD
export ZEBU_BUILD=debug
export CARGO_HOME=~/.cargo
export CC=clang
export CXX=clang++
export RUST_TEST_THREADS=1
export RUST_BACKTRACE=1
export MU_LOG_LEVEL=trace
export LD_LIBRARY_PATH=$MU_ZEBU/target/$ZEBU_BUILD/deps/:$LD_LIBRARY_PATH
max_width = 80
wrap_comments = true
trailing_comma = "Never"
......@@ -15,16 +15,22 @@
[package]
name = "mu_ast"
version = "0.0.1"
authors = ["qinsoon <qinsoon@gmail.com>"]
authors = ["qinsoon <qinsoon@gmail.com>", "Javad Amiri <javad.amiri@anu.edu.au>"]
[features]
realtime = []
[lib]
crate-type = ["rlib"]
[build-dependencies]
log = "*"
[dependencies]
mu_utils = {path = "../utils"}
lazy_static = "*"
lazy_static = "0.2.11"
log = "*"
simple_logger = "*"
regex = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "new", version = "^0.1.13" }
#rodal = { path = "../../rodal", version = "*" }
regex = "0.2.2"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "master", version = "^0.4.0" }
libc = "*"
\ No newline at end of file
// Copyright 2019 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.
fn main() {
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
// Copyright 2019 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.
// Copyright 2019 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.
extern crate libc;
pub type SysThreadID = libc::pthread_t;
pub type SysThreadAttr = libc::pthread_attr_t;
pub type SysPriority = libc::c_int;
pub type SysTime = libc::timespec;
pub type SysAffinityMask = libc::cpu_set_t;
pub type SysAffinitySize = libc::size_t;
// Copyright 2019 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.
......@@ -14,7 +14,8 @@
//! # MuIR AST crate
//!
//! This crate provides data structures to allow construct MuIR in Rust code, including:
//! This crate provides data structures to allow construct MuIR in Rust code,
//! including:
//!
//! * types
//! * ir
......@@ -46,15 +47,19 @@ macro_rules! impl_mu_entity {
($entity: ty) => {
impl MuEntity for $entity {
#[inline(always)]
fn id(&self) -> MuID {self.hdr.id()}
fn id(&self) -> MuID {
self.hdr.id()
}
#[inline(always)]
fn name(&self) -> MuName {self.hdr.name()}
fn name(&self) -> MuName {
self.hdr.name()
}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
let ref_ty: &$entity = self;
ref_ty as &MuEntity
}
}
}
};
}
/// select between two values based on condition
......@@ -65,12 +70,18 @@ macro_rules! select_value {
} else {
$res2
}
}
};
}
#[macro_use]
pub mod ir;
pub mod inst;
pub mod types;
pub mod ptr;
pub mod op;
pub mod ptr;
pub mod types;
#[cfg(feature = "realtime")]
pub mod ir_rt;
#[cfg(all(feature = "realtime", target_os = "linux"))]
pub mod ir_rt_posix;
......@@ -92,7 +92,8 @@ impl fmt::Display for CmpOp {
}
impl CmpOp {
/// returns the CmpOp X for CmpOp Y, such that (a Y b) is equivalent to (b X a)
/// returns the CmpOp X for CmpOp Y, such that (a Y b) is equivalent to (b X
/// a)
pub fn swap_operands(self) -> CmpOp {
use op::CmpOp::*;
match self {
......@@ -120,7 +121,8 @@ impl CmpOp {
}
}
/// returns the CmpOp X for CmpOp Y, such that (a Y b) is equivalent to NOT(a X b)
/// returns the CmpOp X for CmpOp Y, such that (a Y b) is equivalent to
/// NOT(a X b)
pub fn invert(self) -> CmpOp {
use op::CmpOp::*;
match self {
......
......@@ -14,7 +14,8 @@
use std::sync::Arc;
/// P<T> is alias type for sharable Mu AST components (such as Value, MuFuncSig, MuType, etc)
/// P<T> is alias type for sharable Mu AST components (such as Value, MuFuncSig,
/// MuType, etc)
// This design is similar to P<T> in rustc compiler.
// However, instead of using Box<T>, we use Arc<T> to encourage sharing
pub type P<T> = Arc<T>;
......
This diff is collapsed.
This diff is collapsed.
use ast::ir::*;
use ast::ptr::*;
use ast::types::*;
use compiler::backend::RegGroup;
use compiler::backend::x86_64;
use compiler::backend::BackendType;
use compiler::backend::RegGroup;
use utils::ByteSize;
use vm::VM;
......@@ -21,8 +21,8 @@ pub mod mu {
pub mod swapstack {
pub use super::c::compute_arguments;
pub use super::c::compute_stack_args;
pub use super::c::compute_arguments as compute_return_values;
pub use super::c::compute_stack_args;
pub use super::c::compute_stack_args as compute_stack_retvals;
}
......@@ -55,10 +55,12 @@ pub mod c {
ret.push(CallConvResult::STACK);
}
} else if arg_reg_group == RegGroup::GPREX {
// need two regsiters for this, otherwise, we need to pass on stack
// need two regsiters for this, otherwise, we need to pass on
// stack
if gpr_arg_count + 1 < x86_64::ARGUMENT_GPRS.len() {
let arg_gpr1 = x86_64::ARGUMENT_GPRS[gpr_arg_count].clone();
let arg_gpr2 = x86_64::ARGUMENT_GPRS[gpr_arg_count + 1].clone();
let arg_gpr2 =
x86_64::ARGUMENT_GPRS[gpr_arg_count + 1].clone();
ret.push(CallConvResult::GPREX(arg_gpr1, arg_gpr2));
gpr_arg_count += 2;
......@@ -83,7 +85,10 @@ pub mod c {
ret
}
pub fn compute_stack_args(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, Vec<ByteSize>) {
pub fn compute_stack_args(
tys: &Vec<P<MuType>>,
vm: &VM
) -> (ByteSize, Vec<ByteSize>) {
let callconv = compute_arguments(tys);
let mut stack_arg_tys = vec![];
......@@ -124,7 +129,8 @@ pub mod c {
} else if RegGroup::get_from_ty(ty) == RegGroup::GPREX {
if gpr_ret_count + 1 < x86_64::RETURN_GPRS.len() {
let ret_gpr1 = x86_64::RETURN_GPRS[gpr_ret_count].clone();
let ret_gpr2 = x86_64::RETURN_GPRS[gpr_ret_count + 1].clone();
let ret_gpr2 =
x86_64::RETURN_GPRS[gpr_ret_count + 1].clone();
ret.push(CallConvResult::GPREX(ret_gpr1, ret_gpr2));
} else {
......@@ -149,14 +155,19 @@ pub mod c {
ret
}
pub fn compute_stack_retvals(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, Vec<ByteSize>) {
pub fn compute_stack_retvals(
tys: &Vec<P<MuType>>,
vm: &VM
) -> (ByteSize, Vec<ByteSize>) {
let callconv = compute_return_values(tys);
let mut stack_ret_val_tys = vec![];
for i in 0..callconv.len() {
let ref cc = callconv[i];
match cc {
&CallConvResult::STACK => stack_ret_val_tys.push(tys[i].clone()),
&CallConvResult::STACK => {
stack_ret_val_tys.push(tys[i].clone())
}
_ => {}
}
}
......@@ -164,8 +175,8 @@ pub mod c {
compute_stack_locations(&stack_ret_val_tys, vm)
}
/// computes the area on the stack for a list of types that need to put on stack,
/// returns a tuple of (size, offset for each values on stack)
/// computes the area on the stack for a list of types that need to put on
/// stack, returns a tuple of (size, offset for each values on stack)
pub fn compute_stack_locations(
stack_val_tys: &Vec<P<MuType>>,
vm: &VM
......@@ -176,7 +187,8 @@ pub mod c {
// "The end of the input argument area shall be aligned on a 16
// (32, if __m256 is passed on stack) byte boundary." - x86 ABI
// if we need to special align the args, we do it now
// (then the args will be put to stack following their regular alignment)
// (then the args will be put to stack following their regular
// alignment)
let mut stack_arg_size_with_padding = stack_arg_size;
if stack_arg_size % 16 == 0 {
......
......@@ -12,24 +12,28 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use ast::ptr::P;
use ast::ir::*;
use ast::ptr::P;
use runtime::ValueLocation;
use compiler::backend::{Mem, Reg};
use compiler::machine_code::MachineCode;
use compiler::backend::{Reg, Mem};
/// CodeGenerator provides an interface to emit x86_64 code for instruction selection.
/// This allows us to implement the other parts of the compiler (mostly instruction selection)
/// without assuming code generator. Currently there is only an assembly backend
/// that implements this interface for ahead-of-time compilation. We plan to add
/// a binary backend for just-in-time compilation.
/// CodeGenerator provides an interface to emit x86_64 code for instruction
/// selection. This allows us to implement the other parts of the compiler
/// (mostly instruction selection) without assuming code generator. Currently
/// there is only an assembly backend that implements this interface for
/// ahead-of-time compilation. We plan to add a binary backend for just-in-time
/// compilation.
pub trait CodeGenerator {
/// starts code for a function
fn start_code(&mut self, func_name: MuName, entry: MuName) -> ValueLocation;
fn start_code(&mut self, func_name: MuName, entry: MuName)
-> ValueLocation;
/// finishes code for a function
fn finish_code(&mut self, func_name: MuName)
-> (Box<MachineCode + Sync + Send>, ValueLocation);
fn finish_code(
&mut self,
func_name: MuName
) -> (Box<MachineCode + Sync + Send>, ValueLocation);
/// starts a sequence of linear code (no branch)
fn start_code_sequence(&mut self);
......@@ -43,7 +47,8 @@ pub trait CodeGenerator {
fn start_block(&mut self, block_name: MuName);
/// starts an exceptional block, and returns its code address
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation;
/// finishes a block (must have called start_block() or start_excpetion_block() first)
/// finishes a block (must have called start_block() or
/// start_excpetion_block() first)
fn end_block(&mut self, block_name: MuName);
// adds CFI info
......@@ -81,8 +86,8 @@ pub trait CodeGenerator {
fn emit_mov_r_mem(&mut self, dest: Reg, src: Mem); // load
fn emit_mov_r_r(&mut self, dest: Reg, src: Reg);
fn emit_mov_mem_r(&mut self, dest: Mem, src: Reg); // store
// we can infer imm length from Reg, but cannot from Mem
// because mem may only have type as ADDRESS_TYPE
// we can infer imm length from Reg, but cannot from Mem
// because mem may only have type as ADDRESS_TYPE
fn emit_mov_mem_imm(&mut self, dest: Mem, src: i32, oplen: usize); // store
fn emit_mov_mem_r_callee_saved(&mut self, dest: Mem, src: Reg); // store callee saved register
......
This diff is collapsed.
......@@ -14,16 +14,16 @@
#![allow(dead_code)]
use compiler::CompilerPass;
use ast::ir::*;
use vm::VM;
use compiler::backend::emit_code;
use compiler::CompilerPass;
use std::any::Any;
use vm::VM;
use std::path;
use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path;
pub use vm::uir_output::create_emit_directory;
/// should emit machien code dot graph?
pub const EMIT_MC_DOT: bool = true;
......@@ -67,18 +67,15 @@ fn create_emit_file(name: String, vm: &VM) -> File {
file_path.push(name);
match File::create(file_path.as_path()) {
Err(why) => {
panic!(
"couldn't create emit file {}: {}",
file_path.to_str().unwrap(),
why
)
}
Err(why) => panic!(
"couldn't create emit file {}: {}",
file_path.to_str().unwrap(),
why
),
Ok(file) => file
}
}
fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
let func_name = func.name();
......@@ -118,7 +115,8 @@ fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
"{} [label = \"{}:\\l\\l",
id(block_name.clone()),
block_name
).unwrap();
)
.unwrap();
for inst in mc.get_block_range(&block_name).unwrap() {
file.write_all(&mc.emit_inst(inst)).unwrap();
......@@ -132,7 +130,8 @@ fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
for block_name in blocks.iter() {
let end_inst = mc.get_block_range(block_name).unwrap().end;
for succ in mc.get_succs(mc.get_last_inst(end_inst).unwrap())
for succ in mc
.get_succs(mc.get_last_inst(end_inst).unwrap())
.into_iter()
{
match mc.get_block_for_inst(*succ) {
......@@ -142,7 +141,10 @@ fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
writeln!(file, "{} -> {};", source_id, target_id).unwrap();
}
None => {
panic!("cannot find succesor {} for block {}", succ, block_name);
panic!(
"cannot find succesor {} for block {}",
succ, block_name
);
}
}
}
......
......@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use compiler::CompilerPass;
use ast::ir::*;
use vm::VM;
use compiler::machine_code::*;
use compiler::CompilerPass;
use utils::LinkedHashMap;
use utils::LinkedHashSet;
use utils::LinkedMultiMap;
use utils::LinkedRepeatableMultiMap;
use utils::Tree;
use vm::VM;
use std::any::Any;
......@@ -65,7 +65,8 @@ impl CompilerPass for MCLoopAnalysis {
trace!("---merged loops---");
trace!("{:?}", merged_loops);
let loop_nest_tree = compute_loop_nest_tree(prologue.clone(), &merged_loops);
let loop_nest_tree =
compute_loop_nest_tree(prologue.clone(), &merged_loops);
trace!("---loop-nest tree---");
trace!("{:?}", loop_nest_tree);
......@@ -100,7 +101,10 @@ impl MCLoopAnalysis {
}
}
fn compute_dominators(func: &CompiledFunction, cfg: &MachineCFG) -> LinkedMultiMap<MuName, MuName> {
fn compute_dominators(
func: &CompiledFunction,
cfg: &MachineCFG
) -> LinkedMultiMap<MuName, MuName> {
let mc = func.mc();
// D[s0] = s0
// D[n] = {n} \/ ( /\ D[p] for all p in pred[n])
......@@ -161,9 +165,11 @@ fn compute_dominators(func: &CompiledFunction, cfg: &MachineCFG) -> LinkedMultiM
dominators
}
fn compute_immediate_dominators(dominators: &LinkedMultiMap<MuName, MuName>)
-> LinkedHashMap<MuName, MuName> {
let mut immediate_doms: LinkedHashMap<MuName, MuName> = LinkedHashMap::new();
fn compute_immediate_dominators(
dominators: &LinkedMultiMap<MuName, MuName>
) -> LinkedHashMap<MuName, MuName> {
let mut immediate_doms: LinkedHashMap<MuName, MuName> =
LinkedHashMap::new();
for (n, doms) in dominators.iter() {
trace_if!(TRACE_LOOPANALYSIS, "compute idom(n={:?})", n);
......@@ -196,7 +202,10 @@ fn compute_immediate_dominators(dominators: &LinkedMultiMap<MuName, MuName>)
candidate_is_idom = false;
}
} else {
trace_if!(TRACE_LOOPANALYSIS, " skip, as d==candidate or d==n");
trace_if!(
TRACE_LOOPANALYSIS,
" skip, as d==candidate or d==n"
);
}
}
......@@ -222,13 +231,20 @@ fn compute_immediate_dominators(dominators: &LinkedMultiMap<MuName, MuName>)
}
/// whether a dominates b (i.e. b is one of the dominators of a
fn is_dom(a: &MuName, b: &MuName, dominators: &LinkedMultiMap<MuName, MuName>) -> bool {
fn is_dom(
a: &MuName,
b: &MuName,
dominators: &LinkedMultiMap<MuName, MuName>
) -> bool {
dominators.contains_key_val(b, a)
}
pub type MCDomTree = Tree<MuName>;
fn compute_domtree(entry: MuName, idoms: &LinkedHashMap<MuName, MuName>) -> MCDomTree {
fn compute_domtree(
entry: MuName,
idoms: &LinkedHashMap<MuName, MuName>
) -> MCDomTree {
let mut domtree = MCDomTree::new(entry);
// for every other node, there is an edge from
for (x, idom_x) in idoms.iter() {
......@@ -325,8 +341,9 @@ struct MCMergedLoop {
blocks: LinkedHashSet<MuName>
}
fn compute_merged_loop(loops: &LinkedRepeatableMultiMap<MuName, MCNaturalLoop>)
-> LinkedHashMap<MuName, MCMergedLoop> {
fn compute_merged_loop(
loops: &LinkedRepeatableMultiMap<MuName, MCNaturalLoop>
) -> LinkedHashMap<MuName, MCMergedLoop> {
let mut merged_loops = LinkedHashMap::new();
for (header, natural_loops) in loops.iter() {
let mut merged_loop = MCMergedLoop {
......@@ -356,15 +373,19 @@ fn compute_loop_nest_tree(
trace_if!(TRACE_LOOPANALYSIS, "check loop: {}", header);
// if header appears in other merged loop, then it is a nested loop
// we need to find the most recent outer loop (determined by loop size - number of blocks)
// we need to find the most recent outer loop (determined by loop size -
// number of blocks)
let mut outer_loop_candidate = None;
let mut outer_loop_size = {
use std::usize;
usize::MAX
};
for (outer_header, outer_merged_loop) in merged_loops.iter() {
// nested loop - add an edge from outer loop header to this loop header
if header != outer_header && outer_merged_loop.blocks.contains(header) {
// nested loop - add an edge from outer loop header to this loop
// header
if header != outer_header
&& outer_merged_loop.blocks.contains(header)
{
let loop_size = outer_merged_loop.blocks.len();
if loop_size < outer_loop_size {
outer_loop_candidate = Some(outer_header);
......@@ -375,7 +396,8 @@ fn compute_loop_nest_tree(
if let Some(outer_loop) = outer_loop_candidate {
loop_nest_tree.insert(outer_loop.clone(), header.clone());
} else {
// this header is not a nested loop - add an edge from root to this loop header
// this header is not a nested loop - add an edge from root to this
// loop header
loop_nest_tree.insert(root.clone(), header.clone());
}
}
......@@ -403,8 +425,8 @@ fn record_depth(
// insert the header with the deapth
trace_if!(TRACE_LOOPANALYSIS, "Header {} = Depth {}", node, depth);
map.insert(node.clone(), depth);
// also find all the blocks that belong to the header and are not inner loop header
// and insert them with the same depth
// also find all the blocks that belong to the header and are not inner loop
// header and insert them with the same depth
if let Some(merged_loop) = merged_loops.get(node) {
for b in merged_loop.blocks.iter() {
if !merged_loops.contains_key(b) {
......
This diff is collapsed.
This diff is collapsed.
......@@ -14,20 +14,19 @@
extern crate petgraph;
mod liveness;
mod coloring;
mod liveness;
use compiler::backend::reg_alloc::graph_coloring::liveness::build_interference_graph_chaitin_briggs
as build_inteference_graph;
use compiler::backend::reg_alloc::graph_coloring::coloring::GraphColoring;
use compiler::backend::reg_alloc::graph_coloring::liveness::build_interference_graph_chaitin_briggs as build_inteference_graph;
use ast::ir::*;
use vm::VM;
use compiler::CompilerPass;
use compiler::backend::is_callee_saved;
use compiler::backend::init_machine_regs_for_func;
use compiler::backend::is_callee_saved;
use compiler::backend::reg_alloc::validate;
use compiler::CompilerPass;
use std::any::Any;
use vm::VM;
pub struct RegisterAllocation {
name: &'static str
......@@ -59,7 +58,8 @@ impl RegisterAllocation {
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
// initialize machine registers for the function context (we are gonna use them)
// initialize machine registers for the function context (we are gonna
// use them)
init_machine_regs_for_func(&mut func.context);
// do graph coloring
......@@ -73,7 +73,11 @@ impl RegisterAllocation {
// we use this to validate spilling correctness
let spill_scratch_temps = coloring.get_spill_scratch_temps();
validate::validate_regalloc(&coloring.cf, reg_assignment, spill_scratch_temps);
validate::validate_regalloc(
&coloring.cf,
reg_assignment,
spill_scratch_temps
);
}
// use the result to replace temporaries with assigned regs
......@@ -84,11 +88,13 @@ impl RegisterAllocation {
coloring.cf.temps.insert(temp, machine_reg);
}
// find out what callee saved registers are used, so we can delete unnecessary savings.
// Currently I am only deleting those unnecessary push/pops of callee saved regs, but
// I am not deleting the frame slots for them (so the frame size is still larger than
// it needs to be).
// FIXME: should fix offsets of frame slots, and patch the code. See Issue #47
// find out what callee saved registers are used, so we can delete
// unnecessary savings. Currently I am only deleting those
// unnecessary push/pops of callee saved regs, but
// I am not deleting the frame slots for them (so the frame size is
// still larger than it needs to be).
// FIXME: should fix offsets of frame slots, and patch the code. See
// Issue #47
{
// all the used callee saved registers
let used_callee_saved: Vec<MuID> = {
......
......@@ -14,9 +14,9 @@
//! This module is for register allocation.
//! We should encapsulate the details of register allocation within this module,
//! and expose RegisterAllocation (which implements CompilerPass) to the compiler.
//! Outside of this module, the compiler should not assume a specific register
//! allocation algorithm.
//! and expose RegisterAllocation (which implements CompilerPass) to the
//! compiler. Outside of this module, the compiler should not assume a specific
//! register allocation algorithm.
//! We currently implemented graph coloring. We may have other algorithms in
//! the future.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use utils::LOG_POINTER_SIZE;
use utils::Address;
use common::bitmap::Bitmap;
use utils::Address;
use utils::LOG_POINTER_SIZE;
#[derive(Clone)]
pub struct AddressBitmap {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.