Commit 415d45e8 authored by qinsoon's avatar qinsoon

Merge branch 'master' into open-source

parents 29759a3c 99a65c69
......@@ -11,8 +11,10 @@ Cargo.lock
*.pyc
*.o
*.dylib
mu-client-pypy
**mu-client-pypy**
**RPySOM**
.gitignore
cmake-build-debug/*
Notes/*
CMakeLists.txt
\ No newline at end of file
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"
paths:
- .cargo/registry/cache
- .cargo/registry/index
- target
- Cargo.lock
# 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:
- 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
......@@ -33,4 +33,5 @@ rustc-serialize = "*"
time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
petgraph = "0.4.1"
\ No newline at end of file
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
......@@ -6,7 +6,6 @@ use op::*;
use utils::vec_utils;
use std::fmt;
use std::sync::RwLock;
/// Instruction represents a Mu instruction
#[derive(Debug)] // RustcEncodable, RustcDecodable, Clone and Display
......@@ -17,7 +16,7 @@ pub struct Instruction {
/// ops field list all the children nodes,
/// and in Instruction_, the children nodes are referred by indices
/// This design makes it easy for the compiler to iterate through all the children
pub ops : RwLock<Vec<P<TreeNode>>>,
pub ops : Vec<P<TreeNode>>,
/// used for pattern matching
pub v: Instruction_
}
......@@ -32,7 +31,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)));
......@@ -55,7 +54,7 @@ impl Decodable for Instruction {
Ok(Instruction{
hdr: hdr,
value: value,
ops: RwLock::new(ops),
ops: ops,
v: v
})
})
......@@ -67,13 +66,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
}
/// is this instruction the terminal inst of its block?
/// Terminal instructions end Mu blocks, and Mu block ends with a terminal instruction.
pub fn is_terminal_inst(&self) -> bool {
......@@ -249,7 +255,6 @@ impl Instruction {
/// returns exception target(block ID), returns None if this instruction does not have exceptional branch
pub fn get_exception_target(&self) -> Option<MuID> {
use inst::Instruction_::*;
match self.v {
Watchpoint {ref resume, ..}
| Call {ref resume, ..}
......@@ -308,7 +313,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 {
......
......@@ -249,7 +249,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, ..}
......@@ -364,6 +364,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)
}
}
/// FunctionContext contains compilation information about the function
......@@ -560,7 +570,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
......@@ -738,16 +748,17 @@ impl Value {
_ => false
}
}
pub fn is_int_reg(&self) -> bool {
pub fn is_reg(&self) -> bool {
match self.v {
Value_::SSAVar(_) => {
if self.ty.is_scalar() && !self.ty.is_fp() {
true
} else {
false
}
}
Value_::SSAVar(_) => true,
_ => false
}
}
pub fn is_const(&self) -> bool {
match self.v {
Value_::Constant(_) => true,
_ => false
}
}
......@@ -763,21 +774,6 @@ impl Value {
})
}
pub fn is_fp_reg(&self) -> bool {
match self.v {
Value_::SSAVar(_) => {
if self.ty.is_scalar() && self.ty.is_fp() {
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,
......@@ -800,6 +796,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;
......@@ -868,7 +871,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 {
......@@ -878,6 +884,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(())
})
}
......@@ -886,14 +893,16 @@ impl Encodable for SSAVarEntry {
impl Decodable for SSAVarEntry {
fn decode<D: Decoder>(d: &mut D) -> Result<SSAVarEntry, D::Error> {
d.read_struct("SSAVarEntry", 3, |d| {
let val = try!(d.read_struct_field("val", 0, |d| Decodable::decode(d)));
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 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);
......@@ -908,7 +917,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);
......@@ -944,6 +954,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 {
......@@ -957,6 +977,7 @@ impl fmt::Display for SSAVarEntry {
pub enum Constant {
/// all integer constants are stored as u64
Int(u64),
IntEx(Vec<u64>),
/// float constants
Float(f32),
/// double constants
......@@ -977,6 +998,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),
......@@ -1227,6 +1249,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 {
......
......@@ -117,6 +117,22 @@ impl MuType {
}
}
/// is this type a float type (single-precision floating point)
pub fn is_float(&self) -> bool {
match self.v {
MuType_::Float => true,
_ => false
}
}
/// is this type a double type (double-precision floating point)
pub fn is_double(&self) -> bool {
match self.v {
MuType_::Double => true,
_ => false
}
}
/// is this type a scalar type?
pub fn is_scalar(&self) -> bool {
match self.v {
......@@ -173,6 +189,14 @@ impl MuType {
}
}
/// is a type raw pointer?
pub fn is_ptr(&self) -> bool {
match self.v {
MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
_ => false
}
}
/// is this type an aggregated type? (consisted of other types)
pub fn is_aggregate(&self) -> bool {
match self.v {
......
......@@ -39,6 +39,9 @@ pub trait CodeGenerator {
fn emit_cmp_imm_r(&mut self, op1: i32, op2: Reg);
fn emit_cmp_mem_r(&mut self, op1: Reg, op2: Reg);
fn emit_test_r_r (&mut self, op1: Reg, op2: Reg);
fn emit_test_imm_r(&mut self, op1: i32, op2: Reg);
// gpr move
// mov imm64 to r64
......@@ -133,16 +136,29 @@ pub trait CodeGenerator {
fn emit_add_r_r (&mut self, dest: Reg, src: Reg);
fn emit_add_r_mem(&mut self, dest: Reg, src: Mem);
fn emit_add_r_imm(&mut self, dest: Reg, src: i32);
// add with carry
fn emit_adc_r_r (&mut self, dest: Reg, src: Reg);
fn emit_adc_r_mem(&mut self, dest: Reg, src: Mem);
fn emit_adc_r_imm(&mut self, dest: Reg, src: i32);
// sub
fn emit_sub_r_r (&mut self, dest: Reg, src: Reg);
fn emit_sub_r_mem(&mut self, dest: Reg, src: Mem);
fn emit_sub_r_imm(&mut self, dest: Reg, src: i32);
// sub with borrow
fn emit_sbb_r_r (&mut self, dest: Reg, src: Reg);
fn emit_sbb_r_mem(&mut self, dest: Reg, src: Mem);
fn emit_sbb_r_imm(&mut self, dest: Reg, src: i32);
// multiply
fn emit_mul_r (&mut self, src: Reg);
fn emit_mul_mem(&mut self, src: Mem);
// signed multiply
fn emit_imul_r_r(&mut self, dest: Reg, src: Reg);
// div
fn emit_div_r (&mut self, src: Reg);
fn emit_div_mem (&mut self, src: Mem);
......@@ -155,9 +171,13 @@ pub trait CodeGenerator {
fn emit_shl_r_cl (&mut self, dest: Reg);
fn emit_shl_r_imm8 (&mut self, dest: Reg, src: i8);
fn emit_shld_r_r_cl (&mut self, dest: Reg, src: Reg);
fn emit_shr_r_cl (&mut self, dest: &P<Value>);
fn emit_shr_r_imm8 (&mut self, dest: &P<Value>, src: i8);
fn emit_shrd_r_r_cl (&mut self, dest: Reg, src: Reg);
fn emit_sar_r_cl (&mut self, dest: &P<Value>);
fn emit_sar_r_imm8 (&mut self, dest: &P<Value>, src: i8);
......@@ -166,16 +186,18 @@ pub trait CodeGenerator {
fn emit_cwd(&mut self); // sign extend ax to dx:ax
fn emit_jmp(&mut self, dest: MuName);
fn emit_je(&mut self, dest: MuName);
fn emit_je (&mut self, dest: MuName);
fn emit_jne(&mut self, dest: MuName);
fn emit_ja(&mut self, dest: MuName);
fn emit_ja (&mut self, dest: MuName);
fn emit_jae(&mut self, dest: MuName);
fn emit_jb(&mut self, dest: MuName);
fn emit_jb (&mut self, dest: MuName);
fn emit_jbe(&mut self, dest: MuName);
fn emit_jg(&mut self, dest: MuName);
fn emit_jg (&mut self, dest: MuName);
fn emit_jge(&mut self, dest: MuName);
fn emit_jl(&mut self, dest: MuName);
fn emit_jl (&mut self, dest: MuName);
fn emit_jle(&mut self, dest: MuName);
fn emit_js(&mut self, dest: MuName);
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName, pe: Option<MuName>) -> ValueLocation;
fn emit_call_near_r64 (&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation;
......@@ -192,33 +214,57 @@ pub trait CodeGenerator {
fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>); // store
fn emit_movss_f32_f32 (&mut self, dest: &P<Value>, src: &P<Value>);
fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>); // load
fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>); // store
// fp add
fn emit_addsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_addss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp sub
fn emit_subsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_subss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp div
fn emit_divsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_divss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp mul
fn emit_mulsd_f64_f64 (&mut self, dest: Reg, src: Reg);
fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);
fn emit_mulss_f32_f32 (&mut self, dest: Reg, src: Reg);
fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);
// fp comparison
fn emit_comisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
fn emit_comiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg);
// fp conversion
fn emit_cvtsi2sd_f64_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvtsi2ss_f32_r (&mut self, dest: Reg, src: Reg);
fn emit_cvtss2si_r_f32 (&mut self, dest: Reg, src: Reg);
// used for unsigned int to fp conversion
fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
fn emit_cvttss2si_r_f32 (&mut self, dest: Reg, src: Reg);
// unpack low data - interleave low byte
fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
// substract packed double-fp
......@@ -229,4 +275,6 @@ pub trait CodeGenerator {
// move aligned packed double-precision fp values
fn emit_movapd_f64_mem128(&mut self, dest: Reg, src: Mem);
fn emit_movapd_f64_f64 (&mut self, dest: Reg, src: Mem);
fn emit_movaps_f32_f32 (&mut self, dest: Reg, src: Reg);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,7 +6,7 @@ pub mod inst_sel;
mod codegen;
pub use compiler::backend::x86_64::codegen::CodeGenerator;
mod asm_backend;
pub mod asm_backend;
pub use compiler::backend::x86_64::asm_backend::ASMCodeGen;
pub use compiler::backend::x86_64::asm_backend::emit_code;
pub use compiler::backend::x86_64::asm_backend::emit_context;
......@@ -425,8 +425,9 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
pub fn number_of_regs_in_group(group: RegGroup) -> usize {
match group {
RegGroup::GPR => ALL_GPRs.len(),
RegGroup::FPR => ALL_FPRs.len()
RegGroup::GPR => ALL_GPRs.len(),
RegGroup::GPREX => ALL_GPRs.len(),
RegGroup::FPR => ALL_FPRs.len()
}
}
......@@ -444,13 +445,7 @@ pub fn all_usable_regs() -> &'static Vec<P<Value>> {
pub fn pick_group_for_reg(reg_id: MuID) -> RegGroup {
let reg = all_regs().get(&reg_id).unwrap();
if reg.is_int_reg() {
RegGroup::GPR
} else if reg.is_fp_reg() {
RegGroup::FPR
} else {
panic!("expect a machine reg to be either a GPR or a FPR: {}", reg)
}
RegGroup::get_from_value(reg)
}
pub fn is_callee_saved(reg_id: MuID) -> bool {
......
......@@ -222,7 +222,7 @@ fn emit_muir_dot_inner(file: &mut File,
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.read().unwrap();
let ref ops = inst.ops;
match inst.v {
Branch1(ref dest) => {
......
......@@ -121,6 +121,10 @@ pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
size: 8, alignment: 8, struct_layout: None, elem_padded_size: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(8, 8))
},
128 => BackendTypeInfo {
size: 16, alignment: 16, struct_layout: None, elem_padded_size: None,
gc_type: mm::add_gc_type(GCType::new_noreftype(16, 16))
},
_ => unimplemented!()
}
},
......@@ -297,7 +301,7 @@ pub fn sequetial_layout(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, ByteSize, V
let ret = layout_struct(tys, vm);
(ret.size, ret.alignment, ret.struct_layout.unwrap())
}
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BackendTypeInfo {
......@@ -343,10 +347,10 @@ impl fmt::Display for BackendTypeInfo {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum RegGroup {GPR, FPR}
pub enum RegGroup {GPR, GPREX, FPR}
impl RegGroup {
pub fn get(ty: &P<MuType>) -> RegGroup {
pub fn get_from_ty(ty: &P<MuType>) -> RegGroup {
match ty.v {
// for now, only use 64bits registers
MuType_::Int(len) if len == 1 => RegGroup::GPR,
......@@ -354,6 +358,7 @@ impl RegGroup {
MuType_::Int(len) if len == 16 => RegGroup::GPR,
MuType_::Int(len) if len == 32 => RegGroup::GPR,
MuType_::Int(len) if len == 64 => RegGroup::GPR,
MuType_::Int(len) if len == 128=> RegGroup::GPREX,
MuType_::Ref(_)
| MuType_::IRef(_)
......@@ -371,4 +376,8 @@ impl RegGroup {
_ => unimplemented!()
}
}
pub fn get_from_value(val: &P<Value>) -> RegGroup {
RegGroup::get_from_ty(&val.ty)
}
}
......@@ -43,7 +43,7 @@ impl InterferenceGraph {
let node = GraphNode {
temp: reg_id,
color: None,
group: backend::RegGroup::get(entry.ty()),
group: backend::RegGroup::get_from_ty(entry.ty()),
spill_cost: 0.0f32
};
......
......@@ -14,7 +14,6 @@ use compiler::CompilerPass;
use compiler::backend::is_callee_saved;
use compiler::backend::init_machine_regs_for_func;