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 9e67a38d authored by Javad Ebrahimian Amiri's avatar Javad Ebrahimian Amiri

Merge branch 'rtmu-dev' into 'master'

rtmu dev

See merge request !59
parents 6f647556 c6557f98
......@@ -7,20 +7,26 @@ 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 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:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo clean
- time rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test -j6 --release --no-run --color=always
- rustc --version
- cargo clean
- time cargo test -j6 $ZEBU_CARGO_ARG --no-run --color=always
artifacts:
paths:
- 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-*
......@@ -28,22 +34,22 @@ build:
test:cargo:api:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_api --release 2> /dev/null
- cargo test test_api $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:ir:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_ir --release 2> /dev/null
- cargo test test_ir $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:compiler:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_compiler --release 2> /dev/null
- cargo test test_compiler $ZEBU_CARGO_ARG 2> /dev/null
test:cargo:runtime:
stage: test
script:
- rustup run 1.30.1-x86_64-unknown-linux-gnu cargo test test_runtime --release 2> /dev/null
- 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
......@@ -53,7 +59,7 @@ test:cargo:runtime:
export ANTLR_HOME=/home/gitlab-runner/antlr4/runtime/Cpp/run
mkdir lib
cp -r $ANTLR_HOME/usr/local/lib/* $PWD/lib/
cp -r $MU_ZEBU/target/release/deps/* $PWD/lib/
cp -r $MU_ZEBU/target/$ZEBU_BUILD/deps/* $PWD/lib/
export CC=clang
export CXX=clang++
make
......@@ -159,7 +165,7 @@ testjit:som:
mubench:
stage: mubench
script:
- cp ./target/release/deps/libmu.so ./target/release/libmu.so
- 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
......@@ -179,3 +185,4 @@ rustfmt:
stage: rustfmt
script:
- cargo-fmt -- --check --verbose -- src/lib.rs src/ast/src/lib.rs src/gc/src/lib.rs src/utils/src/lib.rs
allow_failure: true
......@@ -15,7 +15,7 @@
[package]
name = "mu"
version = "0.0.1"
authors = [ "Your name <you@example.com>" ]
authors = [ "Your name <you@example.com>", "Javad Amiri <javad.amiri@anu.edu.au>" ]
build = "build.rs"
[lib]
......@@ -26,6 +26,7 @@ doctest = false
default = ["aot"]
aot = []
jit = []
realtime = ["mu_ast/realtime", "mu_utils/realtime", "mu_gc/realtime"]
[build-dependencies]
cc = "*"
......@@ -34,7 +35,7 @@ built = "*"
[dependencies]
mu_ast = {path = "src/ast"}
mu_utils = {path = "src/utils"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "rust-1.30.1", version = "^0.3.18" }
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "master", version = "^0.4.0" }
libc="*"
field-offset = "*"
......@@ -46,7 +47,8 @@ num = "*"
hprof = "*"
memmap = "*"
memsec = "0.1.9"
serde = "*"
serde = { version = "*", features = ["derive"]}
bincode = "*"
serde_derive = "*"
time = "*"
maplit = "*"
......@@ -56,3 +58,4 @@ extprim = "*"
num-traits = "*"
built = "*"
mu_gc = { path = "src/gc"}
cfg-if = "*"
......@@ -53,5 +53,6 @@ fn main() {
}
fn built() {
built::write_built_file().expect("Failed to acquire build-time information");
built::write_built_file()
.expect("Failed to acquire build-time information");
}
#trailing_comma = "Never"
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 = "0.2.11"
log = "*"
simple_logger = "*"
regex = "0.2.2"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "rust-1.30.1", version = "^0.3.18" }
#rodal = { path = "../../rodal", version = "*" }
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", branch = "master", version = "^0.4.0" }
libc = "*"
\ 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.
......@@ -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
......@@ -78,3 +79,9 @@ pub mod inst;
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;
......@@ -36,7 +36,7 @@ pub enum BinOp {
FSub,
FMul,
FDiv,
FRem,
FRem
}
impl fmt::Display for BinOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
......@@ -49,7 +49,7 @@ impl BinOp {
use op::BinOp::*;
match self {
FAdd | FSub | FMul | FDiv | FRem => true,
_ => false,
_ => false
}
}
}
......@@ -83,7 +83,7 @@ pub enum CmpOp {
FULT,
FULE,
FUNE,
FUNO,
FUNO
}
impl fmt::Display for CmpOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
......@@ -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 {
......@@ -116,11 +117,12 @@ impl CmpOp {
FUGT => FULT,
FULT => FUGT,
_ => self, // all other comparisons are symmetric
_ => self // all other comparisons are symmetric
}
}
/// 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 {
......@@ -161,7 +163,7 @@ impl CmpOp {
FONE => FUEQ,
FFALSE => FTRUE,
FTRUE => FFALSE,
FTRUE => FFALSE
}
}
......@@ -173,7 +175,7 @@ impl CmpOp {
SLT => ULT,
SGT => UGT,
SLE => ULE,
_ => self,
_ => self
}
}
......@@ -181,7 +183,7 @@ impl CmpOp {
use op::CmpOp::*;
match self {
SGE | SLT | SGT | SLE => true,
_ => false,
_ => false
}
}
......@@ -189,7 +191,7 @@ impl CmpOp {
use op::CmpOp::*;
match self {
EQ | NE | SGE | SGT | SLE | SLT | UGE | UGT | ULE | ULT => true,
_ => false,
_ => false
}
}
......@@ -200,14 +202,14 @@ impl CmpOp {
use op::CmpOp::*;
match self {
EQ | NE => true,
_ => false,
_ => false
}
}
pub fn is_ult_cmp(self) -> bool {
use op::CmpOp::*;
match self {
UGE | UGT | ULE | ULT => true,
_ => false,
_ => false
}
}
......@@ -215,7 +217,7 @@ impl CmpOp {
use op::CmpOp::*;
match self {
EQ | NE | FORD | FUNO | FUNE | FUEQ | FONE | FOEQ => true,
_ => false,
_ => false
}
}
}
......@@ -233,7 +235,7 @@ pub enum ConvOp {
SITOFP,
BITCAST,
REFCAST,
PTRCAST,
PTRCAST
}
impl fmt::Display for ConvOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
......@@ -253,7 +255,7 @@ pub enum AtomicRMWOp {
MAX,
MIN,
UMAX,
UMIN,
UMIN
}
impl fmt::Display for AtomicRMWOp {
......
......@@ -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.
......@@ -12,7 +12,7 @@ pub enum CallConvResult {
GPR(P<Value>),
GPREX(P<Value>, P<Value>),
FPR(P<Value>),
STACK,
STACK
}
pub mod mu {
......@@ -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,11 +175,11 @@ 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,
vm: &VM
) -> (ByteSize, Vec<ByteSize>) {
let (stack_arg_size, _, stack_arg_offsets) =
BackendType::sequential_layout(stack_val_tys, 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 {
......
......@@ -19,17 +19,21 @@ use runtime::ValueLocation;
use compiler::backend::{Mem, Reg};
use compiler::machine_code::MachineCode;
/// 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
......@@ -238,7 +243,7 @@ pub trait CodeGenerator {
pe: Option<MuName>,
uses: Vec<P<Value>>,
defs: Vec<P<Value>>,
is_native: bool,
is_native: bool
) -> ValueLocation;
fn emit_call_near_r64(
&mut self,
......@@ -246,7 +251,7 @@ pub trait CodeGenerator {
func: &P<Value>,
pe: Option<MuName>,
uses: Vec<P<Value>>,
defs: Vec<P<Value>>,
defs: Vec<P<Value>>
) -> ValueLocation;
fn emit_call_near_mem64(
&mut self,
......@@ -254,7 +259,7 @@ pub trait CodeGenerator {
func: &P<Value>,
pe: Option<MuName>,
uses: Vec<P<Value>>,
defs: Vec<P<Value>>,
defs: Vec<P<Value>>
) -> ValueLocation;
// sometimes we use jmp as a call (but without pushing return address)
......@@ -265,7 +270,7 @@ pub trait CodeGenerator {
pe: Option<MuName>,
uses: Vec<P<Value>>,
defs: Vec<P<Value>>,
is_native: bool,
is_native: bool
) -> ValueLocation;
fn emit_call_jmp_indirect(
&mut self,
......@@ -273,7 +278,7 @@ pub trait CodeGenerator {
func: &P<Value>,
pe: Option<MuName>,
uses: Vec<P<Value>>,
defs: Vec<P<Value>>,
defs: Vec<P<Value>>
) -> ValueLocation;
fn emit_ret(&mut self);
......
......@@ -18,8 +18,9 @@
pub mod inst_sel;
mod codegen;
/// CodeGenerator trait serves as an interface to the backend code generator, which
/// may generate assembly code or binary (not implemented yet)
/// CodeGenerator trait serves as an interface to the backend code
/// generator, which may generate assembly code or binary (not implemented
/// yet)
use compiler::backend::x86_64::codegen::CodeGenerator;
/// assembly backend as AOT compiler
......@@ -54,16 +55,22 @@ use utils::LinkedHashMap;
// number of normal callee saved registers (excluding RSP and RBP)
pub const CALLEE_SAVED_COUNT: usize = 5;
/// a macro to declare a set of general purpose registers that are aliased to the first one
/// a macro to declare a set of general purpose registers that are aliased to
/// the first one
macro_rules! GPR_ALIAS {
($alias: ident: ($id64: expr, $r64: ident) ->
$r32: ident, $r16: ident, $r8l: ident, $r8h: ident) => {
lazy_static! {
pub static ref $r64: P<Value> = GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r32: P<Value> = GPR!($id64 + 1, stringify!($r32), UINT32_TYPE);
pub static ref $r16: P<Value> = GPR!($id64 + 2, stringify!($r16), UINT16_TYPE);
pub static ref $r8l: P<Value> = GPR!($id64 + 3, stringify!($r8l), UINT8_TYPE);
pub static ref $r8h: P<Value> = GPR!($id64 + 4, stringify!($r8h), UINT8_TYPE);
pub static ref $r64: P<Value> =
GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r32: P<Value> =
GPR!($id64 + 1, stringify!($r32), UINT32_TYPE);
pub static ref $r16: P<Value> =
GPR!($id64 + 2, stringify!($r16), UINT16_TYPE);
pub static ref $r8l: P<Value> =
GPR!($id64 + 3, stringify!($r8l), UINT8_TYPE);
pub static ref $r8h: P<Value> =
GPR!($id64 + 4, stringify!($r8h), UINT8_TYPE);
pub static ref $alias: [P<Value>; 5] = [
$r64.clone(),
$r32.clone(),
......@@ -76,10 +83,14 @@ macro_rules! GPR_ALIAS {
($alias: ident: ($id64: expr, $r64: ident) -> $r32: ident, $r16: ident, $r8: ident) => {
lazy_static! {
pub static ref $r64: P<Value> = GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r32: P<Value> = GPR!($id64 + 1, stringify!($r32), UINT32_TYPE);
pub static ref $r16: P<Value> = GPR!($id64 + 2, stringify!($r16), UINT16_TYPE);
pub static ref $r8: P<Value> = GPR!($id64 + 3, stringify!($r8), UINT8_TYPE);
pub static ref $r64: P<Value> =
GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r32: P<Value> =
GPR!($id64 + 1, stringify!($r32), UINT32_TYPE);
pub static ref $r16: P<Value> =
GPR!($id64 + 2, stringify!($r16), UINT16_TYPE);
pub static ref $r8: P<Value> =
GPR!($id64 + 3, stringify!($r8), UINT8_TYPE);
pub static ref $alias: [P<Value>; 4] =
[$r64.clone(), $r32.clone(), $r16.clone(), $r8.clone()];
}
......@@ -87,7 +98,8 @@ macro_rules! GPR_ALIAS {
($alias: ident: ($id64: expr, $r64: ident)) => {
lazy_static! {
pub static ref $r64: P<Value> = GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $r64: P<Value> =
GPR!($id64, stringify!($r64), UINT64_TYPE);
pub static ref $alias: [P<Value>; 4] =
[$r64.clone(), $r64.clone(), $r64.clone(), $r64.clone()];
}
......@@ -100,7 +112,7 @@ macro_rules! GPR {
P(Value {
hdr: MuEntityHeader::named($id, Arc::new($name.to_string())),
ty: $ty.clone(),
v: Value_::SSAVar($id),
v: Value_::SSAVar($id)
})
}};
}
......@@ -111,7 +123,7 @@ macro_rules! FPR {
P(Value {
hdr: MuEntityHeader::named($id, Arc::new($name.to_string())),
ty: DOUBLE_TYPE.clone(),
v: Value_::SSAVar($id),
v: Value_::SSAVar($id)
})
}};
}
......@@ -186,7 +198,7 @@ pub fn get_alias_for_length(id: MuID, length: usize) -> P<Value> {
if id < FPR_ID_START {
let vec = match GPR_ALIAS_TABLE.get(&id) {
Some(vec) => vec,
None => panic!("didnt find {} as GPR", id),
None => panic!("didnt find {} as GPR", id)
};
match length {
......@@ -195,7 +207,7 @@ pub fn get_alias_for_length(id: MuID, length: usize) -> P<Value> {
16 => vec[2].clone(),
8 => vec[3].clone(),
1 => vec[3].clone(),
_ => panic!("unexpected length {} for {}", length, vec[0]),
_ => panic!("unexpected length {} for {}", length, vec[0])
}
} else {
for r in ALL_FPRS.iter() {
......@@ -208,11 +220,13 @@ pub fn get_alias_for_length(id: MuID, length: usize) -> P<Value> {
}
}
/// are two registers aliased? (both must be machine register IDs, otherwise this function panics)
/// are two registers aliased? (both must be machine register IDs, otherwise
/// this function panics)
pub fn is_aliased(id1: MuID, id2: MuID) -> bool {
if get_color_for_precolored(id1) == get_color_for_precolored(id2) {
// we need to specially check the case for AH/BH/CH/DH
// because both AH and AL are aliased to RAX, but AH and AL are not aliased
// because both AH and AL are aliased to RAX, but AH and AL are not
// aliased
macro_rules! is_match {
($a1: expr, $a2: expr; $b: expr) => {
$a1 == $b.id() || $a2 == $b.id()
......@@ -242,7 +256,7 @@ pub fn get_color_for_precolored(id: MuID) -> MuID {
if id < FPR_ID_START {
match GPR_ALIAS_LOOKUP.get(&id) {
Some(val) => val.id(),
None => panic!("cannot find GPR {}", id),
None => panic!("cannot find GPR {}", id)
}
} else {
// we do not have alias for FPRs
......@@ -259,7 +273,7 @@ pub fn check_op_len(op: &P<Value>) -> usize {
Some(16) => 16,
Some(8) => 8,
Some(1) => 8,
_ => panic!("unsupported register length for x64: {}", op.ty),
_ => panic!("unsupported register length for x64: {}", op.ty)
}
}
......@@ -529,7 +543,7 @@ pub fn number_of_usable_regs_in_group(group: RegGroup) -> usize {
match group {
RegGroup::GPR => ALL_USABLE_GPRS.len(),
RegGroup::GPREX => ALL_USABLE_GPRS.len(),
RegGroup::FPR => ALL_USABLE_FPRS.len(),
RegGroup::FPR => ALL_USABLE_FPRS.len()
}
}
......@@ -569,7 +583,10 @@ pub fn get_return_address(frame_pointer: Address) -> Address {