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() {
|
||||
let parameter_0 = builder.parameters()[0].clone();
|
||||
// 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_function::IrFunction;
|
||||
use crate::ir::ir_operation::IrOperation;
|
||||
use crate::ir::ir_parameter::IrParameter;
|
||||
use crate::ir::ir_return::IrReturn;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
||||
@ -17,36 +18,11 @@ use dvm_lib::instruction::{
|
||||
};
|
||||
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> {
|
||||
type_infos: &'a Vec<IrTypeInfo>,
|
||||
variables_to_type_infos: &'a HashMap<IrVariableId, IrTypeInfoId>,
|
||||
variable_locations: &'a VariableLocations,
|
||||
parameters: &'a [IrParameter],
|
||||
constants_table: &'a mut ConstantsTable,
|
||||
instructions: Vec<Instruction>,
|
||||
}
|
||||
@ -63,6 +39,7 @@ pub fn assemble_ir_function(
|
||||
variables_to_type_infos,
|
||||
variable_locations,
|
||||
constants_table,
|
||||
parameters: ir_function.parameters(),
|
||||
instructions: Vec::new(),
|
||||
};
|
||||
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 {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
MoveOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter_id) => MoveOperand::Location(
|
||||
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||
),
|
||||
IrExpression::Variable(ir_variable_id) => MoveOperand::Location(to_location(
|
||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||
)),
|
||||
@ -229,9 +206,9 @@ fn to_multiply_operand(
|
||||
ctx: &mut FunctionAssemblyContext,
|
||||
) -> MultiplyOperand {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
MultiplyOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter_id) => MultiplyOperand::Location(
|
||||
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||
),
|
||||
IrExpression::Variable(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];
|
||||
@ -254,11 +231,14 @@ fn to_multiply_operand(
|
||||
|
||||
fn to_add_operand(ir_expression: &IrExpression, ctx: &mut FunctionAssemblyContext) -> AddOperand {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||
IrTypeInfo::Int | IrTypeInfo::Double | IrTypeInfo::String => {
|
||||
AddOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
IrExpression::Parameter(ir_parameter_id) => {
|
||||
let ir_parameter = &ctx.parameters[*ir_parameter_id];
|
||||
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 = ctx.variables_to_type_infos[ir_variable_id];
|
||||
let ir_type_info = &ctx.type_infos[ir_type_info_id];
|
||||
@ -282,15 +262,18 @@ fn to_subtract_operand(
|
||||
ctx: &mut FunctionAssemblyContext,
|
||||
) -> SubtractOperand {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => match ir_parameter.type_info() {
|
||||
IrTypeInfo::Int | IrTypeInfo::Double => {
|
||||
SubtractOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
IrExpression::Parameter(ir_parameter_id) => {
|
||||
let ir_parameter = &ctx.parameters[*ir_parameter_id];
|
||||
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()
|
||||
),
|
||||
}
|
||||
_ => panic!(
|
||||
"Attempt to subtract with non-integer type (found {})",
|
||||
ir_parameter.type_info()
|
||||
),
|
||||
},
|
||||
}
|
||||
IrExpression::Variable(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];
|
||||
@ -317,8 +300,9 @@ fn to_location_or_number(
|
||||
ctx: &mut FunctionAssemblyContext,
|
||||
) -> LocationOrNumber {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
LocationOrNumber::Location(ir_parameter.as_location())
|
||||
IrExpression::Parameter(ir_parameter_id) => {
|
||||
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(
|
||||
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 {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
PushOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter_id) => PushOperand::Location(
|
||||
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||
),
|
||||
IrExpression::Variable(ir_variable_id) => PushOperand::Location(to_location(
|
||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||
)),
|
||||
@ -354,9 +338,9 @@ fn to_return_operand(
|
||||
ctx: &mut FunctionAssemblyContext,
|
||||
) -> ReturnOperand {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
ReturnOperand::Location(Location::StackFrameOffset(ir_parameter.stack_offset()))
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter_id) => ReturnOperand::Location(
|
||||
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||
),
|
||||
IrExpression::Variable(ir_variable) => ReturnOperand::Location(to_location(
|
||||
ctx.variable_locations.get_variable_location(ir_variable),
|
||||
)),
|
||||
@ -374,9 +358,9 @@ fn to_location_or_integer(
|
||||
ctx: &mut FunctionAssemblyContext,
|
||||
) -> LocationOrInteger {
|
||||
match ir_expression {
|
||||
IrExpression::Parameter(ir_parameter) => {
|
||||
LocationOrInteger::Location(ir_parameter.as_location())
|
||||
}
|
||||
IrExpression::Parameter(ir_parameter_id) => LocationOrInteger::Location(
|
||||
Location::StackFrameOffset(ctx.parameters[*ir_parameter_id].stack_offset()),
|
||||
),
|
||||
IrExpression::Variable(ir_variable_id) => LocationOrInteger::Location(to_location(
|
||||
ctx.variable_locations.get_variable_location(ir_variable_id),
|
||||
)),
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::{HasVrUsers, RegisterAssignment, VrUser};
|
||||
use crate::offset_counter::OffsetCounter;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use std::collections::HashSet;
|
||||
|
||||
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 {
|
||||
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
||||
self.statements
|
||||
@ -58,27 +44,6 @@ impl VrUser for IrBlock {
|
||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||
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 {
|
||||
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::IrParameter;
|
||||
use crate::ir::ir_type_info::{IrTypeInfo, IrTypeInfoId};
|
||||
use crate::ir::ir_parameter::IrParameterId;
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use crate::ir::variable_locations::{VariableLocation, VariableLocations};
|
||||
use dvm_lib::instruction::{
|
||||
AddOperand, Location, LocationOrInteger, LocationOrNumber, MoveOperand, MultiplyOperand,
|
||||
PushOperand, ReturnOperand, SetFieldOperand, SubtractOperand,
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub enum IrExpression {
|
||||
Parameter(Rc<IrParameter>),
|
||||
Parameter(IrParameterId),
|
||||
Variable(IrVariableId),
|
||||
Int(i32),
|
||||
Double(f64),
|
||||
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 {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -12,7 +12,7 @@ use std::rc::Rc;
|
||||
|
||||
pub struct IrFunction {
|
||||
fqn: Rc<str>,
|
||||
parameters: Vec<Rc<IrParameter>>,
|
||||
parameters: Vec<IrParameter>,
|
||||
variables: Vec<IrVariable>,
|
||||
return_type_info: Option<IrTypeInfo>,
|
||||
blocks: Vec<IrBlock>,
|
||||
@ -21,7 +21,7 @@ pub struct IrFunction {
|
||||
impl IrFunction {
|
||||
pub fn new(
|
||||
fqn: Rc<str>,
|
||||
parameters: Vec<Rc<IrParameter>>,
|
||||
parameters: Vec<IrParameter>,
|
||||
variables: Vec<IrVariable>,
|
||||
return_type_info: Option<IrTypeInfo>,
|
||||
blocks: Vec<IrBlock>,
|
||||
@ -43,7 +43,7 @@ impl IrFunction {
|
||||
&self.blocks
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> &[Rc<IrParameter>] {
|
||||
pub fn parameters(&self) -> &[IrParameter] {
|
||||
&self.parameters
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub struct IrGetFieldRef {
|
||||
self_variable_id: IrVariableId,
|
||||
self_variable_or_parameter: IrParameterOrVariable,
|
||||
field_index: usize,
|
||||
}
|
||||
|
||||
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_variable_id,
|
||||
self_variable_or_parameter,
|
||||
field_index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn self_variable_id(self) -> IrVariableId {
|
||||
self.self_variable_id
|
||||
pub fn self_variable_id(&self) -> &IrParameterOrVariable {
|
||||
&self.self_variable_or_parameter
|
||||
}
|
||||
|
||||
pub fn field_index(&self) -> usize {
|
||||
@ -27,12 +28,16 @@ impl IrGetFieldRef {
|
||||
|
||||
impl Display for IrGetFieldRef {
|
||||
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 {
|
||||
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::register_allocation::VrUser;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub struct IrGetFieldRefMut {
|
||||
self_ir_variable: IrVariableId,
|
||||
self_variable_or_parameter: IrParameterOrVariable,
|
||||
field_index: usize,
|
||||
}
|
||||
|
||||
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_ir_variable,
|
||||
self_variable_or_parameter,
|
||||
field_index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn self_ir_variable(&self) -> IrVariableId {
|
||||
self.self_ir_variable
|
||||
pub fn self_ir_variable(&self) -> &IrParameterOrVariable {
|
||||
&self.self_variable_or_parameter
|
||||
}
|
||||
|
||||
pub fn field_index(&self) -> usize {
|
||||
@ -27,12 +28,17 @@ impl IrGetFieldRefMut {
|
||||
|
||||
impl Display for IrGetFieldRefMut {
|
||||
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 {
|
||||
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::rc::Rc;
|
||||
|
||||
pub type IrParameterId = usize;
|
||||
|
||||
pub struct IrParameter {
|
||||
name: Rc<str>,
|
||||
type_info: IrTypeInfo,
|
||||
|
||||
@ -1,51 +1,27 @@
|
||||
use crate::ir::ir_parameter::IrParameter;
|
||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVirtualRegisterVariable};
|
||||
use dvm_lib::instruction::Location;
|
||||
use std::cell::RefCell;
|
||||
use crate::ir::ir_parameter::IrParameterId;
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[deprecated]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum IrParameterOrVariable {
|
||||
IrParameter(Rc<IrParameter>),
|
||||
Variable(Rc<RefCell<IrVariable>>),
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
Parameter(IrParameterId),
|
||||
Variable(IrVariableId),
|
||||
}
|
||||
|
||||
impl Display for IrParameterOrVariable {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IrParameterOrVariable::IrParameter(ir_parameter) => {
|
||||
write!(f, "{}", ir_parameter)
|
||||
}
|
||||
IrParameterOrVariable::Variable(ir_variable) => {
|
||||
write!(f, "{}", ir_variable.borrow())
|
||||
}
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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_variable::{IrVariable, IrVariableId};
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::VrUser;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct IrSetField {
|
||||
field_ref_variable: Rc<RefCell<IrVariable>>,
|
||||
field_ref_variable: IrVariableId,
|
||||
initializer: Box<IrExpression>,
|
||||
}
|
||||
|
||||
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 {
|
||||
field_ref_variable: field_ref_variable.clone(),
|
||||
field_ref_variable,
|
||||
initializer: initializer.into(),
|
||||
}
|
||||
}
|
||||
@ -22,16 +20,10 @@ impl IrSetField {
|
||||
|
||||
impl VrUser for IrSetField {
|
||||
fn vr_uses(&self) -> HashSet<IrVariableId> {
|
||||
// let mut set = HashSet::new();
|
||||
// match self.field_ref_variable.borrow().descriptor() {
|
||||
// IrVariableDescriptor::VirtualRegister(vr_variable) => {
|
||||
// set.insert(vr_variable.clone());
|
||||
// }
|
||||
// IrVariableDescriptor::Stack(_) => {}
|
||||
// }
|
||||
// set.extend(self.initializer.vr_uses());
|
||||
// set
|
||||
todo!()
|
||||
let mut set = HashSet::new();
|
||||
set.insert(self.field_ref_variable);
|
||||
set.extend(self.initializer.vr_uses());
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,11 +37,6 @@ impl VrUser for IrSetField {
|
||||
|
||||
impl Display for IrSetField {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"*{} = {}",
|
||||
self.field_ref_variable.borrow(),
|
||||
self.initializer
|
||||
)
|
||||
write!(f, "*{} = {}", self.field_ref_variable, self.initializer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::ir::ir_block::IrBlock;
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::variable_locations::VariableLocations;
|
||||
use crate::offset_counter::OffsetCounter;
|
||||
use dvm_lib::instruction::{Register, StackFrameOffset};
|
||||
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) )
|
||||
let use_s = ir_statement
|
||||
.vr_uses()
|
||||
.iter()
|
||||
.map(|u| *u)
|
||||
.collect::<HashSet<_>>();
|
||||
let use_s = ir_statement.vr_uses();
|
||||
let out_s = &live_out[statement_index];
|
||||
let def_s = ir_statement
|
||||
.vr_definitions()
|
||||
.iter()
|
||||
.map(|d| *d)
|
||||
.collect::<HashSet<_>>();
|
||||
let def_s = ir_statement.vr_definitions();
|
||||
let rhs = out_s - &def_s;
|
||||
let new_ins = use_s.union(&rhs).map(|v| *v).collect::<HashSet<_>>();
|
||||
|
||||
@ -66,11 +57,16 @@ pub fn block_interference_graph(
|
||||
ir_block: &IrBlock,
|
||||
spilled: &HashSet<IrVariableId>,
|
||||
) -> 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();
|
||||
for statement in ir_block.statements() {
|
||||
all_vr_variables.extend(statement.vr_definitions());
|
||||
all_vr_variables.extend(statement.vr_uses());
|
||||
let definitions = statement.vr_definitions();
|
||||
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
|
||||
@ -84,6 +80,11 @@ pub fn block_interference_graph(
|
||||
for (statement_index, ir_statement) in ir_block.statements().iter().enumerate() {
|
||||
let statement_live_out = &live_out[statement_index];
|
||||
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 {
|
||||
// we do the following check to avoid adding an edge to itself
|
||||
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 (registers, new_spills) = registers_and_spills(&mut interference_graph, register_count);
|
||||
|
||||
if spilled != new_spills {
|
||||
spilled = new_spills; // todo: figure out if this works algorithmically
|
||||
} else {
|
||||
let old_n_spilled = spilled.len();
|
||||
spilled.extend(new_spills);
|
||||
// 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> =
|
||||
HashMap::new();
|
||||
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 {
|
||||
fn vr_definitions(&self) -> HashSet<IrVariableId> {
|
||||
HashSet::new()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
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)]
|
||||
@ -160,7 +138,7 @@ struct WorkItem {
|
||||
color: bool,
|
||||
}
|
||||
|
||||
pub fn registers_and_spills(
|
||||
fn registers_and_spills(
|
||||
interference_graph: &mut InterferenceGraph,
|
||||
k: usize,
|
||||
) -> (
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
use crate::ir::ir_variable::IrVariableId;
|
||||
use crate::ir::register_allocation::RegisterAssignment;
|
||||
use dvm_lib::instruction::StackFrameOffset;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type StackVariableOffset = isize;
|
||||
|
||||
pub enum VariableLocation {
|
||||
Register(RegisterAssignment),
|
||||
Stack(StackFrameOffset),
|
||||
Stack(StackVariableOffset),
|
||||
}
|
||||
|
||||
pub struct VariableLocations {
|
||||
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
||||
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
|
||||
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
|
||||
}
|
||||
|
||||
impl VariableLocations {
|
||||
pub fn new(
|
||||
register_variables: HashMap<IrVariableId, RegisterAssignment>,
|
||||
stack_variables: HashMap<IrVariableId, StackFrameOffset>,
|
||||
stack_variables: HashMap<IrVariableId, StackVariableOffset>,
|
||||
) -> Self {
|
||||
Self {
|
||||
register_variables,
|
||||
|
||||
@ -161,10 +161,7 @@ fn lower_to_ir_function(function: &Function, ctx: &mut LowerToIrContext) {
|
||||
|
||||
let ir_function = IrFunction::new(
|
||||
function_symbol.fqn_owned(),
|
||||
lower_to_ir_parameters(function, ctx)
|
||||
.into_iter()
|
||||
.map(|ir_parameter| Rc::new(ir_parameter))
|
||||
.collect(),
|
||||
lower_to_ir_parameters(function, ctx),
|
||||
fn_ctx.ir_variables,
|
||||
return_type_info_to_ir_type_info(return_type_info),
|
||||
fn_ctx.blocks,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user