Commit a4f8045f authored by qinsoon's avatar qinsoon

Merge remote-tracking branch 'origin/develop' into open-source

parents 5145efb5 c0089a9f
Pipeline #699 passed with stages
in 28 minutes and 17 seconds
......@@ -30,21 +30,16 @@ stages:
- build
- test
build_vm:
build:
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
- time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test --release --no-run --color=always
artifacts:
paths:
- target/release/libmu.so
- target/release/libmu.a
- target/release/lib-*
before_script:
- export PATH=$PATH:/root/.cargo/bin
......@@ -56,68 +51,68 @@ before_script:
test:cargo:api:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_api 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_api 2> /dev/null
test:cargo:ir:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_ir 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_ir 2> /dev/null
test:cargo:compiler:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_compiler 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_compiler 2> /dev/null
test:cargo:runtime:
stage: test
script:
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release test_runtime 2> /dev/null
- RUST_BACKTRACE=1 RUST_TEST_THREADS=1 ./test-release --color=always test_runtime 2> /dev/null
testjit:milestones:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py -v --color=yes
testjit:binops:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_binops.py -v --color=yes
testjit:cmpops:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_cmpops.py -v --color=yes
testjit:controlflow:
stage: test
script:
- cd tests/test_jit
- RUST_BACKTRACE=1 pytest test_controlflow.py -v
- RUST_BACKTRACE=1 pytest test_controlflow.py -v --color=yes
testjit:convops:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_convops.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_convops.py -v --color=yes
testjit:double:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_double.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_double.py -v --color=yes
testjit:memops:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_memops.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_memops.py -v --color=yes
testjit:milestones:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_milestones.py -v --color=yes
testjit:otherops:
stage: test
script:
- RUST_BACKTRACE=1 pytest tests/test_jit/test_otherops.py -v
- RUST_BACKTRACE=1 pytest tests/test_jit/test_otherops.py -v --color=yes
testjit:rpython:
stage: test
......@@ -128,7 +123,7 @@ testjit:rpython:
- 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 pytest test_rpython*.py -v
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy pytest test_rpython*.py -v --color=yes
testjit:som:
stage: test
......@@ -142,4 +137,4 @@ testjit:som:
- 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
- MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy:RPySOM/src RPYSOM=RPySOM pytest test_som.py -v --color=yes
\ No newline at end of file
......@@ -34,7 +34,7 @@ gcc = "*"
ast = {path = "src/ast"}
utils = {path = "src/utils"}
gc = {path = "src/gc"}
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = "*" }
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
libc="*"
field-offset = "*"
libloading = "*"
......
......@@ -29,15 +29,29 @@ rm -rf $MU_ZEBU/tests/test_jit/emit
#cargo clean
cargo test --release --no-run --color=always 2>&1 | tee build_out.txt
$(exit ${PIPESTATUS[0]}) # this command will exit the shell but only if the above cargo test failed
/usr/bin/time -f "finished in %e secs" -a -o cargo_test_out.txt ./test-release --color=always 2>/dev/null | tee cargo_test_out.txt
cd $MU_ZEBU/tests/test_jit/mu-client-pypy
git pull
cd $MU_ZEBU/tests/test_jit/
cd $MU_ZEBU/tests/test_jit/RPySOM
git pull
if [ -d "./mu-client-pypy" ]
then
git -C ./mu-client-pypy pull
else
git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git
git -C ./mu-client-pypy checkout mu-rewrite
git -C ./mu-client-pypy apply pypy.patch
fi
cd $MU_ZEBU/tests/test_jit/
ZEBU_BUILD=release LD_LIBRARY_PATH=. PYTHONPATH=mu-client-pypy:RPySOM/src pytest test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
if [ -d "./RPySOM" ]
then
git -C ./RPySOM pull
else
git clone https://github.com/microvm/RPySOM.git
git -C ./RPySOM submodule init
git -C ./RPySOM submodule update
fi
pytest test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
......@@ -25,4 +25,4 @@ utils = {path = "../utils"}
lazy_static = "*"
log = "*"
simple_logger = "*"
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = "*" }
rodal = { git = "https://gitlab.anu.edu.au/mu/rodal", version = ">= 0.0.5" }
......@@ -835,10 +835,7 @@ pub struct CallData {
impl CallData {
fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
let func_name = match ops[self.func].name() {
Some(name) => name,
None => "Anonymous Function".to_string()
};
let func_name = ops[self.func].name();
format!("{:?} {} [{}]", self.convention, func_name, op_vector_str(&self.args, ops))
}
}
......
This diff is collapsed.
......@@ -46,7 +46,7 @@ macro_rules! impl_mu_entity {
#[inline(always)]
fn id(&self) -> MuID {self.hdr.id()}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.hdr.name()}
fn name(&self) -> MuName {self.hdr.name()}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
ref_ty as &MuEntity
......
......@@ -49,7 +49,6 @@ pub trait CodeGenerator {
// emit code to adjust frame
fn emit_frame_grow(&mut self); // Emits a SUB
fn emit_frame_shrink(&mut self); // Emits an ADD
// Used to pass a string that the assembler will interpret as an immediate argument
// (This is neccesary to support the use of ELF relocations like ':tprel_hi12:foo')
......@@ -109,7 +108,7 @@ pub trait CodeGenerator {
// branching
// calls
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>) -> ValueLocation;
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>, is_native: bool) -> ValueLocation;
fn emit_blr(&mut self, callsite: String, func: Reg, pe: Option<MuName>) -> ValueLocation;
// Branches
......
......@@ -794,8 +794,8 @@ pub fn get_return_address(frame_pointer: Address) -> Address {
// Gets the stack pointer before the current frame was created
#[inline(always)]
pub fn get_previous_stack_pointer(frame_pointer: Address) -> Address {
frame_pointer + 16 as ByteSize
pub fn get_previous_stack_pointer(frame_pointer: Address, stack_arg_size: usize) -> Address {
frame_pointer + 16 as ByteSize + stack_arg_size
}
#[inline(always)]
......@@ -2179,7 +2179,7 @@ pub fn emit_addr_sym(backend: &mut CodeGenerator, dest: &P<Value>, src: &P<Value
match src.v {
Value_::Memory(ref mem) => {
match mem {
&MemoryLocation::Symbolic{ref label, is_global} => {
&MemoryLocation::Symbolic{ref label, is_global, is_native} => {
if is_global {
// Set dest to be the page address of the entry for src in the GOT
backend.emit_adrp(&dest, &src);
......@@ -2189,7 +2189,12 @@ pub fn emit_addr_sym(backend: &mut CodeGenerator, dest: &P<Value>, src: &P<Value
let offset = P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: UINT64_TYPE.clone(),
v: Value_::Constant(Constant::ExternSym(format!(":got_lo12:{}", label)))
v: Value_::Constant(Constant::ExternSym(
if is_native {
format!("/*C*/:got_lo12:{}", label)
} else {
format!(":got_lo12:{}", mangle_name(label.clone()))
}))
});
// [dest + low 12 bits of the GOT entry for src]
......@@ -2451,7 +2456,8 @@ fn make_value_symbolic(label: MuName, global: bool, ty: &P<MuType>, vm: &VM) ->
ty : ty.clone(),
v : Value_::Memory(MemoryLocation::Symbolic {
label: label,
is_global: global
is_global: global,
is_native: false,
})
})
}
......
......@@ -54,8 +54,7 @@ pub trait CodeGenerator {
// emit code to adjust frame size
fn emit_frame_grow(&mut self);
fn emit_frame_shrink(&mut self);
fn emit_nop(&mut self, bytes: usize);
// comparison
......@@ -221,7 +220,7 @@ pub trait CodeGenerator {
fn emit_js(&mut self, dest: MuName);
// call
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName, pe: Option<MuName>) -> ValueLocation;
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName, pe: Option<MuName>, is_native: bool) -> ValueLocation;
fn emit_call_near_r64 (&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation;
fn emit_call_near_mem64(&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation;
......
......@@ -532,8 +532,8 @@ pub fn get_return_address(frame_pointer: Address) -> Address {
/// gets the stack pointer before the current frame was created
#[inline(always)]
pub fn get_previous_stack_pointer(frame_pointer: Address) -> Address {
frame_pointer + 16 as ByteSize
pub fn get_previous_stack_pointer(frame_pointer: Address, stack_arg_size: usize) -> Address {
frame_pointer + 16 as ByteSize + stack_arg_size
}
/// sets the stack point
......
This diff is collapsed.
......@@ -30,7 +30,7 @@ use runtime::mm::common::gctype::{GCType, GCTYPE_INIT_ID, RefPattern};
/// for ahead-of-time compilation (boot image making), the file contains a persisted VM, a persisted
/// heap, constants. This allows the VM to resume execution with the same status as before persisting.
#[cfg(feature = "aot")]
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.S";
/// name for prologue (this is not full name, but prologue name is generated from this)
pub const PROLOGUE_BLOCK_NAME: &'static str = "prologue";
......@@ -498,3 +498,7 @@ impl RegGroup {
RegGroup::get_from_ty(&val.ty)
}
}
fn make_block_name(fv_name: &String, id: MuID, label: &str) -> MuName {
format!("{}.#{}:{}", fv_name, id, label)
}
\ No newline at end of file
......@@ -18,6 +18,9 @@ use compiler::frame::*;
use runtime::ValueLocation;
use rodal;
use utils::Address;
use std::sync::Arc;
use runtime::resolve_symbol;
use std::ops;
use std::collections::HashMap;
use std::collections::HashSet;
......@@ -101,6 +104,27 @@ impl CompiledFunction {
}
}
// Contains information about a callsite (needed for exception handling)
pub struct CompiledCallsite {
pub exceptional_destination: Option<Address>,
pub stack_args_size: usize,
pub callee_saved_registers: Arc<HashMap<isize, isize>>,
pub function_version: MuID
}
impl CompiledCallsite {
pub fn new(callsite: &Callsite, fv: MuID, callee_saved_registers: Arc<HashMap<isize, isize>>) -> CompiledCallsite {
CompiledCallsite {
exceptional_destination: match &callsite.exception_destination {
&Some(ref name) => Some(resolve_symbol(name.clone())),
&None => None
},
stack_args_size: callsite.stack_arg_size,
callee_saved_registers: callee_saved_registers,
function_version: fv,
}
}
}
use std::any::Any;
/// MachineCode allows the compiler manipulate machine code in a target independent way
......
......@@ -91,6 +91,7 @@ impl CompilerPolicy {
impl Default for CompilerPolicy {
fn default() -> Self {
let mut passes : Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::DotGen::new(".orig")));
passes.push(Box::new(passes::Inlining::new()));
// ir level passes
passes.push(Box::new(passes::DefUse::new()));
......@@ -98,6 +99,7 @@ impl Default for CompilerPolicy {
passes.push(Box::new(passes::GenMovPhi::new()));
passes.push(Box::new(passes::ControlFlowAnalysis::new()));
passes.push(Box::new(passes::TraceGen::new()));
passes.push(Box::new(passes::DotGen::new(".transformed")));
// compilation
passes.push(Box::new(backend::inst_sel::InstructionSelection::new()));
......
// 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.
#![allow(dead_code)]
use compiler::CompilerPass;
use ast::ir::*;
use vm::VM;
use std::any::Any;
use std::path;
use std::io::prelude::*;
use std::fs::File;
pub const EMIT_MUIR : bool = true;
pub fn create_emit_directory(vm: &VM) {
use std::fs;
match fs::create_dir(&vm.vm_options.flag_aot_emit_dir) {
Ok(_) => {},
Err(_) => {}
}
}
fn create_emit_file(name: String, vm: &VM) -> File {
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(name);
match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create emit file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
}
}
pub struct DotGen {
name: &'static str,
suffix: &'static str,
}
impl DotGen {
pub fn new(suffix: &'static str) -> DotGen {
DotGen {
name: "DotGen",
suffix: suffix,
}
}
}
#[allow(dead_code)]
fn emit_muir(suffix: &str, func: &MuFunctionVersion, vm: &VM) {
let func_name = func.name();
// create emit directory
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(func_name.clone() + suffix + ".muir");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create muir file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
};
write!(file, "{:?}", func).unwrap();
}
fn emit_muir_dot(suffix: &str, func: &MuFunctionVersion, vm: &VM) {
let func_name = func.name();
// create emit directory
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(func_name.clone() + suffix + ".dot");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldnt create muir dot {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
};
emit_muir_dot_inner(&mut file, func_name.clone(), func.content.as_ref().unwrap());
}
fn emit_muir_dot_inner(file: &mut File,
f_name: String,
f_content: &FunctionContent) {
use utils::vec_utils;
// digraph func {
writeln!(file, "digraph {} {{", mangle_name(f_name)).unwrap();
// node shape: rect
writeln!(file, "node [shape=rect];").unwrap();
// every graph node (basic block)
for (id, block) in f_content.blocks.iter() {
let block_name = block.name();
// BBid [label = "name
write!(file, "BB{} [label = \"[{}]{} ", *id, *id, &block_name).unwrap();
let block_content = block.content.as_ref().unwrap();
// (args)
write!(file, "{}", vec_utils::as_str(&block_content.args)).unwrap();
if block_content.exn_arg.is_some() {
// [exc_arg]
write!(file, "[{}]", block_content.exn_arg.as_ref().unwrap()).unwrap();
}
write!(file, ":\\l\\l").unwrap();
// all the instructions
for inst in block_content.body.iter() {
write!(file, "{}\\l", inst).unwrap();
}
// "];
writeln!(file, "\"];").unwrap();
}
// every edge
for (id, block) in f_content.blocks.iter() {
use ast::inst::Instruction_::*;
let cur_block = *id;
// get last instruction
let last_inst = block.content.as_ref().unwrap().body.last().unwrap();
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let ref ops = inst.ops;
match inst.v {
Branch1(ref dest) => {
writeln!(file, "BB{} -> BB{} [label = \"{}\"];",
cur_block, dest.target, vec_utils::as_str(&dest.get_arguments(&ops))
).unwrap();
}
Branch2{ref true_dest, ref false_dest, ..} => {
writeln!(file, "BB{} -> BB{} [label = \"true: {}\"]",
cur_block, true_dest.target, vec_utils::as_str(&true_dest.get_arguments(&ops))
).unwrap();
writeln!(file, "BB{} -> BB{} [label = \"false: {}\"]",
cur_block, false_dest.target, vec_utils::as_str(&false_dest.get_arguments(&ops))
).unwrap();
}
Switch{ref default, ref branches, ..} => {
for &(op, ref dest) in branches.iter() {
writeln!(file, "BB{} -> BB{} [label = \"case {}: {}\"]",
cur_block, dest.target, ops[op], vec_utils::as_str(&dest.get_arguments(&ops))
).unwrap();
}
writeln!(file, "BB{} -> BB{} [label = \"default: {}\"]",
cur_block, default.target, vec_utils::as_str(&default.get_arguments(&ops))
).unwrap();
}
Call{ref resume, ..}
| CCall{ref resume, ..}
| SwapStack{ref resume, ..}
| ExnInstruction{ref resume, ..} => {
let ref normal = resume.normal_dest;
let ref exn = resume.exn_dest;
writeln!(file, "BB{} -> BB{} [label = \"normal: {}\"];",
cur_block, normal.target, vec_utils::as_str(&normal.get_arguments(&ops))
).unwrap();
writeln!(file, "BB{} -> BB{} [label = \"exception: {}\"];",
cur_block, exn.target, vec_utils::as_str(&exn.get_arguments(&ops))
).unwrap();
}
Watchpoint{ref id, ref disable_dest, ref resume, ..} if id.is_some() => {
let ref normal = resume.normal_dest;
let ref exn = resume.exn_dest;
if id.is_some() {
let disable_dest = disable_dest.as_ref().unwrap();
writeln!(file, "BB{} -> {} [label = \"disabled: {}\"];",
cur_block, disable_dest.target, vec_utils::as_str(&disable_dest.get_arguments(&ops))
).unwrap();
}
writeln!(file, "BB{} -> BB{} [label = \"normal: {}\"];",
cur_block, normal.target, vec_utils::as_str(&normal.get_arguments(&ops))
).unwrap();
writeln!(file, "BB{} -> BB{} [label = \"exception: {}\"];",
cur_block, exn.target, vec_utils::as_str(&exn.get_arguments(&ops))
).unwrap();
}
WPBranch{ref disable_dest, ref enable_dest, ..} => {
writeln!(file, "BB{} -> BB{} [label = \"disabled: {}\"];",
cur_block, disable_dest.target, vec_utils::as_str(&disable_dest.get_arguments(&ops))
).unwrap();
writeln!(file, "BB{} -> BB{} [label = \"enabled: {}\"];",
cur_block, enable_dest.target, vec_utils::as_str(&enable_dest.get_arguments(&ops))
).unwrap();
}
Return(_)
| Throw(_)
| ThreadExit
| TailCall(_) => {}
_ => {
panic!("unexpected terminating instruction: {}", inst);
}
}
},
TreeNode_::Value(_) => {
panic!("expected last tree node to be an instruction");
}
}
}
writeln!(file, "}}").unwrap();
}
impl CompilerPass for DotGen {
fn name(&self) -> &'static str {
self.name
}
fn as_any(&self) -> &Any {
self
}
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
if EMIT_MUIR {
emit_muir_dot(self.suffix, func, vm);
}
}
}
......@@ -32,6 +32,7 @@ impl GenMovPhi {
struct IntermediateBlockInfo {
blk_id: MuID,
blk_name: MuName,
target: MuID,
from_args : Vec<P<TreeNode>>
}
......@@ -76,12 +77,12 @@ impl CompilerPass for GenMovPhi {
match last_inst.v {
TreeNode_::Instruction(inst) => {
let ref ops = inst.ops;
let inst_name = inst.name().clone();
match inst.v {
Instruction_::Branch2{cond, true_dest, false_dest, true_prob} => {
// check and insert intermediate blocks for true/false dest
let true_dest = process_dest(true_dest, &mut new_blocks_to_insert, &ops, vm);
let false_dest = process_dest(false_dest, &mut new_blocks_to_insert, &ops, vm);
let true_dest = process_dest(true_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "true");
let false_dest = process_dest(false_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "false");
// rewrite the instruction
let new_inst = func.new_inst(Instruction{
......@@ -100,8 +101,8 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
}
Instruction_::Call{data, resume} => {
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm);
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm);
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "norm");
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "exc");
let new_inst = func.new_inst(Instruction{
hdr: inst.hdr.clone(),
......@@ -120,8 +121,8 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
}
Instruction_::CCall{data, resume} => {
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm);
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm);
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "norm");
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "exc");
let new_inst = func.new_inst(Instruction{
hdr: inst.hdr.clone(),
......@@ -140,10 +141,10 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
},
Instruction_::Switch{cond, default, mut branches} => {
let default_dest = process_dest(default, &mut new_blocks_to_insert, &ops, vm);
let default_dest = process_dest(default, &mut new_blocks_to_insert, &ops, vm, &inst_name, "default");
let new_branches = branches.drain(..).map(|pair| {
let dest = process_dest(pair.1, &mut new_blocks_to_insert, &ops, vm);
let dest = process_dest(pair.1, &mut new_blocks_to_insert, &ops, vm, &inst_name, format!("case_{}", pair.0).as_str());
(pair.0, dest)
}).collect();
......@@ -199,9 +200,7 @@ impl CompilerPass for GenMovPhi {
// create intermediate block
let block = {
let target_id = block_info.target;
let name = format!("intermediate_block_{}_to_{}", block_info.blk_id, target_id);
let mut ret = Block::new(MuEntityHeader::named(block_info.blk_id, name));
let mut ret = Block::new(MuEntityHeader::named(block_info.blk_id, block_info.blk_name.clone()));
vm.set_name(ret.as_entity());
let mut target_block = f_content.get_block_mut(target_id);
......@@ -267,7 +266,7 @@ impl CompilerPass for GenMovPhi {
/// we need an intermediate block to move the arguments, return
/// the intermediate block as destination. Otherwise, return
/// the original destination
fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockInfo>, ops: &Vec<P<TreeNode>>, vm: &VM) -> Destination {
fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockInfo>, ops: &Vec<P<TreeNode>>, vm: &VM, inst: &MuName, label: &str) -> Destination {
if dest.args.is_empty() {
dest
} else {
......@@ -292,6 +291,7 @@ fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockI
blocks_to_insert.push(IntermediateBlockInfo {
blk_id: new_blk_id,
blk_name: format!("{}:{}:#{}-#{}", inst, label, new_blk_id, target),
target: target,
from_args: from_args
});
......