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

Commit fe287e80 authored by Isaac Gariano's avatar Isaac Gariano

Merge branch 'master' into 'aarch64'

Merging master to aarch64

See merge request !9
parents 0ec81e6a 99a65c69
......@@ -11,8 +11,10 @@ Cargo.lock
*.pyc
*.o
*.dylib
mu-client-pypy
**mu-client-pypy**
**RPySOM**
.gitignore
cmake-build-debug/*
Notes/*
CMakeLists.txt
*.iml
# This file is a template, and might need editing before it works on your project.
# Unofficial language image. Look for the different tagged releases at:
# https://hub.docker.com/r/scorpil/rust/tags/
image: "qinsoon/ubuntu-zebu-test:lastest"
image: "qinsoon/ubuntu-zebu-test:latest"
# Optional: Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
......@@ -18,36 +18,60 @@ image: "qinsoon/ubuntu-zebu-test:lastest"
#- apt-get install -yqq --no-install-recommends build-essential
# Use cargo to test the project
cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
# cache:
# key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
# paths:
# - .cargo/registry/cache
# - .cargo/registry/index
# - target
# - Cargo.lock
stages:
- build
- test
build_vm:
stage: build
script:
- rustc --version
- time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo build --release
build_test:
stage: build
script:
- rustc --version
- time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test --release --no-run
artifacts:
paths:
- .cargo/registry/cache
- .cargo/registry/index
- target
- Cargo.lock
- target/release/libmu.so
- target/release/libmu.a
before_script:
- time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test --no-run
- export PATH=$PATH:/root/.cargo/bin
- export MU_ZEBU=$CI_PROJECT_DIR
- export ZEBU_BUILD=release
- export CARGO_HOME=.cargo
- export CC=clang
test:cargo:api:
stage: test
script:
- CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_api 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_api 2> /dev/null
test:cargo:ir:
stage: test
script:
- CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_ir 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_ir 2> /dev/null
test:cargo:compiler:
stage: test
script:
- CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_compiler 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_compiler 2> /dev/null
test:cargo:runtime:
stage: test
script:
- CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test test_runtime 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_runtime 2> /dev/null
testjit:milestones:
stage: test
......@@ -98,17 +122,24 @@ testjit:otherops:
testjit:rpython:
stage: test
script:
- if [ -d "tests/test_jit/mu-client-pypy" ]; then rm -Rf tests/test_jit/mu-client-pypy; fi
- git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git tests/test_jit/mu-client-pypy
- cd tests/test_jit/mu-client-pypy
- git checkout mu-rewrite
- git apply pypy.patch
- cd $CI_PROJECT_DIR/tests/test_jit
- LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy MU_ZEBU=$CI_PROJECT_DIR pytest test_rpython*.py -v
cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
paths:
- .cargo/registry/cache
- .cargo/registry/index
- target
- Cargo.lock
- tests/test_jit/mu-client-pypy
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy pytest test_rpython*.py -v
testjit:som:
stage: test
script:
- if [ -d "tests/test_jit/RPySOM" ]; then rm -Rf tests/test_jit/RPySOM; fi
- git clone https://github.com/microvm/RPySOM.git tests/test_jit/RPySOM
- cd tests/test_jit/RPySOM; git submodule init; git submodule update; cd $CI_PROJECT_DIR
- if [ -d "tests/test_jit/mu-client-pypy" ]; then rm -Rf tests/test_jit/mu-client-pypy; fi
- git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git tests/test_jit/mu-client-pypy
- cd tests/test_jit/mu-client-pypy
- git checkout mu-rewrite
- git apply pypy.patch
- cd $CI_PROJECT_DIR/tests/test_jit
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy:RPySOM/src RPYSOM=RPySOM pytest test_som.py -v
\ No newline at end of file
......@@ -34,3 +34,4 @@ time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
petgraph = "0.4.1"
extprim = "*"
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUST_MODULE" version="4">
<component name="FacetManager">
<facet type="Python" name="Python">
<configuration sdkName="" />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Rust &lt;mu&gt;" level="project" />
<orderEntry type="library" name="Cargo &lt;mu&gt;" level="project" />
</component>
</module>
\ No newline at end of file
......@@ -7,14 +7,13 @@ use ir_semantics;
use utils::vec_utils;
use std::fmt;
use std::sync::RwLock;
#[derive(Debug)]
// this implements RustcEncodable, RustcDecodable, Clone and Display
pub struct Instruction {
pub hdr: MuEntityHeader,
pub value : Option<Vec<P<Value>>>,
pub ops : RwLock<Vec<P<TreeNode>>>,
pub ops : Vec<P<TreeNode>>,
pub v: Instruction_
}
......@@ -27,7 +26,7 @@ impl Encodable for Instruction {
try!(s.emit_struct_field("hdr", 0, |s| self.hdr.encode(s)));
try!(s.emit_struct_field("value", 1, |s| self.value.encode(s)));
let ops = &self.ops.read().unwrap();
let ref ops = self.ops;
try!(s.emit_struct_field("ops", 2, |s| ops.encode(s)));
try!(s.emit_struct_field("v", 3, |s| self.v.encode(s)));
......@@ -50,7 +49,7 @@ impl Decodable for Instruction {
Ok(Instruction{
hdr: hdr,
value: value,
ops: RwLock::new(ops),
ops: ops,
v: v
})
})
......@@ -62,13 +61,20 @@ impl Clone for Instruction {
Instruction {
hdr: self.hdr.clone(),
value: self.value.clone(),
ops: RwLock::new(self.ops.read().unwrap().clone()),
ops: self.ops.clone(),
v: self.v.clone()
}
}
}
impl Instruction {
pub fn clone_with_id(&self, new_id: MuID) -> Instruction {
let mut clone = self.clone();
clone.hdr = self.hdr.clone_with_id(new_id);
clone
}
pub fn has_exception_clause(&self) -> bool {
ir_semantics::is_potentially_excepting_instruction(&self.v)
}
......@@ -133,7 +139,7 @@ impl Instruction {
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ops = &self.ops.read().unwrap();
let ref ops = self.ops;
if self.value.is_some() {
write!(f, "{} = {}", vec_utils::as_str(self.value.as_ref().unwrap()), self.v.debug_str(ops))
} else {
......
......@@ -242,7 +242,7 @@ impl MuFunctionVersion {
for inst in block_content.body.iter() {
match inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.read().unwrap();
let ref ops = inst.ops;
match inst.v {
Instruction_::ExprCall{ref data, ..}
......@@ -358,6 +358,16 @@ impl FunctionContent {
None => panic!("cannot find block #{}", id)
}
}
pub fn get_block_by_name(&self, name: String) -> &Block {
for block in self.blocks.values() {
if block.name().unwrap() == name {
return block;
}
}
panic!("cannot find block {}", name)
}
}
#[derive(Default, Debug, RustcEncodable, RustcDecodable)]
......@@ -535,7 +545,7 @@ impl BlockContent {
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.read().unwrap();
let ref ops = inst.ops;
match inst.v {
Instruction_::Return(_)
| Instruction_::ThreadExit
......@@ -703,15 +713,16 @@ impl Value {
}
}
pub fn is_int_reg(&self) -> bool {
pub fn is_reg(&self) -> bool {
match self.v {
Value_::SSAVar(_) => {
if is_scalar(&self.ty) && !is_fp(&self.ty) {
true
} else {
false
Value_::SSAVar(_) => true,
_ => false
}
}
pub fn is_const(&self) -> bool {
match self.v {
Value_::Constant(_) => true,
_ => false
}
}
......@@ -724,21 +735,6 @@ impl Value {
})
}
pub fn is_fp_reg(&self) -> bool {
match self.v {
Value_::SSAVar(_) => {
if is_scalar(&self.ty) && is_fp(&self.ty) {
true
} else {
false
}
},
Value_::Constant(Constant::Double(_)) => true,
Value_::Constant(Constant::Float(_)) => true,
_ => false
}
}
pub fn is_int_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::Int(_)) => true,
......@@ -761,6 +757,13 @@ impl Value {
_ => None
}
}
pub fn extract_memory_location(&self) -> Option<MemoryLocation> {
match self.v {
Value_::Memory(ref loc) => Some(loc.clone()),
_ => None
}
}
}
const DISPLAY_ID : bool = true;
......@@ -826,7 +829,10 @@ pub struct SSAVarEntry {
use_count: AtomicUsize,
// this field is only used during TreeGeneration pass
expr: Option<Instruction>
expr: Option<Instruction>,
// some ssa vars (such as int128) needs to be split into smaller vars
split: Option<Vec<P<Value>>>
}
impl Encodable for SSAVarEntry {
......@@ -836,6 +842,7 @@ impl Encodable for SSAVarEntry {
let count = self.use_count.load(Ordering::SeqCst);
try!(s.emit_struct_field("use_count", 1, |s| s.emit_usize(count)));
try!(s.emit_struct_field("expr", 2, |s| self.expr.encode(s)));
try!(s.emit_struct_field("split", 3, |s| self.split.encode(s)));
Ok(())
})
}
......@@ -847,11 +854,13 @@ impl Decodable for SSAVarEntry {
let val = try!(d.read_struct_field("val", 0, |d| Decodable::decode(d)));
let count = try!(d.read_struct_field("use_count", 1, |d| d.read_usize()));
let expr = try!(d.read_struct_field("expr", 2, |d| Decodable::decode(d)));
let split = try!(d.read_struct_field("split", 3, |d| Decodable::decode(d)));
let ret = SSAVarEntry {
val: val,
use_count: ATOMIC_USIZE_INIT,
expr: expr
expr: expr,
split: split
};
ret.use_count.store(count, Ordering::SeqCst);
......@@ -866,7 +875,8 @@ impl SSAVarEntry {
let ret = SSAVarEntry {
val: val,
use_count: ATOMIC_USIZE_INIT,
expr: None
expr: None,
split: None
};
ret.use_count.store(0, Ordering::SeqCst);
......@@ -902,6 +912,16 @@ impl SSAVarEntry {
debug_assert!(self.has_expr());
self.expr.take().unwrap()
}
pub fn has_split(&self) -> bool {
self.split.is_some()
}
pub fn set_split(&mut self, vec: Vec<P<Value>>) {
self.split = Some(vec);
}
pub fn get_split(&self) -> &Option<Vec<P<Value>>> {
&self.split
}
}
impl fmt::Display for SSAVarEntry {
......@@ -913,6 +933,7 @@ impl fmt::Display for SSAVarEntry {
#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Constant {
Int(u64),
IntEx(Vec<u64>),
Float(f32),
Double(f64),
// IRef(Address),
......@@ -929,6 +950,7 @@ impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Constant::Int(v) => write!(f, "{}", v as i64),
&Constant::IntEx(ref v) => write!(f, "IntEx {:?}", v),
&Constant::Float(v) => write!(f, "{}", v),
&Constant::Double(v) => write!(f, "{}", v),
// &Constant::IRef(v) => write!(f, "{}", v),
......@@ -1163,6 +1185,13 @@ impl MuEntityHeader {
None => None
}
}
pub fn clone_with_id(&self, new_id: MuID) -> MuEntityHeader {
let mut clone = self.clone();
clone.id = new_id;
clone
}
}
impl PartialEq for MuEntityHeader {
......
......@@ -59,6 +59,7 @@ lazy_static! {
UINT128_TYPE.clone(),
FLOAT_TYPE.clone(),
DOUBLE_TYPE.clone(),
FLOAT_TYPE.clone(),
VOID_TYPE.clone()
];
}
......@@ -103,28 +104,166 @@ impl MuType {
}
}
pub fn get_struct_hybrid_tag(&self) -> Option<MuName> {
pub fn is_ref(&self) -> bool {
match self.v {
MuType_::Hybrid(ref name)
| MuType_::Struct(ref name) => Some(name.clone()),
_ => None
MuType_::Ref(_) => true,
_ => false
}
}
pub fn is_ref(&self) -> bool {
pub fn is_iref(&self) -> bool {
match self.v {
MuType_::Ref(_) => true,
MuType_::IRef(_) => true,
_ => false
}
}
pub fn is_iref(&self) -> bool {
pub fn is_fp(&self) -> bool {
match self.v {
MuType_::Float | MuType_::Double => true,
_ => false
}
}
pub fn is_float(&self) -> bool {
match self.v {
MuType_::Float => true,
_ => false
}
}
pub fn is_double(&self) -> bool {
match self.v {
MuType_::Double => true,
_ => false
}
}
/// is a type raw pointer?
pub fn is_ptr(&self) -> bool {
match self.v {
MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
_ => false
}
}
/// this a type reference type (located in heap)?
pub fn is_reference(&self) -> bool {
match self.v {
MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_) => true,
_ => false
}
}
/// this is a aggregated type (consited of other types)
pub fn is_aggregate(&self) -> bool {
match self.v {
MuType_::Struct(_)
| MuType_::Hybrid(_)
| MuType_::Array(_, _) => true,
_ => false
}
}
/// is a type scalar type?
pub fn is_scalar(&self) -> bool {
match self.v {
MuType_::Int(_)
| MuType_::Float
| MuType_::Double
| MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_)
| MuType_::FuncRef(_)
| MuType_::UFuncPtr(_)
| MuType_::ThreadRef
| MuType_::StackRef
| MuType_::Tagref64
| MuType_::UPtr(_) => true,
_ => false
}
}
/// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced.
pub fn is_traced(&self) -> bool {
match self.v {
MuType_::Ref(_) => true,
MuType_::IRef(_) => true,
MuType_::WeakRef(_) => true,
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => elem_ty.is_traced(),
MuType_::ThreadRef
| MuType_::StackRef
| MuType_::Tagref64 => true,
MuType_::Hybrid(ref tag) => {
let map = HYBRID_TAG_MAP.read().unwrap();
let hybrid_ty = map.get(tag).unwrap();
let ref fix_tys = hybrid_ty.fix_tys;
let ref var_ty = hybrid_ty.var_ty;
var_ty.is_traced() ||
fix_tys.into_iter().map(|ty| ty.is_traced())
.fold(false, |ret, this| ret || this)
},
MuType_::Struct(ref tag) => {
let map = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = map.get(tag).unwrap();
let ref field_tys = struct_ty.tys;
field_tys.into_iter().map(|ty| ty.is_traced())
.fold(false, |ret, this| ret || this)
},
_ => false
}
}
/// is a type native safe?
/// Note: An aggregated type is native safe if all of its parts are native safe.
pub fn is_native_safe(&self) -> bool {
match self.v {
MuType_::Int(_) => true,
MuType_::Float => true,
MuType_::Double => true,
MuType_::Void => true,
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => elem_ty.is_native_safe(),
MuType_::UPtr(_) => true,
MuType_::UFuncPtr(_) => true,
MuType_::Hybrid(ref tag) => {
let map = HYBRID_TAG_MAP.read().unwrap();
let hybrid_ty = map.get(tag).unwrap();
let ref fix_tys = hybrid_ty.fix_tys;
let ref var_ty = hybrid_ty.var_ty;
var_ty.is_native_safe() &&
fix_tys.into_iter().map(|ty| ty.is_native_safe())
.fold(true, |ret, this| ret && this)
},
MuType_::Struct(ref tag) => {
let map = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = map.get(tag).unwrap();
let ref field_tys = struct_ty.tys;
field_tys.into_iter().map(|ty| ty.is_native_safe())
.fold(true, |ret, this| ret && this)
},
_ => false
}
}
pub fn get_struct_hybrid_tag(&self) -> Option<MuName> {
match self.v {
MuType_::Hybrid(ref name)
| MuType_::Struct(ref name) => Some(name.clone()),
_ => None
}
}
pub fn get_elem_ty(&self) -> Option<P<MuType>> {
match self.v {
MuType_::Array(ref elem_ty, _) => Some(elem_ty.clone()),
......@@ -475,131 +614,6 @@ impl MuType_ {
}
}
/// is a type floating-point type?
pub fn is_fp(ty: &MuType) -> bool {
match ty.v {
MuType_::Float | MuType_::Double => true,
_ => false
}
}
/// is a type raw pointer?
pub fn is_ptr(ty: &MuType) -> bool {
match ty.v {
MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
_ => false
}
}
/// this a type reference type (located in heap)?
pub fn is_reference(ty: &MuType) -> bool {
match ty.v {
MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_) => true,
_ => false
}
}
/// this is a aggregated type (consited of other types)
pub fn is_aggregate(ty: &MuType) -> bool {
match ty.v {
MuType_::Struct(_)
| MuType_::Hybrid(_)
| MuType_::Array(_, _) => true,
_ => false
}
}
/// is a type scalar type?
pub fn is_scalar(ty: &MuType) -> bool {
match ty.v {
MuType_::Int(_)
| MuType_::Float
| MuType_::Double
| MuType_::Ref(_)
| MuType_::IRef(_)
| MuType_::WeakRef(_)
| MuType_::FuncRef(_)
| MuType_::UFuncPtr(_)
| MuType_::ThreadRef
| MuType_::StackRef
| MuType_::Tagref64
| MuType_::UPtr(_) => true,
_ => false
}
}
/// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced.
pub fn is_traced(ty: &MuType) -> bool {
match ty.v {
MuType_::Ref(_) => true,
MuType_::IRef(_) => true,
MuType_::WeakRef(_) => true,
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => is_traced(elem_ty),
MuType_::ThreadRef
| MuType_::StackRef
| MuType_::Tagref64 => true,
MuType_::Hybrid(ref tag) => {
let map = HYBRID_TAG_MAP.read().unwrap();
let hybrid_ty = map.get(tag).unwrap();
let ref fix_tys = hybrid_ty.fix_tys;
let ref var_ty = hybrid_ty.var_ty;
is_traced(var_ty) ||
fix_tys.into_iter().map(|ty| is_traced(ty))
.fold(false, |ret, this| ret || this)
},
MuType_::Struct(ref tag) => {
let map = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = map.get(tag).unwrap();
let ref field_tys = struct_ty.tys;
field_tys.into_iter().map(|ty| is_traced(&ty))
.fold(false, |ret, this| ret || this)
},
_ => false
}
}
/// is a type native safe?
/// Note: An aggregated type is native safe if all of its parts are native safe.
pub fn is_native_safe(ty: &MuType) -> bool {
match ty.v {
MuType_::Int(_) => true,
MuType_::Float => true,
MuType_::Double => true,
MuType_::Void => true,
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => is_native_safe(elem_ty),
MuType_::UPtr(_) => true,
MuType_::UFuncPtr(_) => true,
MuType_::Hybrid(ref tag) => {
let map = HYBRID_TAG_MAP.read().unwrap();
let hybrid_ty = map.get(tag).unwrap();
let ref fix_tys = hybrid_ty.fix_tys;
let ref var_ty = hybrid_ty.var_ty;
is_native_safe(var_ty) &&
fix_tys.into_iter().map(|ty| is_native_safe(&ty))
.fold(true, |ret, this| ret && this)
},
MuType_::Struct(ref tag) => {
let map = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = map.get(tag).unwrap();
let ref field_tys = struct_ty.tys;
field_tys.into_iter().map(|ty| is_native_safe(&ty))
.fold(true, |ret, this| ret && this)
},
_ => false
}
}
pub fn get_referent_ty(ty: &MuType) -> Option<P<MuType>> {
match ty.v {
MuType_::Ref(ref referent)
......
......@@ -39,6 +39,9 @@ pub trait CodeGenerator {
fn emit_cmp_imm_r(&mut self, op1: i32, op2: Reg); </