forked from NUDT-compiler/nudt-compiler-rust
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
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);
|
|
}
|
|
}
|