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 a4f8045f authored by qinsoon's avatar qinsoon

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

parents 5145efb5 c0089a9f
......@@ -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
});
......
......@@ -216,8 +216,9 @@ impl Inlining {
// finish current block