Add stack offset propagation, clean up some deprecated things.
This commit is contained in:
parent
12c4d0eb83
commit
12174c9cf6
@ -64,16 +64,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ir_function in &mut ir_functions {
|
let mut functions: Vec<Function> = vec![];
|
||||||
ir_function.assign_registers(args.register_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut constants_table = ConstantsTable::new();
|
let mut constants_table = ConstantsTable::new();
|
||||||
|
|
||||||
let functions: Vec<Function> = ir_functions
|
for ir_function in &mut ir_functions {
|
||||||
.iter()
|
let (_, stack_size) = ir_function.assign_registers(args.register_count);
|
||||||
.map(|ir_function| ir_function.assemble(&mut constants_table))
|
let function = ir_function.assemble(stack_size, &mut constants_table);
|
||||||
.collect();
|
functions.push(function);
|
||||||
|
}
|
||||||
|
|
||||||
if args.show_asm {
|
if args.show_asm {
|
||||||
for function in &functions {
|
for function in &functions {
|
||||||
|
|||||||
@ -87,14 +87,9 @@ impl Function {
|
|||||||
// handle parameters
|
// handle parameters
|
||||||
symbol_table.push_scope(&format!("parameter_scope({})", self.declared_name));
|
symbol_table.push_scope(&format!("parameter_scope({})", self.declared_name));
|
||||||
let mut parameter_symbols = vec![];
|
let mut parameter_symbols = vec![];
|
||||||
let parameter_count = self.parameters.len();
|
for parameter in &mut self.parameters {
|
||||||
let stack_frame_offset_base = (parameter_count as isize).neg();
|
|
||||||
for (i, parameter) in self.parameters.iter_mut().enumerate() {
|
|
||||||
match parameter.gather_declared_names(symbol_table) {
|
match parameter.gather_declared_names(symbol_table) {
|
||||||
Ok(parameter_symbol) => {
|
Ok(parameter_symbol) => {
|
||||||
parameter_symbol
|
|
||||||
.borrow_mut()
|
|
||||||
.set_stack_frame_offset(stack_frame_offset_base + (i as isize));
|
|
||||||
parameter_symbols.push(parameter_symbol);
|
parameter_symbols.push(parameter_symbol);
|
||||||
}
|
}
|
||||||
Err(mut parameter_diagnostics) => {
|
Err(mut parameter_diagnostics) => {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use dvm_lib::instruction::AddOperand;
|
use dvm_lib::instruction::AddOperand;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@ -68,4 +68,8 @@ impl VrUser for IrAdd {
|
|||||||
self.left.propagate_register_assignments(assignments);
|
self.left.propagate_register_assignments(assignments);
|
||||||
self.right.propagate_register_assignments(assignments);
|
self.right.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op, no definitions here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use dvm_lib::instruction::{Instruction, Location};
|
use dvm_lib::instruction::{Instruction, Location};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -68,6 +68,13 @@ impl VrUser for IrAssign {
|
|||||||
}
|
}
|
||||||
self.initializer.propagate_register_assignments(assignments);
|
self.initializer.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
||||||
|
let mut borrowed_destination = self.destination.borrow_mut();
|
||||||
|
if let IrVariableDescriptor::Stack(stack_variable) = borrowed_destination.descriptor_mut() {
|
||||||
|
stack_variable.set_offset(counter.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrAssign {
|
impl Assemble for IrAssign {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::{HasVrUsers, VrUser};
|
use crate::ir::register_allocation::{HasVrUsers, OffsetCounter, VrUser};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@ -75,6 +75,12 @@ impl VrUser for IrBlock {
|
|||||||
statement.propagate_register_assignments(assignments);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrBlock {
|
impl Assemble for IrBlock {
|
||||||
@ -145,7 +151,7 @@ mod tests {
|
|||||||
|
|
||||||
if let ModuleLevelDeclaration::Function(main) = main {
|
if let ModuleLevelDeclaration::Function(main) = main {
|
||||||
let mut main_ir = main.to_ir(&symbol_table);
|
let mut main_ir = main.to_ir(&symbol_table);
|
||||||
let register_assignments = main_ir.assign_registers(2);
|
let (register_assignments, _) = main_ir.assign_registers(2);
|
||||||
assert_eq!(register_assignments.len(), 4);
|
assert_eq!(register_assignments.len(), 4);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::FunctionSymbol;
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -53,6 +53,10 @@ impl VrUser for IrCall {
|
|||||||
argument.propagate_register_assignments(assignments);
|
argument.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op, because no definitions here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrCall {
|
impl Assemble for IrCall {
|
||||||
@ -74,7 +78,6 @@ impl Assemble for IrCall {
|
|||||||
symbol.parameters().len(),
|
symbol.parameters().len(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// todo: handle function postlude
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::ir::ir_parameter::IrParameter;
|
|||||||
use crate::ir::ir_variable::{
|
use crate::ir::ir_variable::{
|
||||||
IrStackVariableDescriptor, IrVariable, IrVariableDescriptor, IrVrVariableDescriptor,
|
IrStackVariableDescriptor, IrVariable, IrVariableDescriptor, IrVrVariableDescriptor,
|
||||||
};
|
};
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::instruction::{AddOperand, Location, MoveOperand, PushOperand, ReturnOperand};
|
use dvm_lib::instruction::{AddOperand, Location, MoveOperand, PushOperand, ReturnOperand};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -225,4 +225,8 @@ impl VrUser for IrExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,21 +34,21 @@ impl IrFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the register assignments for debugging purposes
|
|
||||||
pub fn assign_registers(
|
pub fn assign_registers(
|
||||||
&mut self,
|
&mut self,
|
||||||
register_count: usize,
|
register_count: usize,
|
||||||
) -> HashMap<IrVrVariableDescriptor, usize> {
|
) -> (HashMap<IrVrVariableDescriptor, usize>, isize) {
|
||||||
self.entry.borrow_mut().assign_registers(register_count)
|
self.entry.borrow_mut().assign_registers(register_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assemble(&self, constants_table: &mut ConstantsTable) -> Function {
|
pub fn assemble(&self, stack_size: isize, constants_table: &mut ConstantsTable) -> Function {
|
||||||
let mut builder = InstructionsBuilder::new();
|
let mut builder = InstructionsBuilder::new();
|
||||||
self.entry.borrow().assemble(&mut builder, constants_table);
|
self.entry.borrow().assemble(&mut builder, constants_table);
|
||||||
let instructions = builder.take_instructions();
|
let instructions = builder.take_instructions();
|
||||||
Function::new(
|
Function::new(
|
||||||
self.function_symbol.borrow().name_owned(),
|
self.function_symbol.borrow().name_owned(),
|
||||||
self.parameters.len(),
|
self.parameters.len(),
|
||||||
|
stack_size,
|
||||||
instructions,
|
instructions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ 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::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
@ -75,4 +75,8 @@ impl VrUser for IrOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@ -44,10 +44,14 @@ impl VrUser for IrReturn {
|
|||||||
ir_expression.propagate_register_assignments(assignments);
|
ir_expression.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrReturn {
|
impl Assemble for IrReturn {
|
||||||
fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable) {
|
fn assemble(&self, builder: &mut InstructionsBuilder, _constants_table: &mut ConstantsTable) {
|
||||||
if let Some(ir_expression) = self.value.as_ref() {
|
if let Some(ir_expression) = self.value.as_ref() {
|
||||||
builder.push(Instruction::SetReturnValue(ir_expression.return_operand()));
|
builder.push(Instruction::SetReturnValue(ir_expression.return_operand()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ 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::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
@ -61,6 +61,20 @@ impl VrUser for IrStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
||||||
|
match self {
|
||||||
|
IrStatement::Assign(ir_assign) => {
|
||||||
|
ir_assign.propagate_stack_offsets(counter);
|
||||||
|
}
|
||||||
|
IrStatement::Call(ir_call) => {
|
||||||
|
ir_call.propagate_stack_offsets(counter);
|
||||||
|
}
|
||||||
|
IrStatement::Return(ir_return) => {
|
||||||
|
ir_return.propagate_stack_offsets(counter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrStatement {
|
impl Assemble for IrStatement {
|
||||||
|
|||||||
@ -139,6 +139,10 @@ impl IrStackVariableDescriptor {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_offset(&mut self, offset: isize) {
|
||||||
|
self.offset = Some(offset);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> isize {
|
pub fn offset(&self) -> isize {
|
||||||
self.offset.unwrap()
|
self.offset.unwrap()
|
||||||
}
|
}
|
||||||
@ -146,6 +150,6 @@ impl IrStackVariableDescriptor {
|
|||||||
|
|
||||||
impl Display for IrStackVariableDescriptor {
|
impl Display for IrStackVariableDescriptor {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}_b{}", self.name, self.block_id)
|
write!(f, "{}_{}", self.name, self.block_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@ pub trait HasVrUsers {
|
|||||||
fn assign_registers(
|
fn assign_registers(
|
||||||
&mut self,
|
&mut self,
|
||||||
register_count: usize,
|
register_count: usize,
|
||||||
) -> HashMap<IrVrVariableDescriptor, usize> {
|
) -> (HashMap<IrVrVariableDescriptor, usize>, isize) {
|
||||||
let mut spills: HashSet<IrVrVariableDescriptor> = HashSet::new();
|
let mut spills: HashSet<IrVrVariableDescriptor> = HashSet::new();
|
||||||
loop {
|
loop {
|
||||||
let mut interference_graph = self.interference_graph();
|
let mut interference_graph = self.interference_graph();
|
||||||
@ -122,7 +122,13 @@ pub trait HasVrUsers {
|
|||||||
for vr_user in self.vr_users_mut() {
|
for vr_user in self.vr_users_mut() {
|
||||||
vr_user.propagate_register_assignments(®isters);
|
vr_user.propagate_register_assignments(®isters);
|
||||||
}
|
}
|
||||||
return registers;
|
// also set offsets
|
||||||
|
let mut offset_counter = OffsetCounter::new();
|
||||||
|
for vr_user in self.vr_users_mut() {
|
||||||
|
vr_user.propagate_stack_offsets(&mut offset_counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (registers, offset_counter.get_count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,6 +142,27 @@ pub trait VrUser {
|
|||||||
&mut self,
|
&mut self,
|
||||||
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
);
|
);
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OffsetCounter {
|
||||||
|
counter: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OffsetCounter {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { counter: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self) -> isize {
|
||||||
|
let offset = self.counter;
|
||||||
|
self.counter += 1;
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_count(&self) -> isize {
|
||||||
|
self.counter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@ -51,9 +51,6 @@ pub struct ParameterSymbol {
|
|||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: TypeInfo,
|
type_info: TypeInfo,
|
||||||
ir_parameter: Option<Rc<IrParameter>>,
|
ir_parameter: Option<Rc<IrParameter>>,
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
stack_frame_offset: Option<isize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParameterSymbol {
|
impl ParameterSymbol {
|
||||||
@ -62,7 +59,6 @@ impl ParameterSymbol {
|
|||||||
name: name.into(),
|
name: name.into(),
|
||||||
type_info,
|
type_info,
|
||||||
ir_parameter: None,
|
ir_parameter: None,
|
||||||
stack_frame_offset: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,25 +81,12 @@ impl ParameterSymbol {
|
|||||||
pub fn ir_parameter(&self) -> &Rc<IrParameter> {
|
pub fn ir_parameter(&self) -> &Rc<IrParameter> {
|
||||||
self.ir_parameter.as_ref().unwrap()
|
self.ir_parameter.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub fn set_stack_frame_offset(&mut self, offset: isize) {
|
|
||||||
self.stack_frame_offset = Some(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
pub fn stack_frame_offset(&self) -> isize {
|
|
||||||
self.stack_frame_offset.unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VariableSymbol {
|
pub struct VariableSymbol {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
type_info: Option<TypeInfo>,
|
type_info: Option<TypeInfo>,
|
||||||
vr_variable: Option<Rc<RefCell<IrVariable>>>,
|
vr_variable: Option<Rc<RefCell<IrVariable>>>,
|
||||||
|
|
||||||
#[deprecated]
|
|
||||||
register: Option<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariableSymbol {
|
impl VariableSymbol {
|
||||||
@ -112,7 +95,6 @@ impl VariableSymbol {
|
|||||||
name: name.into(),
|
name: name.into(),
|
||||||
type_info: None,
|
type_info: None,
|
||||||
vr_variable: None,
|
vr_variable: None,
|
||||||
register: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,14 +125,6 @@ impl VariableSymbol {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("ir_variable not yet initialized")
|
.expect("ir_variable not yet initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_register(&mut self, register: usize) {
|
|
||||||
self.register = Some(register);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register(&self) -> usize {
|
|
||||||
self.register.unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ExpressibleSymbol {
|
pub enum ExpressibleSymbol {
|
||||||
|
|||||||
@ -72,7 +72,7 @@ impl Display for Location {
|
|||||||
write!(f, "r{}", register)
|
write!(f, "r{}", register)
|
||||||
}
|
}
|
||||||
Location::StackFrameOffset(offset) => {
|
Location::StackFrameOffset(offset) => {
|
||||||
if offset.is_positive() {
|
if offset.is_positive() || *offset == 0 {
|
||||||
write!(f, "fp+{}", offset)
|
write!(f, "fp+{}", offset)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "fp{}", offset)
|
write!(f, "fp{}", offset)
|
||||||
|
|||||||
@ -5,14 +5,21 @@ use std::rc::Rc;
|
|||||||
pub struct Function {
|
pub struct Function {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
parameter_count: usize,
|
parameter_count: usize,
|
||||||
|
stack_size: isize,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(name: Rc<str>, parameter_count: usize, instructions: Vec<Instruction>) -> Self {
|
pub fn new(
|
||||||
|
name: Rc<str>,
|
||||||
|
parameter_count: usize,
|
||||||
|
stack_size: isize,
|
||||||
|
instructions: Vec<Instruction>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
parameter_count,
|
parameter_count,
|
||||||
|
stack_size,
|
||||||
instructions,
|
instructions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +36,10 @@ impl Function {
|
|||||||
self.parameter_count
|
self.parameter_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stack_size(&self) -> isize {
|
||||||
|
self.stack_size
|
||||||
|
}
|
||||||
|
|
||||||
pub fn instructions(&self) -> &Vec<Instruction> {
|
pub fn instructions(&self) -> &Vec<Instruction> {
|
||||||
&self.instructions
|
&self.instructions
|
||||||
}
|
}
|
||||||
|
|||||||
@ -234,10 +234,16 @@ pub fn call<'a>(
|
|||||||
call_stack.push(CallFrame::new(function));
|
call_stack.push(CallFrame::new(function));
|
||||||
|
|
||||||
// put each arg on the stack
|
// put each arg on the stack
|
||||||
for argument in arguments {
|
for argument in &arguments {
|
||||||
call_stack.top_mut().stack_mut().push(argument);
|
call_stack.top_mut().stack_mut().push(argument.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure enough stack space
|
||||||
|
call_stack.top_mut().stack_mut().resize(
|
||||||
|
arguments.len() + (function.stack_size() as usize),
|
||||||
|
Value::Null,
|
||||||
|
);
|
||||||
|
|
||||||
while call_stack.maybe_top().is_some()
|
while call_stack.maybe_top().is_some()
|
||||||
&& call_stack.top().ip() < call_stack.top().instructions().len()
|
&& call_stack.top().ip() < call_stack.top().instructions().len()
|
||||||
{
|
{
|
||||||
@ -314,6 +320,12 @@ pub fn call<'a>(
|
|||||||
// push args
|
// push args
|
||||||
call_stack.top_mut().stack_mut().append(&mut args);
|
call_stack.top_mut().stack_mut().append(&mut args);
|
||||||
|
|
||||||
|
// ensure enough stack space
|
||||||
|
call_stack
|
||||||
|
.top_mut()
|
||||||
|
.stack_mut()
|
||||||
|
.resize(arg_count + (function.stack_size() as usize), Value::Null);
|
||||||
|
|
||||||
// set fp for callee frame
|
// set fp for callee frame
|
||||||
let callee_frame = call_stack.top_mut();
|
let callee_frame = call_stack.top_mut();
|
||||||
callee_frame.set_fp(*arg_count);
|
callee_frame.set_fp(*arg_count);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user