Commit 5ee0ca24 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Merge branch 'develop' of gitlab.anu.edu.au:mu/mu-impl-fast into develop

parents d9196658 5aad05d0
Pipeline #703 failed with stages
in 2 minutes and 46 seconds
......@@ -17,30 +17,19 @@ extern crate gcc;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(target_arch = "x86_64")]
fn main() {
gcc::compile_library("libruntime.a", &["src/runtime/runtime_x64_sysv.c"]);
gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_x64_sysv.c"]);
gcc::Config::new().flag("-O3").flag("-c")
.file("src/runtime/swap_stack_x64_sysv.S")
.compile("libswap_stack.a");
.file("src/runtime/runtime_asm_x64_sysv.S")
.compile("libruntime_asm.a");
}
#[cfg(target_os = "linux")]
#[cfg(target_arch = "aarch64")]
fn main() {
gcc::compile_library("libruntime.a", &["src/runtime/runtime_aarch64_sysv.c"]);
gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_aarch64_sysv.c"]);
gcc::Config::new().flag("-O3").flag("-c")
.file("src/runtime/swap_stack_aarch64_sysv.S")
.compile("libswap_stack.a");
}
// This is here to enable cross compiling from windows/x86_64 to linux/aarch64
#[cfg(target_os = "windows")]
#[cfg(target_arch = "x86_64")]
fn main() {
gcc::compile_library("libruntime.a", &["src/runtime/runtime_aarch64_sysv.c"]);
gcc::Config::new().flag("-O3").flag("-c")
.file("src/runtime/swap_stack_aarch64_sysv.S")
.compile("libswap_stack.a");
.file("src/runtime/runtime_asm_aarch64_sysv.S")
.compile("libruntime_asm.a");
}
\ No newline at end of file
// 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.
use ir::*;
use ptr::*;
use types::*;
use utils::LinkedHashMap;
pub struct MuBundle {
pub id: MuID,
pub type_defs: LinkedHashMap<MuID, P<MuType>>,
pub func_sigs: LinkedHashMap<MuID, P<MuFuncSig>>,
pub constants: LinkedHashMap<MuID, P<Value>>,
pub globals : LinkedHashMap<MuID, P<Value>>,
pub func_defs: LinkedHashMap<MuID, MuFunction>,
pub func_decls: LinkedHashMap<MuID, MuFunctionVersion>,
// id_name_map: LinkedHashMap<MuID, MuName>,
// name_id_map: LinkedHashMap<MuName, MuID>
}
impl MuBundle {
pub fn new(id: MuID) -> MuBundle {
MuBundle {
id: id,
type_defs: LinkedHashMap::new(),
func_sigs: LinkedHashMap::new(),
constants: LinkedHashMap::new(),
globals: LinkedHashMap::new(),
func_defs: LinkedHashMap::new(),
func_decls: LinkedHashMap::new(),
// id_name_map: LinkedHashMap::new(),
// name_id_map: LinkedHashMap::new()
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
// 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.
use inst::*;
use inst::Instruction_::*;
pub fn is_terminal_inst(inst: &Instruction_) -> bool {
match inst {
&Return(_)
| &ThreadExit
| &Throw(_)
| &TailCall(_)
| &Branch1(_)
| &Branch2{..}
| &Watchpoint{..}
| &WPBranch{..}
| &Call{..}
| &CCall{..}
| &SwapStack{..}
| &Switch{..}
| &ExnInstruction{..} => true,
_ => false,
}
}
pub fn is_non_terminal_inst(inst: &Instruction_) -> bool {
!is_terminal_inst(inst)
}
// FIXME: check the correctness
pub fn has_side_effect(inst: &Instruction_) -> bool {
match inst {
&ExprCall{..}
| &ExprCCall{..}
| &Load{..}
| &Store{..}
| &CmpXchg{..}
| &AtomicRMW{..}
| &New(_)
| &AllocA(_)
| &NewHybrid(_, _)
| &AllocAHybrid(_, _)
| &NewStack(_)
| &NewThread(_, _)
| &NewThreadExn(_, _)
| &NewFrameCursor(_)
| &Fence(_)
| &Return(_)
| &ThreadExit
| &Throw(_)
| &TailCall(_)
| &Branch1(_)
| &Branch2{..}
| &Watchpoint{..}
| &WPBranch{..}
| &Call{..}
| &CCall{..}
| &SwapStack{..}
| &Switch{..}
| &ExnInstruction{..}
| &CommonInst_GetThreadLocal
| &CommonInst_SetThreadLocal(_)
| &CommonInst_Pin(_)
| &CommonInst_Unpin(_)
| &PrintHex(_)
| &SetRetval(_) => true,
_ => false,
}
}
pub fn is_potentially_excepting_instruction(inst: &Instruction_) -> bool {
match inst {
&Watchpoint{..}
| &Call{..}
| &CCall{..}
| &SwapStack{..}
| &ExnInstruction{..} => true,
_ => false
}
}
\ No newline at end of file
// 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.
//! # MuIR AST crate
//!
//! This crate provides data structures to allow construct MuIR in Rust code, including:
//! * types
//! * ir
//! * MuFunction
//! * MuFunctionVersion
//! * FunctionContent
//! * Block
//! * BlockContent
//! * TreeNode
//! * Value
//! * Instruction
//! * inst
//! * op (operators)
//!
//! Client should not create MuIR via this crate, use API instead.
#[macro_use]
extern crate rodal;
extern crate simple_logger;
......@@ -19,6 +37,8 @@ extern crate simple_logger;
extern crate lazy_static;
extern crate utils;
/// all data structures for MuIR is an *MuEntity*
/// which has a unique MuID, and an optional MuName
#[macro_export]
macro_rules! impl_mu_entity {
($entity: ty) => {
......@@ -35,6 +55,7 @@ macro_rules! impl_mu_entity {
}
}
/// select between two values based on condition
macro_rules! select_value {
($cond: expr, $res1 : expr, $res2 : expr) => {
if $cond {
......@@ -47,9 +68,7 @@ macro_rules! select_value {
#[macro_use]
pub mod ir;
pub mod bundle;
pub mod inst;
pub mod types;
pub mod ir_semantics;
pub mod ptr;
pub mod op;
// 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.
use ptr::P;
use types::*;
use inst::*;
use types::MuType_::*;
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
pub enum OpCode {
// SSA
RegI64,
RegFP,
// Constant
IntImmI64,
FPImm,
// non-terminal
Assign,
Fence,
//terminal
Return,
ThreadExit,
Throw,
TailCall,
Branch1,
Branch2,
Select,
Watchpoint,
WPBranch,
Call,
CCall,
SwapStack,
Switch,
ExnInstruction,
// expression
Binary(BinOp),
BinaryWithStatus(BinOp),
Comparison(CmpOp),
Conversion(ConvOp),
AtomicRMW(AtomicRMWOp),
ExprCall,
ExprCCall,
Load,
Store,
CmpXchg,
New,
AllocA,
NewHybrid,
AllocAHybrid,
NewStack,
NewThread,
NewThreadExn,
NewFrameCursor,
GetIRef,
GetFieldIRef,
GetElementIRef,
ShiftIRef,
GetVarPartIRef,
CommonInst_GetThreadLocal,
CommonInst_SetThreadLocal,
CommonInst_Pin,
CommonInst_Unpin,
CommonInst_Tr64IsFp,
CommonInst_Tr64IsInt,
CommonInst_Tr64IsRef,
CommonInst_Tr64FromFp,
CommonInst_Tr64FromInt,
CommonInst_Tr64FromRef,
CommonInst_Tr64ToFp,
CommonInst_Tr64ToInt,
CommonInst_Tr64ToRef,
CommonInst_Tr64ToTag,
Move,
PrintHex,
SetRetval
}
pub fn pick_op_code_for_ssa(ty: &P<MuType>) -> OpCode {
let a : &MuType = ty;
match a.v {
// currently use i64 for all ints
Int(_) => OpCode::RegI64,
// currently do not differentiate float and double
Float
| Double => OpCode::RegFP,
// ref and pointer types use RegI64
Ref(_)
| IRef(_)
| WeakRef(_)
| UPtr(_)
| ThreadRef
| StackRef
| Tagref64
| FuncRef(_)
| UFuncPtr(_) => OpCode::RegI64,
// we are not supposed to have these as SSA
Struct(_)
| Array(_, _)
| Hybrid(_)
| Void => panic!("Not expecting {} as SSA", ty),
// unimplemented
Vector(_, _) => unimplemented!()
}
}
pub fn pick_op_code_for_value(ty: &P<MuType>) -> OpCode {
let a : &MuType = ty;
match a.v {
// currently use i64 for all ints
Int(_) => OpCode::IntImmI64,
// currently do not differentiate float and double
Float
| Double => OpCode::FPImm,
// ref and pointer types use RegI64
Ref(_)
| IRef(_)
| WeakRef(_)
| UPtr(_)
| ThreadRef
| StackRef
| Tagref64
| FuncRef(_)
| UFuncPtr(_) => OpCode::IntImmI64,
// we are not supposed to have these as SSA
Struct(_)
| Array(_, _)
| Hybrid(_)
| Void => unimplemented!(),
// unimplemented
Vector(_, _) => unimplemented!()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BinOp {
// Int(n) BinOp Int(n) -> Int(n)
// BinOp Int(n) Int(n) -> Int(n)
Add,
Sub,
Mul,
......@@ -165,12 +26,12 @@ pub enum BinOp {
Or,
Xor,
// Int(n) BinOp Int(m) -> Int(n)
// BinOp Int(n) Int(m) -> Int(n)
Shl,
Lshr,
Ashr,
// FP BinOp FP -> FP
// BinOp FP FP -> FP
FAdd,
FSub,
FMul,
......@@ -212,7 +73,7 @@ pub enum CmpOp {
}
impl CmpOp {
// Returns the CmpOp c, such that (a self b) is equivelent to (b c 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 {
......@@ -239,6 +100,8 @@ impl CmpOp {
_ => 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)
pub fn invert(self) -> CmpOp {
use op::CmpOp::*;
match self {
......@@ -294,6 +157,7 @@ impl CmpOp {
_ => self,
}
}
pub fn is_signed(self) -> bool {
use op::CmpOp::*;
match self {
......@@ -302,6 +166,23 @@ impl CmpOp {
}
}
pub fn is_int_cmp(self) -> bool {
use op::CmpOp::*;
match self {
EQ
| NE
| SGE
| SGT
| SLE
| SLT
| UGE
| UGT
| ULE
| ULT => true,
_ => false
}
}
pub fn is_symmetric(self) -> bool {
use op::CmpOp::*;
match self {
......@@ -340,80 +221,4 @@ pub enum AtomicRMWOp {
MIN,
UMAX,
UMIN
}
pub fn is_int_cmp(op: CmpOp) -> bool {
match op {
CmpOp::EQ
| CmpOp::NE
| CmpOp::SGE
| CmpOp::SGT
| CmpOp::SLE
| CmpOp::SLT
| CmpOp::UGE
| CmpOp::UGT
| CmpOp::ULE
| CmpOp::ULT => true,
_ => false
}
}
pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
match inst.v {
Instruction_::BinOp(op, _, _) => OpCode::Binary(op),
Instruction_::BinOpWithStatus(op, _, _, _) => OpCode::BinaryWithStatus(op),
Instruction_::CmpOp(op, _, _) => OpCode::Comparison(op),
Instruction_::ConvOp{operation, ..} => OpCode::Conversion(operation),
Instruction_::AtomicRMW{op, ..} => OpCode::AtomicRMW(op),
Instruction_::ExprCall{..} => OpCode::ExprCall,
Instruction_::ExprCCall{..} => OpCode::ExprCCall,
Instruction_::Load{..} => OpCode::Load,
Instruction_::Store{..} => OpCode::Store,
Instruction_::CmpXchg{..} => OpCode::CmpXchg,
Instruction_::New(_) => OpCode::New,
Instruction_::AllocA(_) => OpCode::AllocA,
Instruction_::NewHybrid(_, _) => OpCode::NewHybrid,
Instruction_::AllocAHybrid(_, _) => OpCode::AllocAHybrid,
Instruction_::NewStack(_) => OpCode::NewStack,
Instruction_::NewThread(_, _) => OpCode::NewThread,
Instruction_::NewThreadExn(_, _) => OpCode::NewThreadExn,
Instruction_::NewFrameCursor(_) => OpCode::NewFrameCursor,
Instruction_::GetIRef(_) => OpCode::GetIRef,
Instruction_::GetFieldIRef{..} => OpCode::GetFieldIRef,
Instruction_::GetElementIRef{..} => OpCode::GetElementIRef,
Instruction_::ShiftIRef{..} => OpCode::ShiftIRef,
Instruction_::GetVarPartIRef{..} => OpCode::GetVarPartIRef,
Instruction_::Fence(_) => OpCode::Fence,
Instruction_::Return(_) => OpCode::Return,
Instruction_::ThreadExit => OpCode::ThreadExit,
Instruction_::Throw(_) => OpCode::Throw,
Instruction_::TailCall(_) => OpCode::TailCall,
Instruction_::Branch1(_) => OpCode::Branch1,
Instruction_::Branch2{..} => OpCode::Branch2,
Instruction_::Select{..} => OpCode::Select,
Instruction_::Watchpoint{..} => OpCode::Watchpoint,
Instruction_::WPBranch{..} => OpCode::WPBranch,
Instruction_::Call{..} => OpCode::Call,
Instruction_::CCall{..} => OpCode::CCall,
Instruction_::SwapStack{..} => OpCode::SwapStack,
Instruction_::Switch{..} => OpCode::Switch,
Instruction_::ExnInstruction{..} => OpCode::ExnInstruction,
Instruction_::CommonInst_GetThreadLocal => OpCode::CommonInst_GetThreadLocal,
Instruction_::CommonInst_SetThreadLocal(_) => OpCode::CommonInst_SetThreadLocal,
Instruction_::CommonInst_Pin(_) => OpCode::CommonInst_Pin,
Instruction_::CommonInst_Unpin(_) => OpCode::CommonInst_Unpin,
Instruction_::CommonInst_Tr64IsFp(_) => OpCode::CommonInst_Tr64IsFp,
Instruction_::CommonInst_Tr64IsInt(_) => OpCode::CommonInst_Tr64IsInt,
Instruction_::CommonInst_Tr64IsRef(_) => OpCode::CommonInst_Tr64IsRef,
Instruction_::CommonInst_Tr64FromFp(_) => OpCode::CommonInst_Tr64FromFp,
Instruction_::CommonInst_Tr64FromInt(_) => OpCode::CommonInst_Tr64FromInt,
Instruction_::CommonInst_Tr64FromRef(_, _) => OpCode::CommonInst_Tr64FromRef,
Instruction_::CommonInst_Tr64ToFp(_) => OpCode::CommonInst_Tr64ToFp,
Instruction_::CommonInst_Tr64ToInt(_) => OpCode::CommonInst_Tr64ToInt,
Instruction_::CommonInst_Tr64ToRef(_) => OpCode::CommonInst_Tr64ToRef,
Instruction_::CommonInst_Tr64ToTag(_) => OpCode::CommonInst_Tr64ToTag,
Instruction_::Move(_) => OpCode::Move,
Instruction_::PrintHex(_) => OpCode::PrintHex,
Instruction_::SetRetval(_) => OpCode::SetRetval
}
}
}
\ No newline at end of file
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
// Copyright 2017 The Australian National University
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The AST pointer
//!
//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in
//! the AST.
//!
//! # Motivations and benefits
//!
//! * **Identity**: sharing AST nodes is problematic for the various analysis
//! passes (e.g. one may be able to bypass the borrow checker with a shared
//! `ExprAddrOf` node taking a mutable borrow). The only reason `@T` in the
//! AST hasn't caused issues is because of inefficient folding passes which
//! would always deduplicate any such shared nodes. Even if the AST were to
//! switch to an arena, this would still hold, i.e. it couldn't use `&'a T`,
//! but rather a wrapper like `P<'a, T>`.
//!
//! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
//! (unless it contains an `Unsafe` interior, but that may be denied later).
//! This mainly prevents mistakes, but can also enforces a kind of "purity".
//!
//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
//! the latter even when the input and output types differ (as it would be the
//! case with arenas or a GADT AST using type parameters to toggle features).
//!
//! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
//! `and_then` and `map` - which can remain fully functional even if the
//! implementation changes (using a special thread-local heap, for example).
//! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated.
//use std::fmt::{self, Display, Debug};
//use std::hash::{Hash, Hasher};
//use std::ops::Deref;
// 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.
use std::sync::Arc;
/// 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>;
//pub struct P<T: MuEntity> {
// ptr: Arc<T>
//}
#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T>(value: T) -> P<T> {
// P {ptr: Arc::new(value)}
Arc::new(value)
}
//impl<T: MuEntity> Deref for P<T> {
// type Target = T;
//
// fn deref<'a>(&'a self) -> &'a T {
// &*self.ptr
// }
//}
//
//impl<T: MuEntity> Clone for P<T> {
// fn clone(&self) -> P<T> {
// P {ptr: self.ptr.clone()}
// }
//}
//
//impl<T: MuEntity + PartialEq> PartialEq for P<T> {
// fn eq(&self, other: &P<T>) -> bool {
// **self == **other
// }
//}
//
//impl<T: MuEntity + Eq> Eq for P<T> {}
//
//impl<T: MuEntity + Debug> Debug for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Debug::fmt(&**self, f)
// }
//}
//impl<T: MuEntity + Display> Display for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Display::fmt(&**self, f)
// }
//}
//
//impl<T: MuEntity> fmt::Pointer for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// fmt::Pointer::fmt(&self.ptr, f)
// }
//}
//
//impl<T: MuEntity + Hash> Hash for P<T> {
// fn hash<H: Hasher>(&self, state: &mut H) {
// (**self).hash(state);
// }
//}
\ No newline at end of file
}
\ No newline at end of file
This diff is collapsed.
......@@ -276,9 +276,7 @@ impl ASMCode {
let ref mut asm = self.code;
for i in 0..n_insts {
if TRACE_CFA {
trace!("---inst {}---", i);
}
trace_if!(TRACE_CFA, "---inst {}---", i);
// skip symbol
if asm[i].is_symbol {
......@@ -300,9 +298,7 @@ impl ASMCode {
if !asm[i].preds.contains(&last_inst) {
asm[i].preds.push(last_inst);
if TRACE_CFA {
trace!("inst {}: set PREDS as previous inst - fallthrough {}", i, last_inst);
}
trace_if!(TRACE_CFA,