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.

244 lines
6.3 KiB

use super::context::Context;
use super::defuse::{Useable, User};
use super::function::Function;
use super::instruction::Instruction;
use super::typ::Typ;
use crate::utils::storage::{Arena, ArenaPtr, GenericPtr};
use rustc_hash::FxHashSet as HashSet;
#[derive(Debug, Clone)]
pub enum ConstantValue {
Undef {
typ: Typ,
},
Zero {
typ: Typ,
},
Int32 {
typ: Typ,
value: i32,
},
GlobalPtr {
typ: Typ, // 全局指针类型
name: String, // 全局变量的名
value_type: Typ, // 指针指向数据的类型
},
}
impl ConstantValue {
//常量值的类型
pub fn typ(&self) -> Typ {
match self {
ConstantValue::Undef { typ } => *typ,
ConstantValue::Zero { typ, .. } => *typ,
ConstantValue::Int32 { typ, .. } => *typ,
ConstantValue::GlobalPtr { value_type, .. } => *value_type,
}
}
pub fn undef(typ: Typ) -> ConstantValue {
ConstantValue::Undef { typ }
}
pub fn is_undef(&self) -> bool {
matches!(self, ConstantValue::Undef { .. })
}
/// 创建zero类型
pub fn zero(typ: Typ) -> ConstantValue {
ConstantValue::Zero { typ }
}
/// 判断是不是zero类型
pub fn is_zero(&self) -> bool {
matches!(self, ConstantValue::Zero { .. })
}
pub fn int32(ctx: &mut Context, value: i32) -> ConstantValue {
let int32 = Typ::int32(ctx);
ConstantValue::Int32 { typ: int32, value }
}
pub fn global_ptr(ctx: &mut Context, name: String, value_type: Typ) -> ConstantValue {
let global_ptr = Typ::ptr(ctx, value_type.clone());
ConstantValue::GlobalPtr {
typ: global_ptr,
name,
value_type,
}
}
pub fn to_string(&self, _ctx: &Context) -> String {
let mut str = String::new();
match self {
ConstantValue::Undef { typ: _ } => str.push_str("undef"),
ConstantValue::Zero {..} => {
str.push_str("0")
}
ConstantValue::Int32 { value, .. } => str.push_str(&value.to_string()),
ConstantValue::GlobalPtr { name, .. } => {
str.push_str("@");
str.push_str(name);
}
}
str
}
}
#[derive(Debug)]
pub enum ValueKind {
// 指令的运算结果
InstResult {
instruction: Instruction,
typ: Typ,
},
// 函数参数
Parameter {
function: Function,
index: u32,
typ: Typ,
},
// 常量值
Constant {
value: ConstantValue,
},
}
#[derive(Debug)]
pub struct ValueData {
// 值类型的种类
pub kind: ValueKind,
pub users: HashSet<User<Value>>,
self_ptr: Value,
}
impl ValueData {
pub fn get_self_ptr(&self) -> Value {
self.self_ptr
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, Copy, PartialOrd)]
pub struct Value(pub GenericPtr<ValueData>);
impl ArenaPtr for Value {
type Arena = Context;
type Data = ValueData;
}
impl Value {
pub fn new(ctx: &mut Context, kind: ValueKind) -> Self {
ctx.alloc_with(|self_ptr| ValueData {
self_ptr: self_ptr,
kind,
users: HashSet::default(),
})
}
// InstResult类型的值获取指令
pub fn get_instruction(self, ctx: &Context) -> Option<Instruction> {
match self.deref(ctx).unwrap().kind {
ValueKind::InstResult { instruction, .. } => Some(instruction),
_ => None,
}
}
// 获取值类型
pub fn kind(&self, ctx: &Context) -> Typ {
match self
.deref(ctx)
.expect("Failed to deref `Value` in Value::kind()")
.kind
{
ValueKind::InstResult { typ, .. } => typ,
ValueKind::Parameter { typ, .. } => typ,
ValueKind::Constant { ref value, .. } => value.typ(),
}
}
pub fn parameter(ctx: &mut Context, function: Function, index: u32, typ: Typ) -> Self {
Self::new(
ctx,
ValueKind::Parameter {
function: function,
index,
typ,
},
)
}
pub fn is_parameter(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_parameter` in Value")
.kind,
ValueKind::Parameter { .. }
)
}
pub fn inst_result(ctx: &mut Context, instruction: Instruction, typ: Typ) -> Self {
let value = Self::new(
ctx,
ValueKind::InstResult {
instruction: instruction,
typ,
},
);
value
}
pub fn constant(ctx: &mut Context, value: ConstantValue) -> Self {
Self::new(ctx, ValueKind::Constant { value })
}
pub fn is_constant(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_constant` in Value")
.kind,
ValueKind::Constant { .. }
)
}
pub fn global_ptr(ctx: &mut Context, name: String, value_type: Typ) -> Self {
let t = ConstantValue::global_ptr(ctx, name, value_type);
let t = Self::new(ctx, ValueKind::Constant { value: t });
t
}
pub fn is_global_ptr(&self, ctx: &Context) -> bool {
matches!(
self.deref(ctx)
.expect("Failed to deref `is_global_ptr` in Value")
.kind,
ValueKind::Constant {
value: ConstantValue::GlobalPtr { .. }
}
)
}
}
impl Useable for Value {
fn users(self, arena: &Self::Arena) -> impl IntoIterator<Item = User<Self>> {
self.deref(arena)
.expect("Failed to deref `users` in struct Context")
.users
.iter()
.copied()
}
fn insert(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref mut `users` in struct Context")
.users
.insert(user);
}
fn remove(self, arena: &mut Self::Arena, user: User<Self>) {
self.deref_mut(arena)
.expect("Failed to deref mut `users` in struct Context")
.users
.remove(&user);
}
}