Implement codegen for structs
This commit is contained in:
		
							parent
							
								
									d1a37058df
								
							
						
					
					
						commit
						2a879b5ef4
					
				@ -201,10 +201,6 @@ impl ModuleHolder {
 | 
			
		||||
                context.context_ref,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            for _ty in &self.types {
 | 
			
		||||
                todo!("Do something with types!");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Compile the contents
 | 
			
		||||
 | 
			
		||||
            let mut types = HashMap::new();
 | 
			
		||||
 | 
			
		||||
@ -288,4 +288,4 @@ pub enum CustomTypeKind {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
 | 
			
		||||
pub struct NamedStruct(String, Vec<Type>);
 | 
			
		||||
pub struct NamedStruct(pub String, pub Vec<Type>);
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,16 @@
 | 
			
		||||
use std::{collections::HashMap, mem};
 | 
			
		||||
 | 
			
		||||
use reid_lib::{
 | 
			
		||||
    builder::InstructionValue, compile::CompiledModule, Block, CmpPredicate, ConstValue, Context,
 | 
			
		||||
    Function, FunctionFlags, Instr, Module, TerminatorKind as Term, Type,
 | 
			
		||||
    builder::{InstructionValue, TypeValue},
 | 
			
		||||
    compile::CompiledModule,
 | 
			
		||||
    Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
 | 
			
		||||
    Module, NamedStruct, TerminatorKind as Term, Type,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::mir::{self, types::ReturnType, IndexedVariableReference, NamedVariableRef, TypeKind};
 | 
			
		||||
use crate::mir::{
 | 
			
		||||
    self, types::ReturnType, IndexedVariableReference, NamedVariableRef, StructType,
 | 
			
		||||
    TypeDefinitionKind, TypeKind,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Context that contains all of the given modules as complete codegenerated
 | 
			
		||||
/// LLIR that can then be finally compiled into LLVM IR.
 | 
			
		||||
@ -47,20 +52,42 @@ impl mir::Module {
 | 
			
		||||
    fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
 | 
			
		||||
        let mut module = context.module(&self.name, self.is_main);
 | 
			
		||||
 | 
			
		||||
        let mut types = HashMap::new();
 | 
			
		||||
        let mut type_values = HashMap::new();
 | 
			
		||||
 | 
			
		||||
        for typedef in &self.typedefs {
 | 
			
		||||
            let type_value = match &typedef.kind {
 | 
			
		||||
                TypeDefinitionKind::Struct(StructType(fields)) => {
 | 
			
		||||
                    module.custom_type(CustomTypeKind::NamedStruct(NamedStruct(
 | 
			
		||||
                        typedef.name.clone(),
 | 
			
		||||
                        fields
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            // TODO: Reorder custom-type definitions such that
 | 
			
		||||
                            // inner types get evaluated first. Otherwise this
 | 
			
		||||
                            // will cause a panic!
 | 
			
		||||
                            .map(|(_, t)| t.get_type(&type_values))
 | 
			
		||||
                            .collect(),
 | 
			
		||||
                    )))
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            types.insert(type_value, typedef.kind.clone());
 | 
			
		||||
            type_values.insert(typedef.name.clone(), type_value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut functions = HashMap::new();
 | 
			
		||||
 | 
			
		||||
        for function in &self.functions {
 | 
			
		||||
            let param_types: Vec<Type> = function
 | 
			
		||||
                .parameters
 | 
			
		||||
                .iter()
 | 
			
		||||
                .map(|(_, p)| p.get_type())
 | 
			
		||||
                .map(|(_, p)| p.get_type(&type_values))
 | 
			
		||||
                .collect();
 | 
			
		||||
 | 
			
		||||
            let is_main = self.is_main && function.name == "main";
 | 
			
		||||
            let func = match &function.kind {
 | 
			
		||||
                mir::FunctionDefinitionKind::Local(_, _) => module.function(
 | 
			
		||||
                    &function.name,
 | 
			
		||||
                    function.return_type.get_type(),
 | 
			
		||||
                    function.return_type.get_type(&type_values),
 | 
			
		||||
                    param_types,
 | 
			
		||||
                    FunctionFlags {
 | 
			
		||||
                        is_pub: function.is_pub || is_main,
 | 
			
		||||
@ -71,7 +98,7 @@ impl mir::Module {
 | 
			
		||||
                ),
 | 
			
		||||
                mir::FunctionDefinitionKind::Extern(imported) => module.function(
 | 
			
		||||
                    &function.name,
 | 
			
		||||
                    function.return_type.get_type(),
 | 
			
		||||
                    function.return_type.get_type(&type_values),
 | 
			
		||||
                    param_types,
 | 
			
		||||
                    FunctionFlags {
 | 
			
		||||
                        is_extern: true,
 | 
			
		||||
@ -93,7 +120,7 @@ impl mir::Module {
 | 
			
		||||
                    p_name.clone(),
 | 
			
		||||
                    StackValue(
 | 
			
		||||
                        StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()),
 | 
			
		||||
                        p_ty.get_type(),
 | 
			
		||||
                        p_ty.get_type(&type_values),
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
@ -104,6 +131,8 @@ impl mir::Module {
 | 
			
		||||
                function,
 | 
			
		||||
                block: entry,
 | 
			
		||||
                functions: &functions,
 | 
			
		||||
                types: &types,
 | 
			
		||||
                type_values: &type_values,
 | 
			
		||||
                stack_values,
 | 
			
		||||
            };
 | 
			
		||||
            match &mir_function.kind {
 | 
			
		||||
@ -131,6 +160,8 @@ pub struct Scope<'ctx, 'a> {
 | 
			
		||||
    module: &'ctx Module<'ctx>,
 | 
			
		||||
    function: &'ctx Function<'ctx>,
 | 
			
		||||
    block: Block<'ctx>,
 | 
			
		||||
    types: &'a HashMap<TypeValue, TypeDefinitionKind>,
 | 
			
		||||
    type_values: &'a HashMap<String, TypeValue>,
 | 
			
		||||
    functions: &'a HashMap<String, Function<'ctx>>,
 | 
			
		||||
    stack_values: HashMap<String, StackValue>,
 | 
			
		||||
}
 | 
			
		||||
@ -152,6 +183,8 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
 | 
			
		||||
            context: self.context,
 | 
			
		||||
            module: self.module,
 | 
			
		||||
            functions: self.functions,
 | 
			
		||||
            types: self.types,
 | 
			
		||||
            type_values: self.type_values,
 | 
			
		||||
            stack_values: self.stack_values.clone(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -163,6 +196,10 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
 | 
			
		||||
        mem::swap(&mut self.block, &mut old_block);
 | 
			
		||||
        old_block
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_typedef(&self, name: &String) -> Option<&TypeDefinitionKind> {
 | 
			
		||||
        self.type_values.get(name).and_then(|v| self.types.get(v))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IndexedVariableReference {
 | 
			
		||||
@ -184,8 +221,24 @@ impl IndexedVariableReference {
 | 
			
		||||
                    _ => panic!("Tried to codegen indexing a non-indexable value!"),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            mir::IndexedVariableReferenceKind::StructIndex(indexed_variable_reference, _) => {
 | 
			
		||||
                todo!("codegen for indexed var refrence")
 | 
			
		||||
            mir::IndexedVariableReferenceKind::StructIndex(inner, field) => {
 | 
			
		||||
                let (inner_val, mut indices) = inner.get_stack_value(scope)?;
 | 
			
		||||
 | 
			
		||||
                let idx = if let Type::CustomType(ty_val) = inner_val.1 {
 | 
			
		||||
                    match scope.types.get(&ty_val).unwrap() {
 | 
			
		||||
                        TypeDefinitionKind::Struct(struct_type) => struct_type.find_index(field),
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    None
 | 
			
		||||
                }?;
 | 
			
		||||
 | 
			
		||||
                match &inner_val.1 {
 | 
			
		||||
                    Type::Ptr(_) => {
 | 
			
		||||
                        indices.push(idx as u32);
 | 
			
		||||
                        Some((inner_val, indices))
 | 
			
		||||
                    }
 | 
			
		||||
                    _ => panic!("Tried to codegen indexing a non-indexable value!"),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -206,14 +259,17 @@ impl mir::Statement {
 | 
			
		||||
                                _ => StackValueKind::Mutable({
 | 
			
		||||
                                    let alloca = scope
 | 
			
		||||
                                        .block
 | 
			
		||||
                                        .build(Instr::Alloca(name.clone(), ty.get_type()))
 | 
			
		||||
                                        .build(Instr::Alloca(
 | 
			
		||||
                                            name.clone(),
 | 
			
		||||
                                            ty.get_type(scope.type_values),
 | 
			
		||||
                                        ))
 | 
			
		||||
                                        .unwrap();
 | 
			
		||||
                                    scope.block.build(Instr::Store(alloca, value)).unwrap();
 | 
			
		||||
                                    alloca
 | 
			
		||||
                                }),
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                        ty.get_type(),
 | 
			
		||||
                        ty.get_type(scope.type_values),
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
                None
 | 
			
		||||
@ -398,7 +454,7 @@ impl mir::Expression {
 | 
			
		||||
                Some(
 | 
			
		||||
                    scope
 | 
			
		||||
                        .block
 | 
			
		||||
                        .build(Instr::Load(ptr, val_t.get_type()))
 | 
			
		||||
                        .build(Instr::Load(ptr, val_t.get_type(scope.type_values)))
 | 
			
		||||
                        .unwrap(),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
@ -416,7 +472,7 @@ impl mir::Expression {
 | 
			
		||||
                let array = scope
 | 
			
		||||
                    .block
 | 
			
		||||
                    .build(Instr::ArrayAlloca(
 | 
			
		||||
                        instr_t.get_type(),
 | 
			
		||||
                        instr_t.get_type(scope.type_values),
 | 
			
		||||
                        instr_list.len() as u32,
 | 
			
		||||
                    ))
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
@ -431,10 +487,49 @@ impl mir::Expression {
 | 
			
		||||
 | 
			
		||||
                Some(array)
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::StructIndex(expression, type_kind, _) => {
 | 
			
		||||
                todo!("codegen for struct index")
 | 
			
		||||
            mir::ExprKind::StructIndex(expression, type_kind, field) => {
 | 
			
		||||
                let struct_val = expression.codegen(scope)?;
 | 
			
		||||
 | 
			
		||||
                let struct_ty = expression.return_type().ok()?.1.known().ok()?;
 | 
			
		||||
                let TypeKind::CustomType(name) = struct_ty else {
 | 
			
		||||
                    return None;
 | 
			
		||||
                };
 | 
			
		||||
                let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&name)?;
 | 
			
		||||
                let idx = struct_ty.find_index(field)?;
 | 
			
		||||
 | 
			
		||||
                let ptr = scope
 | 
			
		||||
                    .block
 | 
			
		||||
                    .build(Instr::GetStructElemPtr(struct_val, idx as u32))
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
 | 
			
		||||
                Some(
 | 
			
		||||
                    scope
 | 
			
		||||
                        .block
 | 
			
		||||
                        .build(Instr::Load(ptr, type_kind.get_type(scope.type_values)))
 | 
			
		||||
                        .unwrap(),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::Struct(name, items) => {
 | 
			
		||||
                let struct_ptr = scope
 | 
			
		||||
                    .block
 | 
			
		||||
                    .build(Instr::Alloca(
 | 
			
		||||
                        name.clone(),
 | 
			
		||||
                        Type::CustomType(*scope.type_values.get(name)?),
 | 
			
		||||
                    ))
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
 | 
			
		||||
                for (i, (_, exp)) in items.iter().enumerate() {
 | 
			
		||||
                    let elem_ptr = scope
 | 
			
		||||
                        .block
 | 
			
		||||
                        .build(Instr::GetStructElemPtr(struct_ptr, i as u32))
 | 
			
		||||
                        .unwrap();
 | 
			
		||||
                    if let Some(val) = exp.codegen(scope) {
 | 
			
		||||
                        scope.block.build(Instr::Store(elem_ptr, val)).unwrap();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Some(struct_ptr)
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::Struct(_, items) => todo!("codegen for struct expression"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -501,7 +596,7 @@ impl mir::Literal {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypeKind {
 | 
			
		||||
    fn get_type(&self) -> Type {
 | 
			
		||||
    fn get_type(&self, type_vals: &HashMap<String, TypeValue>) -> Type {
 | 
			
		||||
        match &self {
 | 
			
		||||
            TypeKind::I8 => Type::I8,
 | 
			
		||||
            TypeKind::I16 => Type::I16,
 | 
			
		||||
@ -515,10 +610,10 @@ impl TypeKind {
 | 
			
		||||
            TypeKind::U128 => Type::U128,
 | 
			
		||||
            TypeKind::Bool => Type::Bool,
 | 
			
		||||
            TypeKind::StringPtr => Type::Ptr(Box::new(Type::I8)),
 | 
			
		||||
            TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())),
 | 
			
		||||
            TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type(type_vals))),
 | 
			
		||||
            TypeKind::Void => Type::Void,
 | 
			
		||||
            TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
 | 
			
		||||
            TypeKind::CustomType(_) => todo!("codegen for custom type"),
 | 
			
		||||
            TypeKind::CustomType(n) => Type::CustomType(type_vals.get(n).unwrap().clone()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -84,6 +84,16 @@ pub enum VagueType {
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct StructType(pub Vec<(String, TypeKind)>);
 | 
			
		||||
 | 
			
		||||
impl StructType {
 | 
			
		||||
    pub fn find_index(&self, name: &String) -> Option<u32> {
 | 
			
		||||
        self.0
 | 
			
		||||
            .iter()
 | 
			
		||||
            .enumerate()
 | 
			
		||||
            .find(|(_, (n, _))| n == name)
 | 
			
		||||
            .map(|(i, _)| i as u32)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type TypedefMap = HashMap<String, TypeDefinitionKind>;
 | 
			
		||||
 | 
			
		||||
impl TypeKind {
 | 
			
		||||
 | 
			
		||||
@ -300,7 +300,7 @@ impl Statement {
 | 
			
		||||
            StmtKind::Set(_, expression) => {
 | 
			
		||||
                expression.pass(pass, state, scope);
 | 
			
		||||
            }
 | 
			
		||||
            StmtKind::Import(_) => todo!(),
 | 
			
		||||
            StmtKind::Import(_) => {} // Never exists at this stage
 | 
			
		||||
            StmtKind::Expression(expression) => {
 | 
			
		||||
                expression.pass(pass, state, scope);
 | 
			
		||||
            }
 | 
			
		||||
@ -322,7 +322,7 @@ impl Statement {
 | 
			
		||||
                    .ok();
 | 
			
		||||
            }
 | 
			
		||||
            StmtKind::Set(_, _) => {}
 | 
			
		||||
            StmtKind::Import(_) => todo!(),
 | 
			
		||||
            StmtKind::Import(_) => {} // Never exists at this stage
 | 
			
		||||
            StmtKind::Expression(_) => {}
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user