WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit e9c4386b authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano
Browse files

Made IR output compatiable with MUC (hopefully)

parent 9b82225d
This diff is collapsed.
......@@ -327,11 +327,11 @@ impl MuFunctionVersion {
match callee.v {
TreeNode_::Instruction(_) => {}
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::Constant(Constant::FuncRef(id)) => {
match &pv.v {
&Value_::Constant(Constant::FuncRef(ref func)) => {
ret.insert(
inst.id(),
(id, inst.has_exception_clause())
(func.id(), inst.has_exception_clause())
);
}
_ => {}
......@@ -1103,8 +1103,8 @@ impl Value {
}
}
const DISPLAY_ID: bool = true;
const DISPLAY_TYPE: bool = true;
const DISPLAY_ID: bool = false;
const DISPLAY_TYPE: bool = false;
const PRINT_ABBREVIATE_NAME: bool = true;
impl fmt::Debug for Value {
......@@ -1117,17 +1117,17 @@ impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if DISPLAY_TYPE {
match self.v {
Value_::SSAVar(_) => write!(f, "{}(%{})", self.ty, self.hdr),
Value_::Constant(ref c) => write!(f, "{}({})", self.ty, c),
Value_::Global(ref ty) => write!(f, "{}(@{})", ty, self.hdr),
Value_::Memory(ref mem) => write!(f, "%{}{})", self.hdr, mem)
Value_::SSAVar(_) => write!(f, "<{}>{}", self.ty, self.hdr),
Value_::Constant(ref c) => write!(f, "<{}>{}", self.ty, c),
Value_::Global(ref ty) => write!(f, "<{}>@{}", ty, self.hdr),
Value_::Memory(ref mem) => write!(f, "<{}>{}{}", self.ty, self.hdr, mem)
}
} else {
match self.v {
Value_::SSAVar(_) => write!(f, "%{}", self.hdr),
Value_::Constant(ref c) => write!(f, "{}", c),
Value_::SSAVar(_) => write!(f, "{}", self.hdr),
Value_::Constant(ref c) => write!(f, "<{}>{}", self.ty, c),
Value_::Global(_) => write!(f, "@{}", self.hdr),
Value_::Memory(ref mem) => write!(f, "%{}{}", self.hdr, mem)
Value_::Memory(ref mem) => write!(f, "{}{}", self.hdr, mem)
}
}
}
......@@ -1232,7 +1232,7 @@ pub enum Constant {
/// double constants
Double(f64),
/// function reference
FuncRef(MuID),
FuncRef(MuEntityHeader),
/// vector constant (currently not used)
Vector(Vec<Constant>),
/// null reference
......@@ -1250,12 +1250,20 @@ 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::IntEx(ref v) => {
let mut res = format!("");
// Stored in little-endian order, but we need to display it in big-endian order
for i in 1 .. v.len() + 1 {
res.push_str(format!("{:016X}", v[v.len() - i]).to_string().as_str());
}
write!(f, "0x{}", res)
},
&Constant::Float(v) => write!(f, "{}", v),
&Constant::Double(v) => write!(f, "{}", v),
// &Constant::IRef(v) => write!(f, "{}", v),
&Constant::FuncRef(v) => write!(f, "FuncRef {}", v),
&Constant::FuncRef(ref v) => write!(f, "FuncRef {}", v.name),
&Constant::Vector(ref v) => {
// TODO: Make this Muc compatible?
write!(f, "[").unwrap();
for i in 0..v.len() {
write!(f, "{}", v[i]).unwrap();
......@@ -1265,8 +1273,8 @@ impl fmt::Display for Constant {
}
write!(f, "]")
}
&Constant::NullRef => write!(f, "NullRef"),
&Constant::ExternSym(ref name) => write!(f, "ExternSym({})", name),
&Constant::NullRef => write!(f, "NULL"),
&Constant::ExternSym(ref name) => write!(f, "EXTERN \\\"{}\\\"", name),
&Constant::List(ref vec) => {
write!(f, "List(").unwrap();
......@@ -1569,21 +1577,7 @@ impl MuEntityHeader {
/// an abbreviate (easy reading) version of the name
fn abbreviate_name(&self) -> String {
let split: Vec<&str> = self.name.split('.').collect();
let mut ret = "".to_string();
for i in 0..split.len() - 1 {
ret.push(match split[i].chars().next() {
Some(c) => c,
None => '_'
});
ret.push('.');
}
ret.push_str(split.last().unwrap());
ret
self.name.split('.').last().unwrap().to_string()
}
pub fn clone_with_id(&self, new_id: MuID) -> MuEntityHeader {
......
......@@ -11,8 +11,8 @@
// 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.
#[derive(Copy, Clone, Debug, PartialEq)]
use std::fmt;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum BinOp {
// BinOp Int(n) Int(n) -> Int(n)
Add,
......@@ -38,6 +38,11 @@ pub enum BinOp {
FDiv,
FRem
}
impl fmt::Display for BinOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", format!("{:?}", self).to_uppercase())
}
}
impl BinOp {
pub fn is_fp(self) -> bool {
......@@ -80,6 +85,11 @@ pub enum CmpOp {
FUNE,
FUNO
}
impl fmt::Display for CmpOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl CmpOp {
/// returns the CmpOp X for CmpOp Y, such that (a Y b) is equivalent to (b X a)
......@@ -225,6 +235,11 @@ pub enum ConvOp {
REFCAST,
PTRCAST
}
impl fmt::Display for ConvOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AtomicRMWOp {
......@@ -240,3 +255,9 @@ pub enum AtomicRMWOp {
UMAX,
UMIN
}
impl fmt::Display for AtomicRMWOp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
......@@ -390,6 +390,14 @@ impl MuType {
}
}
/// gets the signature of a funcref or ufuncptr type
pub fn get_sig(&self) -> Option<P<MuFuncSig>> {
match self.v {
MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig)=> Some(sig.clone()),
_ => None
}
}
/// gets a field's type of a struct type,
/// returns None if the type is not a struct or hybrid type
pub fn get_field_ty(&self, index: usize) -> Option<P<MuType>> {
......@@ -540,9 +548,9 @@ impl fmt::Display for MuType_ {
&MuType_::Tagref64 => write!(f, "tagref64"),
&MuType_::Vector(ref ty, size) => write!(f, "vector<{} {}>", ty, size),
&MuType_::FuncRef(ref sig) => write!(f, "funcref<{}>", sig),
&MuType_::UFuncPtr(ref sig) => write!(f, "ufuncref<{}>", sig),
&MuType_::Struct(ref tag) => write!(f, "{}(struct)", tag),
&MuType_::Hybrid(ref tag) => write!(f, "{}(hybrid)", tag)
&MuType_::UFuncPtr(ref sig) => write!(f, "ufuncptr<{}>", sig),
&MuType_::Struct(ref tag) => write!(f, "{}", tag),
&MuType_::Hybrid(ref tag) => write!(f, "{}", tag)
}
}
}
......@@ -643,7 +651,7 @@ impl fmt::Display for HybridType_ {
write!(f, " ").unwrap();
}
}
write!(f, "|{}>", self.var_ty)
write!(f, " {}>", self.var_ty)
}
}
......@@ -820,8 +828,8 @@ rodal_struct!(MuFuncSig{hdr, ret_tys, arg_tys});
impl fmt::Display for MuFuncSig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}] -> [{}]",
vec_utils::as_str(&self.arg_tys), vec_utils::as_str(&self.ret_tys))
write!(f, "({})->({})",
vec_utils::as_str_sp(&self.arg_tys), vec_utils::as_str_sp(&self.ret_tys))
}
}
......
......@@ -37,6 +37,7 @@ use std::usize;
use std::ops;
use std::collections::HashSet;
use std::sync::RwLock;
use compiler::backend::code_emission::{emit_mu_types, emit_mu_globals};
macro_rules! trace_emit {
($arg1:tt $($arg:tt)*) => {
......@@ -3644,6 +3645,9 @@ pub fn emit_context_with_reloc(
use std::path;
use std::io::prelude::*;
emit_mu_types("", vm);
emit_mu_globals("", vm);
debug!("---Emit VM Context---");
create_emit_directory(vm);
......
......@@ -145,7 +145,7 @@ impl<'a> InstructionSelection {
self.process_dest(&ops, fallthrough_dest, f_content, f_context, vm);
self.process_dest(&ops, branch_dest, f_content, f_context, vm);
let branch_target = f_content.get_block(branch_dest.target).name();
let branch_target = f_content.get_block(branch_dest.target.id()).name();
let ref cond = ops[cond];
......@@ -311,7 +311,7 @@ impl<'a> InstructionSelection {
self.process_dest(&ops, dest, f_content, f_context, vm);
let target = f_content.get_block(dest.target).name();
let target = f_content.get_block(dest.target.id()).name();
trace!("emit branch1");
// jmp
......@@ -339,7 +339,7 @@ impl<'a> InstructionSelection {
// process dest
self.process_dest(&ops, case_dest, f_content, f_context, vm);
let target = f_content.get_block(case_dest.target).name();
let target = f_content.get_block(case_dest.target.id()).name();
let mut imm_val = 0 as u64;
// Is one of the arguments a valid immediate?
......@@ -375,7 +375,7 @@ impl<'a> InstructionSelection {
// emit default
self.process_dest(&ops, default, f_content, f_context, vm);
let default_target = f_content.get_block(default.target).name();
let default_target = f_content.get_block(default.target.id()).name();
self.backend.emit_b(default_target);
} else {
panic!("expecting cond in switch to be ireg: {}", cond);
......@@ -4687,7 +4687,7 @@ impl<'a> InstructionSelection {
f_content: &FunctionContent
) -> Option<MuName> {
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
let target_id = resumption.unwrap().exn_dest.target.id();
Some(f_content.get_block(target_id).name())
} else {
None
......@@ -4700,13 +4700,13 @@ impl<'a> InstructionSelection {
callsite: ValueLocation,
stack_arg_size: usize
) {
let target_block = match resumption {
Some(rd) => rd.exn_dest.target,
let target_block_id = match resumption {
Some(rd) => rd.exn_dest.target.id(),
None => 0
};
self.current_callsites
.push_back((callsite.to_relocatable(), target_block, stack_arg_size));
.push_back((callsite.to_relocatable(), target_block_id, stack_arg_size));
}
fn emit_mu_call(
......@@ -4853,9 +4853,7 @@ impl<'a> InstructionSelection {
);
if resumption.is_some() {
let ref normal_dest = resumption.as_ref().unwrap().normal_dest;
let normal_target_name = f_content.get_block(normal_dest.target).name();
self.backend.emit_b(normal_target_name);
self.backend.emit_b(resumption.as_ref().unwrap().normal_dest.target.name());
}
}
}
......@@ -4890,7 +4888,7 @@ impl<'a> InstructionSelection {
// }
//
let ref target_args = f_content
.get_block(dest.target)
.get_block(dest.target.id())
.content
.as_ref()
.unwrap()
......@@ -5832,8 +5830,8 @@ impl<'a> InstructionSelection {
fn node_funcref_const_to_id(&mut self, op: &TreeNode) -> MuID {
match op.v {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::Constant(Constant::FuncRef(id)) => id,
match &pv.v {
&Value_::Constant(Constant::FuncRef(ref hdr)) => hdr.id(),
_ => panic!("expected a funcref const")
}
}
......
......@@ -2061,11 +2061,11 @@ pub fn emit_ireg_value(
tmp
}
&Constant::FuncRef(func_id) => {
&Constant::FuncRef(ref func) => {
let tmp = make_temporary(f_context, pv.ty.clone(), vm);
let mem =
make_value_symbolic(vm.get_name_for_func(func_id), true, &ADDRESS_TYPE, vm);
make_value_symbolic(vm.get_name_for_func(func.id()), true, &ADDRESS_TYPE, vm);
emit_calculate_address(backend, &tmp, &mem, vm);
tmp
}
......@@ -2746,7 +2746,7 @@ fn emit_move_value_to_value(
emit_mov_u64(backend, dest, imm);
} else if src.is_func_const() {
let func_id = match src.v {
Value_::Constant(Constant::FuncRef(id)) => id,
Value_::Constant(Constant::FuncRef(ref func)) => func.id(),
_ => unreachable!()
};
let mem =
......
......@@ -4143,7 +4143,7 @@ pub fn emit_sym_table(vm: &VM) {
use std::collections::HashMap;
use compiler::backend::code_emission::emit_mu_types;
use compiler::backend::code_emission::{emit_mu_types, emit_mu_globals};
/// emit vm context for current session, considering relocation symbols/fields from the client
pub fn emit_context_with_reloc(
......@@ -4155,6 +4155,7 @@ pub fn emit_context_with_reloc(
use std::io::prelude::*;
emit_mu_types("", vm);
emit_mu_globals("", vm);
// creates emit directy, and file
debug!("---Emit VM Context---");
......
......@@ -231,7 +231,7 @@ impl<'a> InstructionSelection {
self.process_dest(&ops, fallthrough_dest, f_content, f_context, vm);
self.process_dest(&ops, branch_dest, f_content, f_context, vm);
let branch_target = f_content.get_block(branch_dest.target).name();
let branch_target = f_content.get_block(branch_dest.target.id()).name();
let ref cond = ops[cond];
if self.match_cmp_res(cond) {
......@@ -539,7 +539,7 @@ impl<'a> InstructionSelection {
self.process_dest(&ops, dest, f_content, f_context, vm);
let target = f_content.get_block(dest.target).name();
let target = f_content.get_block(dest.target.id()).name();
// jmp
self.backend.emit_jmp(target);
}
......@@ -567,7 +567,7 @@ impl<'a> InstructionSelection {
// process dest
self.process_dest(&ops, case_dest, f_content, f_context, vm);
let target = f_content.get_block(case_dest.target).name();
let target = f_content.get_block(case_dest.target.id()).name();
if self.match_iimm(case_op) {
let imm = self.node_iimm_to_i32(case_op);
......@@ -602,7 +602,7 @@ impl<'a> InstructionSelection {
// emit default
self.process_dest(&ops, default, f_content, f_context, vm);
let default_target = f_content.get_block(default.target).name();
let default_target = f_content.get_block(default.target.id()).name();
self.backend.emit_jmp(default_target);
} else {
// other EQ-comparable types, e.g. floating point
......@@ -4473,7 +4473,7 @@ impl<'a> InstructionSelection {
// check if this call has exception clause - need to tell backend about this
let potentially_excepting = {
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
let target_id = resumption.unwrap().exn_dest.target.id();
Some(f_content.get_block(target_id).name())
} else {
None
......@@ -4531,10 +4531,10 @@ impl<'a> InstructionSelection {
if resumption.is_some() {
// record exception branch
let ref exn_dest = resumption.as_ref().unwrap().exn_dest;
let target_block = exn_dest.target;
let target_block_id = exn_dest.target.id();
self.current_callsites
.push_back((callsite.to_relocatable(), target_block, stack_arg_size));
.push_back((callsite.to_relocatable(), target_block_id, stack_arg_size));
// insert an intermediate block to branch to normal
// the branch is inserted later (because we need to deal with postcall convention)
......@@ -4558,10 +4558,7 @@ impl<'a> InstructionSelection {
// jump to target block
if resumption.is_some() {
let ref normal_dest = resumption.as_ref().unwrap().normal_dest;
let normal_target_name = f_content.get_block(normal_dest.target).name();
self.backend.emit_jmp(normal_target_name);
self.backend.emit_jmp(resumption.as_ref().unwrap().normal_dest.target.name());
}
}
......@@ -4713,7 +4710,7 @@ impl<'a> InstructionSelection {
// arguments are ready, we are starting continuation
let potential_exception_dest = match resumption {
Some(ref resumption) => {
let target_id = resumption.exn_dest.target;
let target_id = resumption.exn_dest.target.id();
Some(f_content.get_block(target_id).name())
}
None => None
......@@ -4763,7 +4760,7 @@ impl<'a> InstructionSelection {
if !is_kill {
// record this callsite
let target_block_id = match resumption {
Some(resumption) => resumption.exn_dest.target,
Some(resumption) => resumption.exn_dest.target.id(),
None => 0
};
self.current_callsites
......@@ -4868,7 +4865,7 @@ impl<'a> InstructionSelection {
&DestArg::Normal(op_index) => {
let ref arg = ops[op_index];
let ref target_args = f_content
.get_block(dest.target)
.get_block(dest.target.id())
.content
.as_ref()
.unwrap()
......@@ -5399,18 +5396,18 @@ impl<'a> InstructionSelection {
self.backend.emit_mov_r64_imm64(&tmp_h, vals[1] as i64);
}
// a function reference, loads the funcref to a temporary
&Constant::FuncRef(func_id) => {
&Constant::FuncRef(ref func) => {
// our code for linux has one more level of indirection
// so we need a load for linux
// sel4-rumprun is the same as Linux here
if cfg!(feature = "sel4-rumprun") {
let mem = self.get_mem_for_funcref(func_id, vm);
let mem = self.get_mem_for_funcref(func.id(), vm);
self.backend.emit_mov_r_mem(&tmp, &mem);
} else if cfg!(target_os = "macos") {
let mem = self.get_mem_for_funcref(func_id, vm);
let mem = self.get_mem_for_funcref(func.id(), vm);
self.backend.emit_lea_r64(&tmp, &mem);
} else if cfg!(target_os = "linux") {
let mem = self.get_mem_for_funcref(func_id, vm);
let mem = self.get_mem_for_funcref(func.id(), vm);
self.backend.emit_mov_r_mem(&tmp, &mem);
} else {
unimplemented!()
......@@ -6220,8 +6217,8 @@ impl<'a> InstructionSelection {
fn node_funcref_const_to_id(&mut self, op: &TreeNode) -> MuID {
match op.v {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::Constant(Constant::FuncRef(id)) => id,
match &pv.v {
&Value_::Constant(Constant::FuncRef(ref hdr)) => hdr.id(),
_ => panic!("expected a funcref const")
}
}
......
......@@ -96,7 +96,7 @@ pub fn emit_mu_types(suffix: &str, vm: &VM) {
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push("___types".to_string() + suffix + ".muty");
file_path.push("___types".to_string() + suffix + ".uir");
let mut file = match File::create(file_path.as_path()) {
Err(why) => {
panic!(
......@@ -117,20 +117,20 @@ pub fn emit_mu_types(suffix: &str, vm: &VM) {
for ty in ty_guard.values() {
if ty.is_struct() {
write!(file, "{}", ty).unwrap();
write!(file, ".typedef {} = ", ty.hdr).unwrap();
let struct_ty = struct_map
.get(&ty.get_struct_hybrid_tag().unwrap())
.unwrap();
writeln!(file, " -> {}", struct_ty).unwrap();
writeln!(file, " {}", vm.get_backend_type_info(ty.id())).unwrap();
writeln!(file, "{}", struct_ty).unwrap();
writeln!(file, "\n\t/*{}*/", vm.get_backend_type_info(ty.id())).unwrap();
} else if ty.is_hybrid() {
write!(file, "{}", ty).unwrap();
let hybrid_ty = hybrid_map
.get(&ty.get_struct_hybrid_tag().unwrap())
.unwrap();
writeln!(file, " -> {}", hybrid_ty).unwrap();
writeln!(file, " {}", vm.get_backend_type_info(ty.id())).unwrap();
writeln!(file, "{}", hybrid_ty).unwrap();
writeln!(file, "\n\t/*{}*/", vm.get_backend_type_info(ty.id())).unwrap();
} else {
// we only care about struct
}
......@@ -141,6 +141,33 @@ pub fn emit_mu_types(suffix: &str, vm: &VM) {
}
}
pub fn emit_mu_globals(suffix: &str, vm: &VM) {
if EMIT_MUIR {
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push("___globals".to_string() + suffix + ".uir");
let mut file = match File::create(file_path.as_path()) {
Err(why) => {
panic!(
"couldn't create mu globals file {}: {}",
file_path.to_str().unwrap(),
why
)
}
Ok(file) => file
};
let global_guard = vm.globals().read().unwrap();
for g in global_guard.values() {
write!(file, ".global {}<{}>", g.name(), g.ty.get_referent_ty().unwrap()).unwrap();
}
}
}
fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
let func_name = func.name();
......
......@@ -96,6 +96,7 @@ impl CompilerPolicy {
impl Default for CompilerPolicy {
fn default() -> Self {
let mut passes: Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::UIRGen::new("")));
passes.push(Box::new(passes::DotGen::new(".orig")));
// ir level passes
......
......@@ -148,8 +148,8 @@ fn dfs(cur: MuID, stack: &mut Vec<MuID>, visited: &mut Vec<MuID>, func: &mut MuF
Branch1(ref dest) => {
vec![
BlockEdge {
target: dest.target,
kind: check_edge_kind(dest.target, stack),
target: dest.target.id(),
kind: check_edge_kind(dest.target.id(), stack),
is_exception: false,
probability: 1.0f32
},
......@@ -165,14 +165,14 @@ fn dfs(cur: MuID, stack: &mut Vec<MuID>, visited: &mut Vec<MuID>, func: &mut MuF
} => {
vec![
BlockEdge {
target: true_dest.target,
kind: check_edge_kind(true_dest.target, stack),
target: true_dest.target.id(),
kind: check_edge_kind(true_dest.target.id(), stack),