You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

use super::context::Context;
use super::defuse::{Useable, User};
use super::function::Function;
use super::instruction::Instruction;
use crate::utils::linked_list::{LinkedListContainer, LinkedListNode};
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr, Idx};
use rustc_hash::FxHashSet as HashSet;
pub struct BasicBlockData {
self_ptr: BasicBlock,
// 基本块的首支令和尾指令
head: Option<Instruction>,
tail: Option<Instruction>,
users: HashSet<User<BasicBlock>>,
function: Option<Function>,
// 用于LinkedListNode实现是基本块放入Function的顺序并非实际的前驱和后继关系
pre: Option<BasicBlock>,
succ: Option<BasicBlock>,
}
impl BasicBlockData {
pub fn get_self_ptr(&self) -> BasicBlock {
self.self_ptr
}
}
#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct BasicBlock(pub GenericPtr<BasicBlockData>);
impl BasicBlock {
pub fn new(ctx: &mut Context) -> Self {
ctx.alloc_with(|self_ptr| BasicBlockData {
self_ptr: self_ptr,
head: None,
tail: None,
pre: None,
succ: None,
users: HashSet::default(),
function: None,
})
}
pub fn get_name(self) -> String{
format!("bb_{}", self.0.index())
}
pub fn get_head(self, ctx: &Context) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head
}
pub fn get_tail(self, ctx: &Context) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
}
pub fn is_entry(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre
.is_none()
}
pub fn is_terminated(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
.map_or(false, |tail| tail.is_terminater(ctx))
}
pub fn is_ret(self, ctx: &Context) -> bool {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
.map_or(false, |tail| tail.is_ret(ctx))
}
pub fn get_function(self, ctx: &Context) -> Option<Function> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function
}
}
impl ArenaPtr for BasicBlock {
type Arena = Context;
type Data = BasicBlockData;
}
impl Useable for BasicBlock {
fn users(self, arena: &Self::Arena) -> impl IntoIterator<Item = User<Self>> {
self.deref(arena)
.expect("Failed to deref `basicblocks` in struct")
.users
.iter()
.copied()
}
fn insert(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref `basicblocks` in struct")
.users
.insert(user);
}
fn remove(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref `basicblocks` in struct Context")
.users
.remove(&user);
}
}
impl LinkedListContainer<Instruction> for BasicBlock {
type Ctx = Context;
fn head(self, ctx: &Self::Ctx) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head
}
fn tail(self, ctx: &Self::Ctx) -> Option<Instruction> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail
}
fn set_head(self, ctx: &mut Self::Ctx, head: Option<Instruction>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.head = head;
}
fn set_tail(self, ctx: &mut Self::Ctx, tail: Option<Instruction>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.tail = tail;
}
}
impl LinkedListNode for BasicBlock {
type Container = Function;
type Ctx = Context;
fn succ(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.succ
}
fn pre(self, ctx: &Self::Ctx) -> Option<Self> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre
}
fn container(self, ctx: &Self::Ctx) -> Option<Self::Container> {
self.deref(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function
}
fn set_succ(self, ctx: &mut Self::Ctx, succ: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.succ = succ;
}
fn set_pre(self, ctx: &mut Self::Ctx, pre: Option<Self>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.pre = pre;
}
fn set_container(self, ctx: &mut Self::Ctx, container: Option<Self::Container>) {
self.deref_mut(ctx)
.expect("Failed to deref `basicblocks` in struct Context")
.function = container;
}
fn unlink(self, ctx: &mut Self::Ctx) {
let pre = self.pre(ctx);
let succ = self.succ(ctx);
if let Some(pre) = pre {
pre.set_succ(ctx, succ);
}
if let Some(succ) = succ {
succ.set_pre(ctx, pre);
}
if let Some(container) = self.container(ctx) {
if container.head(ctx) == Some(self) {
container.set_head(ctx, succ);
}
if container.tail(ctx) == Some(self) {
container.set_tail(ctx, pre);
}
}
self.set_pre(ctx, None);
self.set_succ(ctx, None);
self.set_container(ctx, None);
}
}