Cleaning up parameter/variable distinction; first attempt at managing register spills. WIP.
This commit is contained in:
parent
737d7b4232
commit
b29753bc05
@ -435,7 +435,7 @@ impl Function {
|
|||||||
if class_context.is_some() {
|
if class_context.is_some() {
|
||||||
let parameter_0 = builder.parameters()[0].clone();
|
let parameter_0 = builder.parameters()[0].clone();
|
||||||
// put it in the self parameter
|
// put it in the self parameter
|
||||||
builder.set_self_parameter_or_variable(IrParameterOrVariable::IrParameter(parameter_0));
|
builder.set_self_parameter_or_variable(IrParameterOrVariable::Parameter(parameter_0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use crate::ir::ir_call::IrCall;
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_return::IrReturn;
|
use crate::ir::ir_return::IrReturn;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
||||||
@ -17,36 +18,11 @@ use dvm_lib::instruction::{
|
|||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub trait Assemble {
|
|
||||||
fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub struct InstructionsBuilder {
|
|
||||||
instructions: Vec<Instruction>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InstructionsBuilder {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
instructions: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, instruction: Instruction) {
|
|
||||||
self.instructions.push(instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn take_instructions(&mut self) -> Vec<Instruction> {
|
|
||||||
std::mem::take(&mut self.instructions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FunctionAssemblyContext<'a> {
|
struct FunctionAssemblyContext<'a> {
|
||||||
type_infos: &'a Vec<IrTypeInfo>,
|
type_infos: &'a Vec<IrTypeInfo>,
|
||||||
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
||||||
variable_locations: &'a VariableLocations,
|
variable_locations: &'a VariableLocations,
|
||||||
|
parameters: &'a [IrParameter],
|
||||||
constants_table: &'a mut ConstantsTable,
|
constants_table: &'a mut ConstantsTable,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
@ -63,6 +39,7 @@ pub fn assemble_ir_function(
|
|||||||
variables_to_type_infos,
|
variables_to_type_infos,
|
||||||
variable_locations,
|
variable_locations,
|
||||||
constants_table,
|
constants_table,
|
||||||
|
parameters: ir_function.parameters(),
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
};
|
};
|
||||||
for block in ir_function.blocks() {
|
for block in ir_function.blocks() {
|
||||||
@ -209,9 +186,9 @@ fn assemble_ir_return(ir_return: &IrReturn, ctx: &mut FunctionAssemblyContext) {
|
|||||||
|
|
||||||
fn to_move_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> MoveOperand {
|
fn to_move_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> MoveOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => MoveOperand::Location(
|
||||||
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||||
}
|
),
|
||||||
IrExpression::Variable(ir_variable_id) => MoveOperand::Location(to_location(
|
IrExpression::Variable(ir_variable_id) => MoveOperand::Location(to_location(
|
||||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||||
)),
|
)),
|
||||||
@ -229,9 +206,9 @@ fn to_multiply_operand(
|
|||||||
ctx: &mut FunctionAssemblyContext,
|
ctx: &mut FunctionAssemblyContext,
|
||||||
) -> MultiplyOperand {
|
) -> MultiplyOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => MultiplyOperand::Location(
|
||||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||||
}
|
),
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
IrExpression::Variable(ir_variable_id) => {
|
||||||
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id];
|
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id];
|
||||||
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
||||||
@ -254,11 +231,14 @@ fn to_multiply_operand(
|
|||||||
|
|
||||||
fn to_add_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> AddOperand {
|
fn to_add_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> AddOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
IrExpression::Parameter(ir_parameter_id) => {
|
||||||
|
let ir_parameter = &ctx.parameters[*ir_parameter_id];
|
||||||
|
match ir_parameter.type_info() {
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => {
|
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => {
|
||||||
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
IrExpression::Variable(ir_variable_id) => {
|
||||||
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id];
|
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable_id];
|
||||||
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
||||||
@ -282,15 +262,18 @@ fn to_subtract_operand(
|
|||||||
ctx: &mut FunctionAssemblyContext,
|
ctx: &mut FunctionAssemblyContext,
|
||||||
) -> SubtractOperand {
|
) -> SubtractOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
IrExpression::Parameter(ir_parameter_id) => {
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double => {
|
let ir_parameter = &ctx.parameters[*ir_parameter_id];
|
||||||
SubtractOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
match ir_parameter.type_info() {
|
||||||
}
|
IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location(
|
||||||
|
Location::StackFrameOffset(ir_parameter.stack_offset()),
|
||||||
|
),
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Attempt to subtract with non-integer type (found {})",
|
"Attempt to subtract with non-integer type (found {})",
|
||||||
ir_parameter.type_info()
|
ir_parameter.type_info()
|
||||||
),
|
),
|
||||||
},
|
}
|
||||||
|
}
|
||||||
IrExpression::Variable(ir_variable) => {
|
IrExpression::Variable(ir_variable) => {
|
||||||
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable];
|
let ir_type_info_id = ctx.variables_to_type_infos[ir_variable];
|
||||||
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
||||||
@ -317,8 +300,9 @@ fn to_location_or_number(
|
|||||||
ctx: &mut FunctionAssemblyContext,
|
ctx: &mut FunctionAssemblyContext,
|
||||||
) -> LocationOrNumber {
|
) -> LocationOrNumber {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => {
|
||||||
LocationOrNumber::Location(ir_parameter.as_location())
|
let ir_parameter = &ctx.parameters[*ir_parameter_id];
|
||||||
|
LocationOrNumber::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||||
}
|
}
|
||||||
IrExpression::Variable(ir_variable_id) => LocationOrNumber::Location(to_location(
|
IrExpression::Variable(ir_variable_id) => LocationOrNumber::Location(to_location(
|
||||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||||
@ -334,9 +318,9 @@ fn to_location_or_number(
|
|||||||
|
|
||||||
fn to_push_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> PushOperand {
|
fn to_push_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> PushOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => PushOperand::Location(
|
||||||
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||||
}
|
),
|
||||||
IrExpression::Variable(ir_variable_id) => PushOperand::Location(to_location(
|
IrExpression::Variable(ir_variable_id) => PushOperand::Location(to_location(
|
||||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||||
)),
|
)),
|
||||||
@ -354,9 +338,9 @@ fn to_return_operand(
|
|||||||
ctx: &mut FunctionAssemblyContext,
|
ctx: &mut FunctionAssemblyContext,
|
||||||
) -> ReturnOperand {
|
) -> ReturnOperand {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => ReturnOperand::Location(
|
||||||
ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||||
}
|
),
|
||||||
IrExpression::Variable(ir_variable) => ReturnOperand::Location(to_location(
|
IrExpression::Variable(ir_variable) => ReturnOperand::Location(to_location(
|
||||||
ctx.variable_locations.get_variable_location(ir_variable),
|
ctx.variable_locations.get_variable_location(ir_variable),
|
||||||
)),
|
)),
|
||||||
@ -374,9 +358,9 @@ fn to_location_or_integer(
|
|||||||
ctx: &mut FunctionAssemblyContext,
|
ctx: &mut FunctionAssemblyContext,
|
||||||
) -> LocationOrInteger {
|
) -> LocationOrInteger {
|
||||||
match ir_expression {
|
match ir_expression {
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
IrExpression::Parameter(ir_parameter_id) => LocationOrInteger::Location(
|
||||||
LocationOrInteger::Location(ir_parameter.as_location())
|
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||||
}
|
),
|
||||||
IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location(to_location(
|
IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location(to_location(
|
||||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||||
)),
|
)),
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::{HasVrUsers, RegisterAssignment, VrUser};
|
use crate::ir::register_allocation::VrUser;
|
||||||
use crate::offset_counter::OffsetCounter;
|
use std::collections::HashSet;
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
|
|
||||||
pub type IrBlockId = usize;
|
pub type IrBlockId = usize;
|
||||||
|
|
||||||
@ -34,19 +33,6 @@ impl IrBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasVrUsers for IrBlock {
|
|
||||||
fn vr_users(&self) -> Vec<&dyn VrUser> {
|
|
||||||
self.statements.iter().map(|s| s as &dyn VrUser).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vr_users_mut(&mut self) -> Vec<&mut dyn VrUser> {
|
|
||||||
self.statements
|
|
||||||
.iter_mut()
|
|
||||||
.map(|s| s as &mut dyn VrUser)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VrUser for IrBlock {
|
impl VrUser for IrBlock {
|
||||||
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
||||||
self.statements
|
self.statements
|
||||||
@ -58,27 +44,6 @@ impl VrUser for IrBlock {
|
|||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
self.statements.iter().flat_map(|s| s.vr_uses()).collect()
|
self.statements.iter().flat_map(|s| s.vr_uses()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_spills(&mut self, spills: &HashSet<IrVariableId>) {
|
|
||||||
for statement in &mut self.statements {
|
|
||||||
statement.propagate_spills(spills);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn propagate_register_assignments(
|
|
||||||
&mut self,
|
|
||||||
assignments: &HashMap<IrVariableId, RegisterAssignment>,
|
|
||||||
) {
|
|
||||||
for statement in &mut self.statements {
|
|
||||||
statement.propagate_register_assignments(assignments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
|
||||||
for statement in &mut self.statements {
|
|
||||||
statement.propagate_stack_offsets(counter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -39,7 +39,10 @@ impl IrCall {
|
|||||||
|
|
||||||
impl VrUser for IrCall {
|
impl VrUser for IrCall {
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
self.arguments.iter().flat_map(|a| a.vr_uses()).collect()
|
self.arguments
|
||||||
|
.iter()
|
||||||
|
.flat_map(|ir_expression| ir_expression.vr_uses())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,305 +1,18 @@
|
|||||||
use crate::constants_table::ConstantsTable;
|
use crate::ir::ir_parameter::IrParameterId;
|
||||||
use crate::ir::ir_parameter::IrParameter;
|
|
||||||
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use crate::ir::variable_locations::{VariableLocation, VariableLocations};
|
use std::collections::HashSet;
|
||||||
use dvm_lib::instruction::{
|
|
||||||
AddOperand, Location, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand,
|
|
||||||
PushOperand, ReturnOperand, SetFieldOperand, SubtractOperand,
|
|
||||||
};
|
|
||||||
use std::collections::{HashMap, 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 {
|
||||||
Parameter(Rc<IrParameter>),
|
Parameter(IrParameterId),
|
||||||
Variable(IrVariableId),
|
Variable(IrVariableId),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Double(f64),
|
Double(f64),
|
||||||
String(Rc<str>),
|
String(Rc<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrExpression {
|
|
||||||
pub fn move_operand(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
) -> MoveOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
MoveOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
MoveOperand::Location(Location::StackFrameOffset(stack_frame_offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => MoveOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => MoveOperand::Double(*d),
|
|
||||||
IrExpression::String(s) => {
|
|
||||||
let constant_name = constants_table.get_or_insert(s);
|
|
||||||
MoveOperand::String(constant_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_operand(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
) -> PushOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
PushOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
PushOperand::Location(Location::StackFrameOffset(stack_frame_offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => PushOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => PushOperand::Double(*d),
|
|
||||||
IrExpression::String(s) => {
|
|
||||||
let constant_name = constants_table.get_or_insert(s);
|
|
||||||
PushOperand::String(constant_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_operand(
|
|
||||||
&self,
|
|
||||||
type_infos: &Vec<IrTypeInfo>,
|
|
||||||
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
) -> AddOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => {
|
|
||||||
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
|
||||||
let ir_type_info_id = variables_to_type_infos[ir_variable_id];
|
|
||||||
let ir_type_info = &type_infos[ir_type_info_id];
|
|
||||||
match ir_type_info {
|
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => {
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
AddOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
AddOperand::Location(Location::StackFrameOffset(stack_frame_offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => AddOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => AddOperand::Double(*d),
|
|
||||||
IrExpression::String(s) => {
|
|
||||||
let constant_name = constants_table.get_or_insert(s);
|
|
||||||
AddOperand::String(constant_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract_operand(
|
|
||||||
&self,
|
|
||||||
type_infos: &Vec<IrTypeInfo>,
|
|
||||||
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
) -> SubtractOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double => SubtractOperand::Location(
|
|
||||||
Location::StackFrameOffset(ir_parameter.stack_offset()),
|
|
||||||
),
|
|
||||||
_ => panic!(
|
|
||||||
"Attempt to subtract with non-integer type (found {})",
|
|
||||||
ir_parameter.type_info()
|
|
||||||
),
|
|
||||||
},
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
let ir_type_info_id = variables_to_type_infos[ir_variable];
|
|
||||||
let ir_type_info = &type_infos[ir_type_info_id];
|
|
||||||
match ir_type_info {
|
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double => match variable_locations
|
|
||||||
.get_variable_location(ir_variable)
|
|
||||||
{
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
SubtractOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => SubtractOperand::Location(
|
|
||||||
Location::StackFrameOffset(stack_frame_offset),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
_ => panic!(
|
|
||||||
"Attempt to subtract with non-number type (found {})",
|
|
||||||
ir_type_info
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => SubtractOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => SubtractOperand::Double(*d),
|
|
||||||
IrExpression::String(_) => {
|
|
||||||
panic!("Attempt to subtract with a string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn multiply_operand(
|
|
||||||
&self,
|
|
||||||
type_infos: &Vec<IrTypeInfo>,
|
|
||||||
variables_to_type_infos: &HashMap<IrVariableId, IrTypeInfoId>,
|
|
||||||
variables_locations: &VariableLocations,
|
|
||||||
) -> MultiplyOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
|
||||||
let ir_type_info_id = variables_to_type_infos[ir_variable_id];
|
|
||||||
let ir_type_info = &type_infos[ir_type_info_id];
|
|
||||||
match ir_type_info {
|
|
||||||
IrTypeInfo::Int | IrTypeInfo::Double => {
|
|
||||||
match variables_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
MultiplyOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
MultiplyOperand::Location(Location::StackFrameOffset(
|
|
||||||
stack_frame_offset,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("Attempt to multiply non-number (found {})", ir_type_info),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => MultiplyOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => MultiplyOperand::Double(*d),
|
|
||||||
IrExpression::String(_) => {
|
|
||||||
panic!("Attempt to multiply with a string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn return_operand(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
) -> ReturnOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable) => {
|
|
||||||
match variable_locations.get_variable_location(ir_variable) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
ReturnOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
ReturnOperand::Location(Location::StackFrameOffset(stack_frame_offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => ReturnOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => ReturnOperand::Double(*d),
|
|
||||||
IrExpression::String(s) => {
|
|
||||||
let constant_name = constants_table.get_or_insert(s);
|
|
||||||
ReturnOperand::String(constant_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_field_operand(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
) -> SetFieldOperand {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
SetFieldOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => {
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
SetFieldOperand::Location(Location::Register(register_assignment))
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
SetFieldOperand::Location(Location::StackFrameOffset(stack_frame_offset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IrExpression::Int(i) => SetFieldOperand::Int(*i),
|
|
||||||
IrExpression::Double(d) => SetFieldOperand::Double(*d),
|
|
||||||
IrExpression::String(s) => {
|
|
||||||
let constant_name = constants_table.get_or_insert(s);
|
|
||||||
SetFieldOperand::String(constant_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_location_or_number(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
) -> LocationOrNumber {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
LocationOrNumber::Location(ir_parameter.as_location())
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => LocationOrNumber::Location(
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
Location::Register(register_assignment)
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
Location::StackFrameOffset(stack_frame_offset)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IrExpression::Int(i) => LocationOrNumber::Int(*i),
|
|
||||||
IrExpression::Double(d) => LocationOrNumber::Double(*d),
|
|
||||||
_ => panic!("Attempt to convert {} to a location or number", self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_location_or_integer(
|
|
||||||
&self,
|
|
||||||
variable_locations: &VariableLocations,
|
|
||||||
) -> LocationOrInteger {
|
|
||||||
match self {
|
|
||||||
IrExpression::Parameter(ir_parameter) => {
|
|
||||||
LocationOrInteger::Location(ir_parameter.as_location())
|
|
||||||
}
|
|
||||||
IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location(
|
|
||||||
match variable_locations.get_variable_location(ir_variable_id) {
|
|
||||||
VariableLocation::Register(register_assignment) => {
|
|
||||||
Location::Register(register_assignment)
|
|
||||||
}
|
|
||||||
VariableLocation::Stack(stack_frame_offset) => {
|
|
||||||
Location::StackFrameOffset(stack_frame_offset)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IrExpression::Int(i) => LocationOrInteger::Int(*i),
|
|
||||||
_ => panic!("Attempt to convert {} to a location or integer", self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
pub struct IrFunction {
|
pub struct IrFunction {
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
parameters: Vec<Rc<IrParameter>>,
|
parameters: Vec<IrParameter>,
|
||||||
variables: Vec<IrVariable>,
|
variables: Vec<IrVariable>,
|
||||||
return_type_info: Option<IrTypeInfo>,
|
return_type_info: Option<IrTypeInfo>,
|
||||||
blocks: Vec<IrBlock>,
|
blocks: Vec<IrBlock>,
|
||||||
@ -21,7 +21,7 @@ pub struct IrFunction {
|
|||||||
impl IrFunction {
|
impl IrFunction {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
parameters: Vec<Rc<IrParameter>>,
|
parameters: Vec<IrParameter>,
|
||||||
variables: Vec<IrVariable>,
|
variables: Vec<IrVariable>,
|
||||||
return_type_info: Option<IrTypeInfo>,
|
return_type_info: Option<IrTypeInfo>,
|
||||||
blocks: Vec<IrBlock>,
|
blocks: Vec<IrBlock>,
|
||||||
@ -43,7 +43,7 @@ impl IrFunction {
|
|||||||
&self.blocks
|
&self.blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parameters(&self) -> &[Rc<IrParameter>] {
|
pub fn parameters(&self) -> &[IrParameter] {
|
||||||
&self.parameters
|
&self.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,24 @@
|
|||||||
|
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub struct IrGetFieldRef {
|
pub struct IrGetFieldRef {
|
||||||
self_variable_id: IrVariableId,
|
self_variable_or_parameter: IrParameterOrVariable,
|
||||||
field_index: usize,
|
field_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrGetFieldRef {
|
impl IrGetFieldRef {
|
||||||
pub fn new(self_variable_id: IrVariableId, field_index: usize) -> Self {
|
pub fn new(self_variable_or_parameter: IrParameterOrVariable, field_index: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
self_variable_id,
|
self_variable_or_parameter,
|
||||||
field_index,
|
field_index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn self_variable_id(self) -> IrVariableId {
|
pub fn self_variable_id(&self) -> &IrParameterOrVariable {
|
||||||
self.self_variable_id
|
&self.self_variable_or_parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_index(&self) -> usize {
|
pub fn field_index(&self) -> usize {
|
||||||
@ -27,12 +28,16 @@ impl IrGetFieldRef {
|
|||||||
|
|
||||||
impl Display for IrGetFieldRef {
|
impl Display for IrGetFieldRef {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "&{}.{}", self.self_variable_id, self.field_index)
|
write!(
|
||||||
|
f,
|
||||||
|
"&{}.{}",
|
||||||
|
self.self_variable_or_parameter, self.field_index
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrGetFieldRef {
|
impl VrUser for IrGetFieldRef {
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
todo!()
|
self.self_variable_or_parameter.vr_uses()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,24 @@
|
|||||||
|
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub struct IrGetFieldRefMut {
|
pub struct IrGetFieldRefMut {
|
||||||
self_ir_variable: IrVariableId,
|
self_variable_or_parameter: IrParameterOrVariable,
|
||||||
field_index: usize,
|
field_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrGetFieldRefMut {
|
impl IrGetFieldRefMut {
|
||||||
pub fn new(self_ir_variable: IrVariableId, field_index: usize) -> Self {
|
pub fn new(self_variable_or_parameter: IrParameterOrVariable, field_index: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
self_ir_variable,
|
self_variable_or_parameter,
|
||||||
field_index,
|
field_index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn self_ir_variable(&self) -> IrVariableId {
|
pub fn self_ir_variable(&self) -> &IrParameterOrVariable {
|
||||||
self.self_ir_variable
|
&self.self_variable_or_parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_index(&self) -> usize {
|
pub fn field_index(&self) -> usize {
|
||||||
@ -27,12 +28,17 @@ impl IrGetFieldRefMut {
|
|||||||
|
|
||||||
impl Display for IrGetFieldRefMut {
|
impl Display for IrGetFieldRefMut {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "&mut {}.{}", self.self_ir_variable, self.field_index())
|
write!(
|
||||||
|
f,
|
||||||
|
"&mut {}.{}",
|
||||||
|
self.self_variable_or_parameter,
|
||||||
|
self.field_index()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrGetFieldRefMut {
|
impl VrUser for IrGetFieldRefMut {
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
todo!()
|
self.self_variable_or_parameter.vr_uses()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ use dvm_lib::instruction::Location;
|
|||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub type IrParameterId = usize;
|
||||||
|
|
||||||
pub struct IrParameter {
|
pub struct IrParameter {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: IrTypeInfo,
|
type_info: IrTypeInfo,
|
||||||
|
|||||||
@ -1,51 +1,27 @@
|
|||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameterId;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVirtualRegisterVariable};
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use dvm_lib::instruction::Location;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::Display;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
#[deprecated]
|
|
||||||
pub enum IrParameterOrVariable {
|
pub enum IrParameterOrVariable {
|
||||||
IrParameter(Rc<IrParameter>),
|
Parameter(IrParameterId),
|
||||||
Variable(Rc<RefCell<IrVariable>>),
|
Variable(IrVariableId),
|
||||||
}
|
|
||||||
|
|
||||||
impl IrParameterOrVariable {
|
|
||||||
pub fn as_location(&self) -> Location {
|
|
||||||
match self {
|
|
||||||
IrParameterOrVariable::IrParameter(ir_parameter) => {
|
|
||||||
Location::StackFrameOffset(ir_parameter.stack_offset())
|
|
||||||
}
|
|
||||||
IrParameterOrVariable::Variable(ir_variable) => {
|
|
||||||
ir_variable.borrow().descriptor().as_location()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vr_uses(&self) -> HashSet<IrVirtualRegisterVariable> {
|
|
||||||
if let IrParameterOrVariable::Variable(ir_variable) = &self {
|
|
||||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
|
||||||
ir_variable.borrow().descriptor()
|
|
||||||
{
|
|
||||||
return HashSet::from([vr_variable.clone()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HashSet::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrParameterOrVariable {
|
impl Display for IrParameterOrVariable {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
write!(f, "{}", self)
|
||||||
IrParameterOrVariable::IrParameter(ir_parameter) => {
|
|
||||||
write!(f, "{}", ir_parameter)
|
|
||||||
}
|
|
||||||
IrParameterOrVariable::Variable(ir_variable) => {
|
|
||||||
write!(f, "{}", ir_variable.borrow())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrParameterOrVariable {
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
|
if let IrParameterOrVariable::Variable(ir_variable_id) = self {
|
||||||
|
HashSet::from([*ir_variable_id])
|
||||||
|
} else {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ impl IrReadField {
|
|||||||
|
|
||||||
impl VrUser for IrReadField {
|
impl VrUser for IrReadField {
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
todo!()
|
HashSet::from([self.field_ref_variable])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,18 @@
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableId};
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::VrUser;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct IrSetField {
|
pub struct IrSetField {
|
||||||
field_ref_variable: Rc<RefCell<IrVariable>>,
|
field_ref_variable: IrVariableId,
|
||||||
initializer: Box<IrExpression>,
|
initializer: Box<IrExpression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IrSetField {
|
impl IrSetField {
|
||||||
pub fn new(field_ref_variable: &Rc<RefCell<IrVariable>>, initializer: IrExpression) -> Self {
|
pub fn new(field_ref_variable: IrVariableId, initializer: IrExpression) -> Self {
|
||||||
Self {
|
Self {
|
||||||
field_ref_variable: field_ref_variable.clone(),
|
field_ref_variable,
|
||||||
initializer: initializer.into(),
|
initializer: initializer.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,16 +20,10 @@ impl IrSetField {
|
|||||||
|
|
||||||
impl VrUser for IrSetField {
|
impl VrUser for IrSetField {
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||||
// let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
// match self.field_ref_variable.borrow().descriptor() {
|
set.insert(self.field_ref_variable);
|
||||||
// IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
set.extend(self.initializer.vr_uses());
|
||||||
// set.insert(vr_variable.clone());
|
set
|
||||||
// }
|
|
||||||
// IrVariableDescriptor::Stack(_) => {}
|
|
||||||
// }
|
|
||||||
// set.extend(self.initializer.vr_uses());
|
|
||||||
// set
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,11 +37,6 @@ impl VrUser for IrSetField {
|
|||||||
|
|
||||||
impl Display for IrSetField {
|
impl Display for IrSetField {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(f, "*{} = {}", self.field_ref_variable, self.initializer)
|
||||||
f,
|
|
||||||
"*{} = {}",
|
|
||||||
self.field_ref_variable.borrow(),
|
|
||||||
self.initializer
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use crate::ir::ir_block::IrBlock;
|
use crate::ir::ir_block::IrBlock;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::variable_locations::VariableLocations;
|
use crate::ir::variable_locations::VariableLocations;
|
||||||
use crate::offset_counter::OffsetCounter;
|
|
||||||
use dvm_lib::instruction::{Register, StackFrameOffset};
|
use dvm_lib::instruction::{Register, StackFrameOffset};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
@ -31,17 +30,9 @@ pub fn block_live_in_live_out(ir_block: &IrBlock) -> (LivenessSets, LivenessSets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in: use(s) U ( out(s) - def(s) )
|
// in: use(s) U ( out(s) - def(s) )
|
||||||
let use_s = ir_statement
|
let use_s = ir_statement.vr_uses();
|
||||||
.vr_uses()
|
|
||||||
.iter()
|
|
||||||
.map(|u| *u)
|
|
||||||
.collect::<HashSet<_>>();
|
|
||||||
let out_s = &live_out[statement_index];
|
let out_s = &live_out[statement_index];
|
||||||
let def_s = ir_statement
|
let def_s = ir_statement.vr_definitions();
|
||||||
.vr_definitions()
|
|
||||||
.iter()
|
|
||||||
.map(|d| *d)
|
|
||||||
.collect::<HashSet<_>>();
|
|
||||||
let rhs = out_s - &def_s;
|
let rhs = out_s - &def_s;
|
||||||
let new_ins = use_s.union(&rhs).map(|v| *v).collect::<HashSet<_>>();
|
let new_ins = use_s.union(&rhs).map(|v| *v).collect::<HashSet<_>>();
|
||||||
|
|
||||||
@ -66,11 +57,16 @@ pub fn block_interference_graph(
|
|||||||
ir_block: &IrBlock,
|
ir_block: &IrBlock,
|
||||||
spilled: &HashSet<IrVariableId>,
|
spilled: &HashSet<IrVariableId>,
|
||||||
) -> InterferenceGraph {
|
) -> InterferenceGraph {
|
||||||
// create a set of all variables used in the block
|
// create a set of all variables used in the block that are not already spilled
|
||||||
let mut all_vr_variables: HashSet<IrVariableId> = HashSet::new();
|
let mut all_vr_variables: HashSet<IrVariableId> = HashSet::new();
|
||||||
for statement in ir_block.statements() {
|
for statement in ir_block.statements() {
|
||||||
all_vr_variables.extend(statement.vr_definitions());
|
let definitions = statement.vr_definitions();
|
||||||
all_vr_variables.extend(statement.vr_uses());
|
let uses = statement.vr_uses();
|
||||||
|
let not_already_spilled = definitions
|
||||||
|
.union(&uses)
|
||||||
|
.filter(|v| !spilled.contains(*v))
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
all_vr_variables.extend(not_already_spilled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create graph and init all variables' outgoing-edge sets
|
// create graph and init all variables' outgoing-edge sets
|
||||||
@ -84,6 +80,11 @@ pub fn block_interference_graph(
|
|||||||
for (statement_index, ir_statement) in ir_block.statements().iter().enumerate() {
|
for (statement_index, ir_statement) in ir_block.statements().iter().enumerate() {
|
||||||
let statement_live_out = &live_out[statement_index];
|
let statement_live_out = &live_out[statement_index];
|
||||||
for definition_vr_variable in ir_statement.vr_definitions() {
|
for definition_vr_variable in ir_statement.vr_definitions() {
|
||||||
|
// check for spill
|
||||||
|
if spilled.contains(&definition_vr_variable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for live_out_variable in statement_live_out {
|
for live_out_variable in statement_live_out {
|
||||||
// we do the following check to avoid adding an edge to itself
|
// we do the following check to avoid adding an edge to itself
|
||||||
if definition_vr_variable != *live_out_variable {
|
if definition_vr_variable != *live_out_variable {
|
||||||
@ -106,9 +107,10 @@ pub fn block_assign_registers(ir_block: &IrBlock, register_count: usize) -> Vari
|
|||||||
let mut interference_graph = block_interference_graph(ir_block, &spilled);
|
let mut interference_graph = block_interference_graph(ir_block, &spilled);
|
||||||
let (registers, new_spills) = registers_and_spills(&mut interference_graph, register_count);
|
let (registers, new_spills) = registers_and_spills(&mut interference_graph, register_count);
|
||||||
|
|
||||||
if spilled != new_spills {
|
let old_n_spilled = spilled.len();
|
||||||
spilled = new_spills; // todo: figure out if this works algorithmically
|
spilled.extend(new_spills);
|
||||||
} else {
|
// check if added zero spills to get to fixed point
|
||||||
|
if old_n_spilled == spilled.len() {
|
||||||
let mut spills_to_stack_offsets: HashMap<IrVariableId, StackFrameOffset> =
|
let mut spills_to_stack_offsets: HashMap<IrVariableId, StackFrameOffset> =
|
||||||
HashMap::new();
|
HashMap::new();
|
||||||
let mut offset_counter = 0isize;
|
let mut offset_counter = 0isize;
|
||||||
@ -121,36 +123,12 @@ pub fn block_assign_registers(ir_block: &IrBlock, register_count: usize) -> Vari
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasVrUsers {
|
|
||||||
fn vr_users(&self) -> Vec<&dyn VrUser>;
|
|
||||||
fn vr_users_mut(&mut self) -> Vec<&mut dyn VrUser>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait VrUser {
|
pub trait VrUser {
|
||||||
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
||||||
HashSet::new()
|
HashSet::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVariableId>;
|
fn vr_uses(&self) -> HashSet<IrVariableId>;
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
fn propagate_spills(&mut self, _spills: &HashSet<IrVariableId>) {
|
|
||||||
// default no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
fn propagate_register_assignments(
|
|
||||||
&mut self,
|
|
||||||
_assignments: &HashMap<IrVariableId, RegisterAssignment>,
|
|
||||||
) {
|
|
||||||
// default no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
|
||||||
// default no-op
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -160,7 +138,7 @@ struct WorkItem {
|
|||||||
color: bool,
|
color: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registers_and_spills(
|
fn registers_and_spills(
|
||||||
interference_graph: &mut InterferenceGraph,
|
interference_graph: &mut InterferenceGraph,
|
||||||
k: usize,
|
k: usize,
|
||||||
) -> (
|
) -> (
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
use crate::ir::ir_variable::IrVariableId;
|
use crate::ir::ir_variable::IrVariableId;
|
||||||
use crate::ir::register_allocation::RegisterAssignment;
|
use crate::ir::register_allocation::RegisterAssignment;
|
||||||
use dvm_lib::instruction::StackFrameOffset;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub type StackVariableOffset = isize;
|
||||||
|
|
||||||
pub enum VariableLocation {
|
pub enum VariableLocation {
|
||||||
Register(RegisterAssignment),
|
Register(RegisterAssignment),
|
||||||
Stack(StackFrameOffset),
|
Stack(StackVariableOffset),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VariableLocations {
|
pub struct VariableLocations {
|
||||||
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
||||||
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
|
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariableLocations {
|
impl VariableLocations {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
||||||
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
|
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
register_variables,
|
register_variables,
|
||||||
|
|||||||
@ -161,10 +161,7 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
|
|||||||
|
|
||||||
let ir_function = IrFunction::new(
|
let ir_function = IrFunction::new(
|
||||||
function_symbol.fqn_owned(),
|
function_symbol.fqn_owned(),
|
||||||
lower_to_ir_parameters(function, ctx)
|
lower_to_ir_parameters(function, ctx),
|
||||||
.into_iter()
|
|
||||||
.map(|ir_parameter| Rc::new(ir_parameter))
|
|
||||||
.collect(),
|
|
||||||
fn_ctx.ir_variables,
|
fn_ctx.ir_variables,
|
||||||
return_type_info_to_ir_type_info(return_type_info),
|
return_type_info_to_ir_type_info(return_type_info),
|
||||||
fn_ctx.blocks,
|
fn_ctx.blocks,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user