Commit 7fa67a5f authored by qinsoon's avatar qinsoon

detecting infinite loop when eliminating jump-to-jump. This seems to

reveal a rodal bug.
parent 8a1a2d3f
......@@ -155,12 +155,25 @@ impl PeepholeOptimization {
let orig_inst = inst;
// the destination we will rewrite the instruction to branch to
let final_dest: Option<MuName> = {
use std::collections::HashSet;
let mut cur_inst = inst;
let mut last_dest = None;
let mut visited_labels = HashSet::new();
loop {
let opt_dest = mc.is_jmp(cur_inst);
match opt_dest {
Some(ref dest) => {
// if we have already visited this instruction
// this means we met an infinite loop, we need to break
if visited_labels.contains(dest) {
warn!("met an infinite loop in removing jump-to-jump");
warn!("we are not optimizing this case");
return;
}
// get the block for destination
let first_inst = mc.get_block_range(dest).unwrap().start;
debug_assert!(
......@@ -179,6 +192,8 @@ impl PeepholeOptimization {
// its a jump-to-jump case
cur_inst = first_inst;
last_dest = Some(dest2.clone());
visited_labels.insert(dest2.clone());
debug!("visited {}", dest2);
}
None => break
}
......@@ -190,19 +205,7 @@ impl PeepholeOptimization {
};
if let Some(dest) = final_dest {
let first_inst = {
let start = mc.get_block_range(&dest).unwrap().start;
match mc.get_next_inst(start) {
Some(i) => i,
None => {
panic!(
"we are jumping to a block {}\
that does not have instructions?",
dest
)
}
}
};
let first_inst = mc.get_block_range(&dest).unwrap().start;
info!(
"inst {} chain jumps to {}, rewrite as branching to {} (successor: {})",
......
......@@ -405,7 +405,7 @@ macro_rules! inst {
target: $dest.id(),
args: {
let mut i =0;
vec![$($arg.clone()),*].iter().map(|_| {
vec![$($arg.clone()),*].iter().map(|_: &Arc<TreeNode>| {
let ret = DestArg::Normal(i); i+=1; ret
}).collect()
}
......
......@@ -30,3 +30,4 @@ mod test_inline;
mod test_convop;
mod test_int128;
mod test_misc;
mod test_opt;
\ No newline at end of file
......@@ -8,6 +8,7 @@ use self::mu::ast::inst::*;
use self::mu::vm::*;
use self::mu::linkutils;
use self::mu::utils::LinkedHashMap;
use std::sync::Arc;
#[test]
fn test_mov_minus_one_to_int8() {
......
// 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.
extern crate libloading;
use mu::ast::types::*;
use mu::ast::ir::*;
use mu::ast::ptr::*;
use mu::ast::inst::*;
use mu::ast::op::*;
use mu::vm::*;
use mu::compiler::*;
use std::sync::Arc;
use mu::linkutils;
use mu::linkutils::aot;
use mu::utils::LinkedHashMap;
#[test]
#[should_panic]
fn test_infinite_loop1() {
VM::start_logging_trace();
let vm = Arc::new(infinite_loop1());
let func_id = vm.id_of("infinite_loop1");
let func_handle = vm.handle_from_func(func_id);
let test_name = "test_infinite_loop1";
vm.make_boot_image(
vec![func_id],
Some(&func_handle),
None,
None,
vec![],
vec![],
vec![],
vec![],
test_name.to_string()
);
}
fn infinite_loop1() -> VM {
let vm = VM::new();
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> infinite_loop1);
funcdef! ((vm) <sig> infinite_loop1 VERSION infinite_loop1_v1);
// entry:
block! ((vm, infinite_loop1_v1) blk_entry);
block! ((vm, infinite_loop1_v1) blk_loop);
inst! ((vm, infinite_loop1_v1) blk_entry_branch:
BRANCH blk_loop ()
);
define_block!((vm, infinite_loop1_v1) blk_entry() {
blk_entry_branch
});
// loop
inst! ((vm, infinite_loop1_v1) blk_loop_branch:
BRANCH blk_loop ()
);
define_block!((vm, infinite_loop1_v1) blk_loop() {
blk_loop_branch
});
define_func_ver!((vm) infinite_loop1_v1 (entry: blk_entry) {
blk_entry, blk_loop
});
vm
}
#[test]
#[should_panic]
fn test_infinite_loop2() {
VM::start_logging_trace();
let vm = Arc::new(infinite_loop2());
let func_id = vm.id_of("infinite_loop2");
let func_handle = vm.handle_from_func(func_id);
let test_name = "test_infinite_loop2";
vm.make_boot_image(
vec![func_id],
Some(&func_handle),
None,
None,
vec![],
vec![],
vec![],
vec![],
test_name.to_string()
);
}
fn infinite_loop2() -> VM {
let vm = VM::new();
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> infinite_loop2);
funcdef! ((vm) <sig> infinite_loop2 VERSION infinite_loop2_v1);
// entry:
block! ((vm, infinite_loop2_v1) blk_entry);
block! ((vm, infinite_loop2_v1) blk_a);
block! ((vm, infinite_loop2_v1) blk_b);
inst! ((vm, infinite_loop2_v1) blk_entry_branch:
BRANCH blk_a ()
);
define_block!((vm, infinite_loop2_v1) blk_entry() {
blk_entry_branch
});
// blk a
inst! ((vm, infinite_loop2_v1) blk_a_branch:
BRANCH blk_b ()
);
define_block!((vm, infinite_loop2_v1) blk_a() {
blk_a_branch
});
// blk b
inst! ((vm, infinite_loop2_v1) blk_b_branch:
BRANCH blk_a ()
);
define_block!((vm, infinite_loop2_v1) blk_b() {
blk_b_branch
});
define_func_ver!((vm) infinite_loop2_v1 (entry: blk_entry) {
blk_entry, blk_a, blk_b
});
vm
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment