Implement block/statement interference graph algorithm.
This commit is contained in:
parent
c91bb35d8d
commit
272d288213
@ -5,7 +5,6 @@ use crate::ir::ir_expression::IrExpression;
|
|||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::symbol::ExpressibleSymbol;
|
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ pub fn expression_to_ir_expression(
|
|||||||
}
|
}
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let expressible_symbol = identifier.expressible_symbol();
|
let expressible_symbol = identifier.expressible_symbol();
|
||||||
Some(IrExpression::Variable(expressible_symbol.ir_variable()))
|
Some(expressible_symbol.ir_expression())
|
||||||
}
|
}
|
||||||
Expression::Additive(additive_expression) => {
|
Expression::Additive(additive_expression) => {
|
||||||
let ir_add = additive_expression.to_ir(builder, symbol_table);
|
let ir_add = additive_expression.to_ir(builder, symbol_table);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use crate::ast::type_use::TypeUse;
|
|||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::FunctionSymbol;
|
||||||
@ -167,13 +168,13 @@ impl Function {
|
|||||||
// parameters
|
// parameters
|
||||||
for parameter in &self.parameters {
|
for parameter in &self.parameters {
|
||||||
let parameter_symbol = parameter.parameter_symbol();
|
let parameter_symbol = parameter.parameter_symbol();
|
||||||
let ir_variable = IrVariable::new(
|
let ir_parameter = IrParameter::new(
|
||||||
parameter_symbol.borrow().name(),
|
parameter_symbol.borrow().name(),
|
||||||
parameter_symbol.borrow().type_info().clone(),
|
parameter_symbol.borrow().type_info().clone(),
|
||||||
);
|
);
|
||||||
let as_rc = Rc::new(RefCell::new(ir_variable));
|
let as_rc = Rc::new(ir_parameter);
|
||||||
builder.parameters_mut().push(as_rc.clone());
|
builder.parameters_mut().push(as_rc.clone());
|
||||||
parameter_symbol.borrow_mut().set_ir_variable(as_rc);
|
parameter_symbol.borrow_mut().set_ir_parameter(as_rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry_block_id = builder.new_block();
|
let entry_block_id = builder.new_block();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::ir::ir_block::IrBlock;
|
use crate::ir::ir_block::IrBlock;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -6,7 +7,7 @@ use std::collections::HashMap;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct IrBuilder {
|
pub struct IrBuilder {
|
||||||
parameters: Vec<Rc<RefCell<IrVariable>>>,
|
parameters: Vec<Rc<IrParameter>>,
|
||||||
block_counter: usize,
|
block_counter: usize,
|
||||||
t_var_counter: usize,
|
t_var_counter: usize,
|
||||||
blocks: HashMap<usize, Rc<RefCell<IrBlock>>>,
|
blocks: HashMap<usize, Rc<RefCell<IrBlock>>>,
|
||||||
@ -24,11 +25,11 @@ impl IrBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parameters(&self) -> &[Rc<RefCell<IrVariable>>] {
|
pub fn parameters(&self) -> &[Rc<IrParameter>] {
|
||||||
&self.parameters
|
&self.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parameters_mut(&mut self) -> &mut Vec<Rc<RefCell<IrVariable>>> {
|
pub fn parameters_mut(&mut self) -> &mut Vec<Rc<IrParameter>> {
|
||||||
&mut self.parameters
|
&mut self.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +87,6 @@ impl IrBlockBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> IrBlock {
|
pub fn build(self) -> IrBlock {
|
||||||
IrBlock::new(self.id, &format!("b{}:", self.id), self.statements)
|
IrBlock::new(self.id, &format!("b{}", self.id), self.statements)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,9 +96,9 @@ impl LetStatement {
|
|||||||
Expression::String(string_literal) => {
|
Expression::String(string_literal) => {
|
||||||
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
||||||
}
|
}
|
||||||
Expression::Identifier(identifier) => IrOperation::Load(IrExpression::Variable(
|
Expression::Identifier(identifier) => {
|
||||||
identifier.expressible_symbol().ir_variable(),
|
IrOperation::Load(identifier.expressible_symbol().ir_expression())
|
||||||
)),
|
}
|
||||||
Expression::Additive(additive_expression) => {
|
Expression::Additive(additive_expression) => {
|
||||||
IrOperation::Add(additive_expression.to_ir(builder, symbol_table))
|
IrOperation::Add(additive_expression.to_ir(builder, symbol_table))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct IrAdd {
|
pub struct IrAdd {
|
||||||
left: Box<IrExpression>,
|
left: Box<IrExpression>,
|
||||||
@ -20,3 +23,12 @@ impl Display for IrAdd {
|
|||||||
write!(f, "{} + {}", self.left, self.right)
|
write!(f, "{} + {}", self.left, self.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IrAdd {
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
set.extend(self.left.uses());
|
||||||
|
set.extend(self.right.uses());
|
||||||
|
set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,25 +1,33 @@
|
|||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use std::cell::RefCell;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct IrAssign {
|
pub struct IrAssign {
|
||||||
destination: Rc<RefCell<IrVariable>>,
|
destination: Rc<IrVariable>,
|
||||||
initializer: Box<IrOperation>,
|
initializer: Box<IrOperation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrAssign {
|
impl IrAssign {
|
||||||
pub fn new(destination: IrVariable, initializer: IrOperation) -> Self {
|
pub fn new(destination: IrVariable, initializer: IrOperation) -> Self {
|
||||||
Self {
|
Self {
|
||||||
destination: Rc::new(RefCell::new(destination)),
|
destination: Rc::new(destination),
|
||||||
initializer: initializer.into(),
|
initializer: initializer.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destination(&self) -> &Rc<RefCell<IrVariable>> {
|
pub fn destination(&self) -> &Rc<IrVariable> {
|
||||||
&self.destination
|
&self.destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn initializer(&self) -> &IrOperation {
|
||||||
|
&self.initializer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
self.initializer.uses()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrAssign {
|
impl Display for IrAssign {
|
||||||
@ -27,8 +35,8 @@ impl Display for IrAssign {
|
|||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}: {} = {}",
|
"{}: {} = {}",
|
||||||
self.destination.borrow(),
|
self.destination,
|
||||||
self.destination.borrow().type_info(),
|
self.destination.type_info(),
|
||||||
self.initializer
|
self.initializer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -29,14 +31,136 @@ impl IrBlock {
|
|||||||
pub fn statements(&self) -> &[IrStatement] {
|
pub fn statements(&self) -> &[IrStatement] {
|
||||||
&self.statements
|
&self.statements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn definitions(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
for statement in &self.statements {
|
||||||
|
set.extend(statement.definitions())
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
for statement in &self.statements {
|
||||||
|
set.extend(statement.uses());
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn live_in_live_out(
|
||||||
|
&self,
|
||||||
|
) -> (
|
||||||
|
HashMap<usize, HashSet<Rc<IrVariable>>>,
|
||||||
|
HashMap<usize, HashSet<Rc<IrVariable>>>,
|
||||||
|
) {
|
||||||
|
let mut live_in: HashMap<usize, HashSet<Rc<IrVariable>>> = HashMap::new();
|
||||||
|
let mut live_out: HashMap<usize, HashSet<Rc<IrVariable>>> = HashMap::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut did_work = false;
|
||||||
|
for (statement_index, statement) in self.statements.iter().enumerate().rev() {
|
||||||
|
// init if necessary
|
||||||
|
if !live_in.contains_key(&statement_index) {
|
||||||
|
live_in.insert(statement_index, HashSet::new());
|
||||||
|
}
|
||||||
|
if !live_out.contains_key(&statement_index) {
|
||||||
|
live_out.insert(statement_index, HashSet::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
// out (union of successors ins)
|
||||||
|
// for now, a statement can only have one successor
|
||||||
|
// this will need to be updated when we add jumps
|
||||||
|
if let Some(successor_live_in) = live_in.get(&(statement_index + 1)) {
|
||||||
|
let statement_live_out = live_out.get_mut(&statement_index).unwrap();
|
||||||
|
for ir_variable in successor_live_in {
|
||||||
|
if statement_live_out.insert(ir_variable.clone()) {
|
||||||
|
did_work = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in: use(s) U ( out(s) - def(s) )
|
||||||
|
let mut new_ins = statement.uses();
|
||||||
|
let statement_live_out = live_out.get(&statement_index).unwrap();
|
||||||
|
let defs = statement.definitions();
|
||||||
|
let rhs = statement_live_out - &defs;
|
||||||
|
new_ins.extend(rhs);
|
||||||
|
|
||||||
|
let statement_live_in = live_in.get_mut(&statement_index).unwrap();
|
||||||
|
for new_in in new_ins {
|
||||||
|
if statement_live_in.insert(new_in) {
|
||||||
|
did_work = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !did_work {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(live_in, live_out)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interference_graph(&self) -> HashMap<Rc<IrVariable>, HashSet<Rc<IrVariable>>> {
|
||||||
|
let mut all_variables: HashSet<Rc<IrVariable>> = HashSet::new();
|
||||||
|
for statement in &self.statements {
|
||||||
|
all_variables.extend(statement.definitions());
|
||||||
|
all_variables.extend(statement.uses());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut graph: HashMap<Rc<IrVariable>, HashSet<Rc<IrVariable>>> = HashMap::new();
|
||||||
|
for variable in all_variables {
|
||||||
|
graph.insert(variable, HashSet::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, live_out) = self.live_in_live_out();
|
||||||
|
|
||||||
|
for (statement_index, statement) in self.statements.iter().enumerate() {
|
||||||
|
let statement_live_out = live_out.get(&statement_index).unwrap();
|
||||||
|
for definition_variable in statement.definitions() {
|
||||||
|
for live_out_variable in statement_live_out {
|
||||||
|
if definition_variable != *live_out_variable {
|
||||||
|
graph
|
||||||
|
.get_mut(&definition_variable)
|
||||||
|
.unwrap()
|
||||||
|
.insert(live_out_variable.clone());
|
||||||
|
graph
|
||||||
|
.get_mut(live_out_variable)
|
||||||
|
.unwrap()
|
||||||
|
.insert(definition_variable.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graph
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrBlock {
|
impl Display for IrBlock {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, " {}", self.debug_label)?;
|
writeln!(f, " {}:", self.debug_label)?;
|
||||||
for statement in &self.statements {
|
|
||||||
writeln!(f, " {}", statement)?;
|
let (live_in, live_out) = self.live_in_live_out();
|
||||||
|
|
||||||
|
for (statement_index, statement) in self.statements.iter().enumerate() {
|
||||||
|
let statement_live_in = live_in.get(&statement_index).unwrap();
|
||||||
|
let statement_live_out = live_out.get(&statement_index).unwrap();
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" {} // live_in: {:?}, live_out: {:?}",
|
||||||
|
statement, statement_live_in, statement_live_out
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
writeln!(f, " // ---- {} meta ----", self.debug_label)?;
|
||||||
|
writeln!(f, " // definitions: {:?}", self.definitions())?;
|
||||||
|
writeln!(f, " // uses: {:?}", self.uses())?;
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" // interference graph: {:?}",
|
||||||
|
self.interference_graph()
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -14,6 +16,14 @@ impl IrCall {
|
|||||||
arguments,
|
arguments,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
for argument in &self.arguments {
|
||||||
|
set.extend(argument.uses());
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrCall {
|
impl Display for IrCall {
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use std::cell::RefCell;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum IrExpression {
|
pub enum IrExpression {
|
||||||
Variable(Rc<RefCell<IrVariable>>),
|
Parameter(Rc<IrParameter>),
|
||||||
|
Variable(Rc<IrVariable>),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
String(Rc<str>),
|
String(Rc<str>),
|
||||||
}
|
}
|
||||||
@ -12,8 +14,11 @@ pub enum IrExpression {
|
|||||||
impl Display for IrExpression {
|
impl Display for IrExpression {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
IrExpression::Parameter(ir_parameter) => {
|
||||||
|
write!(f, "{}", ir_parameter)
|
||||||
|
}
|
||||||
IrExpression::Variable(ir_variable) => {
|
IrExpression::Variable(ir_variable) => {
|
||||||
write!(f, "{}", ir_variable.borrow())
|
write!(f, "{}", ir_variable)
|
||||||
}
|
}
|
||||||
IrExpression::Int(i) => {
|
IrExpression::Int(i) => {
|
||||||
write!(f, "{}", i)
|
write!(f, "{}", i)
|
||||||
@ -24,3 +29,24 @@ impl Display for IrExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IrExpression {
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
match self {
|
||||||
|
IrExpression::Parameter(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::Variable(ir_variable) => {
|
||||||
|
set.insert(ir_variable.clone());
|
||||||
|
}
|
||||||
|
IrExpression::Int(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::String(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::ir::ir_block::IrBlock;
|
use crate::ir::ir_block::IrBlock;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -7,7 +8,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
pub struct IrFunction {
|
pub struct IrFunction {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
parameters: Vec<Rc<RefCell<IrVariable>>>,
|
parameters: Vec<Rc<IrParameter>>,
|
||||||
return_type_info: TypeInfo,
|
return_type_info: TypeInfo,
|
||||||
entry: Rc<RefCell<IrBlock>>,
|
entry: Rc<RefCell<IrBlock>>,
|
||||||
}
|
}
|
||||||
@ -15,7 +16,7 @@ pub struct IrFunction {
|
|||||||
impl IrFunction {
|
impl IrFunction {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
parameters: &[Rc<RefCell<IrVariable>>],
|
parameters: &[Rc<IrParameter>],
|
||||||
return_type_info: TypeInfo,
|
return_type_info: TypeInfo,
|
||||||
entry: Rc<RefCell<IrBlock>>,
|
entry: Rc<RefCell<IrBlock>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -32,12 +33,7 @@ impl Display for IrFunction {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "fn {}(", self.name)?;
|
write!(f, "fn {}(", self.name)?;
|
||||||
for (i, parameter) in self.parameters.iter().enumerate() {
|
for (i, parameter) in self.parameters.iter().enumerate() {
|
||||||
write!(
|
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
||||||
f,
|
|
||||||
"{}: {}",
|
|
||||||
parameter.borrow(),
|
|
||||||
parameter.borrow().type_info()
|
|
||||||
)?;
|
|
||||||
if i < self.parameters.len() - 1 {
|
if i < self.parameters.len() - 1 {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
use crate::ir::ir_add::IrAdd;
|
use crate::ir::ir_add::IrAdd;
|
||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum IrOperation {
|
pub enum IrOperation {
|
||||||
Load(IrExpression),
|
Load(IrExpression),
|
||||||
@ -24,3 +27,13 @@ impl Display for IrOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IrOperation {
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
match self {
|
||||||
|
IrOperation::Load(ir_expression) => ir_expression.uses(),
|
||||||
|
IrOperation::Add(ir_add) => ir_add.uses(),
|
||||||
|
IrOperation::Call(ir_call) => ir_call.uses(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
27
dmc-lib/src/ir/ir_parameter.rs
Normal file
27
dmc-lib/src/ir/ir_parameter.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct IrParameter {
|
||||||
|
name: Rc<str>,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrParameter {
|
||||||
|
pub fn new(name: &str, type_info: TypeInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.into(),
|
||||||
|
type_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
|
&self.type_info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrParameter {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct IrReturn {
|
pub struct IrReturn {
|
||||||
value: Option<IrExpression>,
|
value: Option<IrExpression>,
|
||||||
@ -9,6 +12,10 @@ impl IrReturn {
|
|||||||
pub fn new(value: Option<IrExpression>) -> Self {
|
pub fn new(value: Option<IrExpression>) -> Self {
|
||||||
Self { value }
|
Self { value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
self.value.as_ref().map_or(HashSet::new(), |v| v.uses())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrReturn {
|
impl Display for IrReturn {
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
use crate::ir::ir_assign::IrAssign;
|
use crate::ir::ir_assign::IrAssign;
|
||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_return::IrReturn;
|
use crate::ir::ir_return::IrReturn;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum IrStatement {
|
pub enum IrStatement {
|
||||||
Assign(IrAssign),
|
Assign(IrAssign),
|
||||||
@ -9,6 +12,38 @@ pub enum IrStatement {
|
|||||||
Return(IrReturn),
|
Return(IrReturn),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IrStatement {
|
||||||
|
pub fn definitions(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
match self {
|
||||||
|
IrStatement::Assign(ir_assign) => {
|
||||||
|
set.insert(ir_assign.destination().clone());
|
||||||
|
}
|
||||||
|
IrStatement::Call(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrStatement::Return(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uses(&self) -> HashSet<Rc<IrVariable>> {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
match self {
|
||||||
|
IrStatement::Assign(ir_assign) => {
|
||||||
|
set.extend(ir_assign.uses());
|
||||||
|
}
|
||||||
|
IrStatement::Call(ir_call) => {
|
||||||
|
set.extend(ir_call.uses());
|
||||||
|
}
|
||||||
|
IrStatement::Return(ir_return) => set.extend(ir_return.uses()),
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for IrStatement {
|
impl Display for IrStatement {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/// Represents a virtual register
|
||||||
pub struct IrVariable {
|
pub struct IrVariable {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: TypeInfo,
|
type_info: TypeInfo,
|
||||||
@ -15,6 +17,10 @@ impl IrVariable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_info(&self) -> &TypeInfo {
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
&self.type_info
|
&self.type_info
|
||||||
}
|
}
|
||||||
@ -25,3 +31,23 @@ impl Display for IrVariable {
|
|||||||
write!(f, "{}", self.name)
|
write!(f, "{}", self.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for IrVariable {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for IrVariable {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.name.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for IrVariable {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.name == other.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for IrVariable {}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ pub mod ir_call;
|
|||||||
pub mod ir_expression;
|
pub mod ir_expression;
|
||||||
pub mod ir_function;
|
pub mod ir_function;
|
||||||
pub mod ir_operation;
|
pub mod ir_operation;
|
||||||
|
pub mod ir_parameter;
|
||||||
pub mod ir_return;
|
pub mod ir_return;
|
||||||
pub mod ir_statement;
|
pub mod ir_statement;
|
||||||
pub mod ir_variable;
|
pub mod ir_variable;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -48,7 +50,7 @@ impl FunctionSymbol {
|
|||||||
pub struct ParameterSymbol {
|
pub struct ParameterSymbol {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: TypeInfo,
|
type_info: TypeInfo,
|
||||||
ir_variable: Option<Rc<RefCell<IrVariable>>>,
|
ir_parameter: Option<Rc<IrParameter>>,
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
stack_frame_offset: Option<isize>,
|
stack_frame_offset: Option<isize>,
|
||||||
@ -59,7 +61,7 @@ impl ParameterSymbol {
|
|||||||
Self {
|
Self {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
type_info,
|
type_info,
|
||||||
ir_variable: None,
|
ir_parameter: None,
|
||||||
stack_frame_offset: None,
|
stack_frame_offset: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,14 +78,12 @@ impl ParameterSymbol {
|
|||||||
&self.type_info
|
&self.type_info
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ir_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
|
pub fn set_ir_parameter(&mut self, ir_parameter: Rc<IrParameter>) {
|
||||||
self.ir_variable = Some(ir_variable);
|
self.ir_parameter = Some(ir_parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ir_variable(&self) -> &Rc<RefCell<IrVariable>> {
|
pub fn ir_parameter(&self) -> &Rc<IrParameter> {
|
||||||
self.ir_variable
|
self.ir_parameter.as_ref().unwrap()
|
||||||
.as_ref()
|
|
||||||
.expect("ir_variable not yet initialized")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
@ -100,7 +100,7 @@ impl ParameterSymbol {
|
|||||||
pub struct VariableSymbol {
|
pub struct VariableSymbol {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: Option<TypeInfo>,
|
type_info: Option<TypeInfo>,
|
||||||
ir_variable: Option<Rc<RefCell<IrVariable>>>,
|
ir_variable: Option<Rc<IrVariable>>,
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
register: Option<usize>,
|
register: Option<usize>,
|
||||||
@ -134,11 +134,11 @@ impl VariableSymbol {
|
|||||||
.expect("TypeInfo not initialized. Did you type check?")
|
.expect("TypeInfo not initialized. Did you type check?")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ir_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
|
pub fn set_ir_variable(&mut self, ir_variable: Rc<IrVariable>) {
|
||||||
self.ir_variable = Some(ir_variable);
|
self.ir_variable = Some(ir_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ir_variable(&self) -> &Rc<RefCell<IrVariable>> {
|
pub fn ir_variable(&self) -> &Rc<IrVariable> {
|
||||||
self.ir_variable
|
self.ir_variable
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("ir_variable not yet initialized")
|
.expect("ir_variable not yet initialized")
|
||||||
@ -160,16 +160,16 @@ pub enum ExpressibleSymbol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ExpressibleSymbol {
|
impl ExpressibleSymbol {
|
||||||
pub fn ir_variable(&self) -> Rc<RefCell<IrVariable>> {
|
pub fn ir_expression(&self) -> IrExpression {
|
||||||
match self {
|
match self {
|
||||||
ExpressibleSymbol::Function(_) => {
|
ExpressibleSymbol::Function(_) => {
|
||||||
panic!("Cannot get ir_variable for FunctionSymbol");
|
panic!("Cannot get ir_variable for FunctionSymbol");
|
||||||
}
|
}
|
||||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||||
parameter_symbol.borrow().ir_variable().clone()
|
IrExpression::Parameter(parameter_symbol.borrow().ir_parameter().clone())
|
||||||
}
|
}
|
||||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||||
variable_symbol.borrow().ir_variable().clone()
|
IrExpression::Variable(variable_symbol.borrow().ir_variable().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,4 +8,5 @@ fn main()
|
|||||||
let y = add(1, 2)
|
let y = add(1, 2)
|
||||||
println(y)
|
println(y)
|
||||||
println(add(3, add(4, 5)))
|
println(add(3, add(4, 5)))
|
||||||
|
println(y)
|
||||||
end
|
end
|
||||||
Loading…
Reference in New Issue
Block a user