Reorder function definition codegen to separate function

This commit is contained in:
Sofia 2025-07-24 14:32:09 +03:00
parent a7795f83db
commit 56b8506f50

View File

@ -1,4 +1,4 @@
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; use std::{cell::RefCell, collections::HashMap, hash::Hash, mem, rc::Rc};
use reid_lib::{ use reid_lib::{
builder::{InstructionValue, TypeValue}, builder::{InstructionValue, TypeValue},
@ -18,9 +18,9 @@ use crate::{
allocator::{Allocator, AllocatorScope}, allocator::{Allocator, AllocatorScope},
lexer::{FullToken, Position}, lexer::{FullToken, Position},
mir::{ mir::{
self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId, self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind,
StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral, Metadata, NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinition,
WhileStatement, TypeDefinitionKind, TypeKind, VagueLiteral, WhileStatement,
}, },
util::try_all, util::try_all,
}; };
@ -88,6 +88,42 @@ pub struct Scope<'ctx, 'scope> {
allocator: Rc<RefCell<Allocator>>, allocator: Rc<RefCell<Allocator>>,
} }
impl<'ctx, 'a> Scope<'ctx, 'a> {
fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> {
Scope {
block,
modules: self.modules,
tokens: self.tokens,
function: self.function,
context: self.context,
module: self.module,
module_id: self.module_id,
functions: self.functions,
types: self.types,
type_values: self.type_values,
stack_values: self.stack_values.clone(),
debug: self.debug.clone(),
allocator: self.allocator.clone(),
}
}
/// Takes the block out from this scope, swaps the given block in it's place
/// and returns the old block.
fn swap_block(&mut self, block: Block<'ctx>) -> Block<'ctx> {
let mut old_block = block;
mem::swap(&mut self.block, &mut old_block);
old_block
}
fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> {
self.type_values.get(key).and_then(|v| self.types.get(v))
}
fn allocate(&self, name: &String, ty: &TypeKind) -> Option<InstructionValue> {
self.allocator.borrow_mut().allocate(name, ty)
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Debug<'ctx> { pub struct Debug<'ctx> {
info: &'ctx DebugInformation, info: &'ctx DebugInformation,
@ -148,40 +184,10 @@ impl StackValueKind {
} }
} }
impl<'ctx, 'a> Scope<'ctx, 'a> { pub struct StackBinopDefinition<'ctx> {
fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> { parameters: ((String, TypeKind), (String, TypeKind)),
Scope { return_ty: TypeKind,
block, ir: Function<'ctx>,
modules: self.modules,
tokens: self.tokens,
function: self.function,
context: self.context,
module: self.module,
module_id: self.module_id,
functions: self.functions,
types: self.types,
type_values: self.type_values,
stack_values: self.stack_values.clone(),
debug: self.debug.clone(),
allocator: self.allocator.clone(),
}
}
/// Takes the block out from this scope, swaps the given block in it's place
/// and returns the old block.
fn swap_block(&mut self, block: Block<'ctx>) -> Block<'ctx> {
let mut old_block = block;
mem::swap(&mut self.block, &mut old_block);
old_block
}
fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> {
self.type_values.get(key).and_then(|v| self.types.get(v))
}
fn allocate(&self, name: &String, ty: &TypeKind) -> Option<InstructionValue> {
self.allocator.borrow_mut().allocate(name, ty)
}
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
@ -285,6 +291,21 @@ impl mir::Module {
insert_debug!(&TypeKind::CustomType(type_key.clone())); insert_debug!(&TypeKind::CustomType(type_key.clone()));
} }
// let mut binops = HashMap::new();
// for binop in &self.binop_defs {
// binops.insert(
// ScopeBinopKey {
// operators: (binop.lhs.1.clone(), binop.rhs.1.clone()),
// commutative: mir::pass::CommutativeKind::True,
// },
// StackBinopDefinition {
// parameters: (binop.lhs.clone(), binop.rhs.clone()),
// return_ty: binop.return_ty.clone(),
// ir: todo!(),
// },
// );
// }
let mut functions = HashMap::new(); let mut functions = HashMap::new();
for function in &self.functions { for function in &self.functions {
@ -332,76 +353,130 @@ impl mir::Module {
for mir_function in &self.functions { for mir_function in &self.functions {
let function = functions.get(&mir_function.name).unwrap(); let function = functions.get(&mir_function.name).unwrap();
match &mir_function.kind {
mir::FunctionDefinitionKind::Local(block, _) => {
let mut entry = function.ir.block("entry"); let mut entry = function.ir.block("entry");
let mut allocator = Allocator::from(
let allocator = match &mir_function.kind {
FunctionDefinitionKind::Local(..) => Allocator::from(
mir_function, mir_function,
&mut AllocatorScope { &mut AllocatorScope {
block: &mut entry, block: &mut entry,
module_id: self.module_id, module_id: self.module_id,
type_values: &type_values, type_values: &type_values,
}, },
); ),
FunctionDefinitionKind::Extern(_) => Allocator::empty(),
FunctionDefinitionKind::Intrinsic(_) => Allocator::empty(),
};
// Insert debug information let mut scope = Scope {
let debug_scope = if let Some(location) = context,
modules: &modules,
tokens,
module: &module,
module_id: self.module_id,
function,
block: entry,
functions: &functions,
types: &types,
type_values: &type_values,
stack_values: HashMap::new(),
debug: Some(Debug {
info: &debug,
scope: compile_unit,
types: &debug_types,
}),
allocator: Rc::new(RefCell::new(allocator)),
};
mir_function
.kind
.codegen(
mir_function.name.clone(),
mir_function.is_pub,
&mut scope,
&mir_function.parameters,
&mir_function.return_type,
&function.ir,
match &mir_function.kind {
FunctionDefinitionKind::Local(..) => {
mir_function.signature().into_debug(tokens, compile_unit) mir_function.signature().into_debug(tokens, compile_unit)
{ }
FunctionDefinitionKind::Extern(_) => None,
FunctionDefinitionKind::Intrinsic(_) => None,
},
)
.unwrap();
}
Ok(ModuleCodegen { module })
}
}
impl FunctionDefinitionKind {
fn codegen<'ctx, 'scope>(
&self,
name: String,
is_pub: bool,
scope: &mut Scope,
parameters: &Vec<(String, TypeKind)>,
return_type: &TypeKind,
ir_function: &Function,
debug_location: Option<DebugLocation>,
) -> Result<(), ErrorKind> {
match &self {
mir::FunctionDefinitionKind::Local(block, _) => {
// Insert debug information
if let Some(debug) = &scope.debug {
if let Some(location) = debug_location {
// let debug_scope = debug.inner_scope(&outer_scope, location); // let debug_scope = debug.inner_scope(&outer_scope, location);
let fn_param_ty = &mir_function.return_type.get_debug_type_hard( let fn_param_ty = &return_type.get_debug_type(&debug, scope);
compile_unit,
&debug,
&debug_types,
&type_values,
&types,
self.module_id,
&self.tokens,
&modules,
);
let debug_ty = let debug_ty =
debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramType { debug
.info
.debug_type(DebugTypeData::Subprogram(DebugSubprogramType {
parameters: vec![*fn_param_ty], parameters: vec![*fn_param_ty],
flags: DwarfFlags, flags: DwarfFlags,
})); }));
let subprogram = debug.subprogram(DebugSubprogramData { let subprogram = debug.info.subprogram(DebugSubprogramData {
name: mir_function.name.clone(), name: name.clone(),
outer_scope: compile_unit.clone(), outer_scope: debug.scope.clone(),
location, location,
ty: debug_ty, ty: debug_ty,
opts: DebugSubprogramOptionals { opts: DebugSubprogramOptionals {
is_local: !mir_function.is_pub, is_local: !is_pub,
is_definition: true, is_definition: true,
..DebugSubprogramOptionals::default() ..DebugSubprogramOptionals::default()
}, },
}); });
function.ir.set_debug(subprogram); ir_function.set_debug(subprogram);
scope.debug = Some(Debug {
Some(subprogram) info: debug.info,
} else { scope: subprogram,
None types: debug.types,
}; });
}
}
// Compile actual IR part // Compile actual IR part
let mut stack_values = HashMap::new(); for (i, (p_name, p_ty)) in parameters.iter().enumerate() {
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
// Codegen actual parameters // Codegen actual parameters
let arg_name = format!("arg.{}", p_name); let arg_name = format!("arg.{}", p_name);
let param = entry let param = scope
.block
.build_named(format!("{}.get", arg_name), Instr::Param(i)) .build_named(format!("{}.get", arg_name), Instr::Param(i))
.unwrap(); .unwrap();
let alloca = allocator.allocate(&p_name, &p_ty).unwrap(); let alloca = scope.allocate(&p_name, &p_ty).unwrap();
entry scope
.block
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
.unwrap(); .unwrap();
stack_values.insert( scope.stack_values.insert(
p_name.clone(), p_name.clone(),
StackValue( StackValue(
StackValueKind::mutable(p_ty.is_mutable(), alloca), StackValueKind::mutable(p_ty.is_mutable(), alloca),
@ -410,10 +485,10 @@ impl mir::Module {
); );
// Generate debug info // Generate debug info
if let (Some(debug_scope), Some(location)) = ( // if let (Some(debug_scope), Some(location)) = (
&debug_scope, // &debug_scope,
mir_function.signature().into_debug(tokens, compile_unit), // mir_function.signature().into_debug(tokens, compile_unit),
) { // ) {
// debug.metadata( // debug.metadata(
// &location, // &location,
// DebugMetadata::ParamVar(DebugParamVariable { // DebugMetadata::ParamVar(DebugParamVariable {
@ -433,33 +508,11 @@ impl mir::Module {
// flags: DwarfFlags, // flags: DwarfFlags,
// }), // }),
// ); // );
// }
} }
}
let mut scope = Scope {
context,
modules: &modules,
tokens,
module: &module,
module_id: self.module_id,
function,
block: entry,
functions: &functions,
types: &types,
type_values: &type_values,
stack_values,
debug: debug_scope.and_then(|scope| {
Some(Debug {
info: &debug,
scope,
types: &debug_types,
})
}),
allocator: Rc::new(RefCell::new(allocator)),
};
let state = State::default(); let state = State::default();
if let Some(ret) = block.codegen(&mut scope, &state)? { if let Some(ret) = block.codegen(scope, &state)? {
scope.block.terminate(Term::Ret(ret.instr())).unwrap(); scope.block.terminate(Term::Ret(ret.instr())).unwrap();
} else { } else {
if !scope.block.delete_if_unused().unwrap() { if !scope.block.delete_if_unused().unwrap() {
@ -469,38 +522,19 @@ impl mir::Module {
} }
} }
if let Some(debug) = scope.debug { if let Some(debug) = &scope.debug {
let location = let location = &block
&block.return_meta().into_debug(tokens, debug.scope).unwrap(); .return_meta()
.into_debug(scope.tokens, debug.scope)
.unwrap();
let location = debug.info.location(&debug.scope, *location); let location = debug.info.location(&debug.scope, *location);
scope.block.set_terminator_location(location).unwrap(); scope.block.set_terminator_location(location).unwrap();
} }
} }
mir::FunctionDefinitionKind::Extern(_) => {} mir::FunctionDefinitionKind::Extern(_) => {}
mir::FunctionDefinitionKind::Intrinsic(kind) => { mir::FunctionDefinitionKind::Intrinsic(kind) => kind.codegen(scope)?,
let entry = function.ir.block("entry");
let mut scope = Scope {
context,
modules: &modules,
tokens,
module: &module,
module_id: self.module_id,
function,
block: entry,
functions: &functions,
types: &types,
type_values: &type_values,
stack_values: Default::default(),
debug: None,
allocator: Rc::new(RefCell::new(Allocator::empty())),
}; };
Ok(())
kind.codegen(&mut scope)?
}
}
}
Ok(ModuleCodegen { module })
} }
} }