(broken) add part 1 of mutability
This commit is contained in:
		
							parent
							
								
									85b2ebf04a
								
							
						
					
					
						commit
						14e0dcbe15
					
				| @ -3,6 +3,8 @@ | ||||
| 
 | ||||
| use std::{cell::RefCell, rc::Rc}; | ||||
| 
 | ||||
| use llvm_sys::core::{LLVMBuildAlloca, LLVMBuildLoad2, LLVMBuildStore}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     BlockData, ConstValue, FunctionData, Instr, InstructionData, ModuleData, TerminatorKind, Type, | ||||
|     util::match_types, | ||||
| @ -250,6 +252,29 @@ impl Builder { | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|                 Alloca(_, _) => Ok(()), | ||||
|                 Load(ptr, _) => { | ||||
|                     if let Ok(ty) = ptr.get_type(&self) { | ||||
|                         if let Type::Ptr(_) = ty { | ||||
|                             Ok(()) | ||||
|                         } else { | ||||
|                             Err(()) | ||||
|                         } | ||||
|                     } else { | ||||
|                         Err(()) | ||||
|                     } | ||||
|                 } | ||||
|                 Store(ptr, _) => { | ||||
|                     if let Ok(ty) = ptr.get_type(&self) { | ||||
|                         if let Type::Ptr(_) = ty { | ||||
|                             Ok(()) | ||||
|                         } else { | ||||
|                             Err(()) | ||||
|                         } | ||||
|                     } else { | ||||
|                         Err(()) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -298,7 +323,7 @@ impl InstructionValue { | ||||
|                     .function_data(&self.0.0) | ||||
|                     .params | ||||
|                     .get(*nth) | ||||
|                     .copied() | ||||
|                     .cloned() | ||||
|                     .ok_or(()), | ||||
|                 Constant(c) => Ok(c.get_type()), | ||||
|                 Add(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
| @ -308,6 +333,9 @@ impl InstructionValue { | ||||
|                 ICmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), | ||||
|                 Phi(values) => values.first().ok_or(()).and_then(|v| v.get_type(&builder)), | ||||
|                 Alloca(_, ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 Load(_, ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 Store(_, value) => value.get_type(builder), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -347,6 +375,7 @@ impl Type { | ||||
|             Type::U128 => true, | ||||
|             Type::Bool => true, | ||||
|             Type::Void => false, | ||||
|             Type::Ptr(_) => false, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -364,6 +393,7 @@ impl Type { | ||||
|             Type::U128 => false, | ||||
|             Type::Bool => false, | ||||
|             Type::Void => false, | ||||
|             Type::Ptr(_) => false, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -333,6 +333,22 @@ impl InstructionHolder { | ||||
|                     ); | ||||
|                     phi | ||||
|                 } | ||||
|                 Alloca(name, ty) => LLVMBuildAlloca( | ||||
|                     module.builder_ref, | ||||
|                     ty.as_llvm(module.context_ref), | ||||
|                     into_cstring(name).as_ptr(), | ||||
|                 ), | ||||
|                 Load(ptr, ty) => LLVMBuildLoad2( | ||||
|                     module.builder_ref, | ||||
|                     ty.as_llvm(module.context_ref), | ||||
|                     module.values.get(&ptr).unwrap().value_ref, | ||||
|                     c"load".as_ptr(), | ||||
|                 ), | ||||
|                 Store(ptr, val) => LLVMBuildStore( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(&val).unwrap().value_ref, | ||||
|                     module.values.get(&ptr).unwrap().value_ref, | ||||
|                 ), | ||||
|             } | ||||
|         }; | ||||
|         LLVMValue { | ||||
| @ -428,6 +444,7 @@ impl Type { | ||||
|                 I128 | U128 => LLVMInt128TypeInContext(context), | ||||
|                 Bool => LLVMInt1TypeInContext(context), | ||||
|                 Void => LLVMVoidType(), | ||||
|                 Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -97,6 +97,9 @@ impl Debug for Instr { | ||||
|             Self::Phi(val) => fmt_call(f, &"Phi", &val), | ||||
|             Self::ICmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs), | ||||
|             Self::FunctionCall(fun, params) => fmt_call(f, fun, params), | ||||
|             Instr::Alloca(name, ty) => write!(f, "alloca<{:?}>({})", ty, name), | ||||
|             Instr::Load(val, ty) => write!(f, "load<{:?}>({:?})", ty, val), | ||||
|             Instr::Store(ptr, val) => write!(f, "store({:?} = {:?})", ptr, val), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -174,13 +174,17 @@ pub enum Instr { | ||||
|     And(InstructionValue, InstructionValue), | ||||
|     Phi(Vec<InstructionValue>), | ||||
| 
 | ||||
|     Alloca(String, Type), | ||||
|     Load(InstructionValue, Type), | ||||
|     Store(InstructionValue, InstructionValue), | ||||
| 
 | ||||
|     /// Integer Comparison
 | ||||
|     ICmp(CmpPredicate, InstructionValue, InstructionValue), | ||||
| 
 | ||||
|     FunctionCall(FunctionValue, Vec<InstructionValue>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Hash)] | ||||
| pub enum Type { | ||||
|     I8, | ||||
|     I16, | ||||
| @ -194,6 +198,7 @@ pub enum Type { | ||||
|     U128, | ||||
|     Bool, | ||||
|     Void, | ||||
|     Ptr(Box<Type>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Hash)] | ||||
|  | ||||
| @ -133,7 +133,7 @@ pub struct Block( | ||||
| pub enum BlockLevelStatement { | ||||
|     Let(LetStatement), | ||||
|     /// Try to set a variable to a specified expression value
 | ||||
|     Set(String, Expression), | ||||
|     Set(String, Expression, TokenRange), | ||||
|     Import { | ||||
|         _i: ImportStatement, | ||||
|     }, | ||||
|  | ||||
| @ -363,8 +363,8 @@ impl Parse for BlockLevelStatement { | ||||
|                 Stmt::Return(ReturnType::Hard, exp) | ||||
|             } | ||||
|             _ => { | ||||
|                 if let Ok(SetStatement(ident, expr)) = stream.parse() { | ||||
|                     Stmt::Set(ident, expr) | ||||
|                 if let Ok(SetStatement(ident, expr, range)) = stream.parse() { | ||||
|                     Stmt::Set(ident, expr, range) | ||||
|                 } else { | ||||
|                     if let Ok(e) = stream.parse() { | ||||
|                         if stream.expect(Token::Semi).is_ok() { | ||||
| @ -382,7 +382,7 @@ impl Parse for BlockLevelStatement { | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetStatement(String, Expression); | ||||
| pub struct SetStatement(String, Expression, TokenRange); | ||||
| 
 | ||||
| impl Parse for SetStatement { | ||||
|     fn parse(mut stream: TokenStream) -> Result<Self, Error> { | ||||
| @ -390,7 +390,7 @@ impl Parse for SetStatement { | ||||
|             stream.expect(Token::Equals)?; | ||||
|             let expr = stream.parse()?; | ||||
|             stream.expect(Token::Semi)?; | ||||
|             Ok(Self(ident, expr)) | ||||
|             Ok(Self(ident, expr, stream.get_range().unwrap())) | ||||
|         } else { | ||||
|             Err(stream.expected_err("identifier")?)? | ||||
|         } | ||||
|  | ||||
| @ -70,11 +70,22 @@ impl ast::Block { | ||||
|                             s_let.0.clone(), | ||||
|                             s_let.4.into(), | ||||
|                         ), | ||||
|                         s_let.2, | ||||
|                         s_let.3.process(), | ||||
|                     ), | ||||
|                     s_let.4, | ||||
|                 ), | ||||
|                 ast::BlockLevelStatement::Set(_, expression) => todo!(), | ||||
|                 ast::BlockLevelStatement::Set(name, expression, range) => ( | ||||
|                     StmtKind::Set( | ||||
|                         VariableReference( | ||||
|                             mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||
|                             name.clone(), | ||||
|                             (*range).into(), | ||||
|                         ), | ||||
|                         expression.process(), | ||||
|                     ), | ||||
|                     *range, | ||||
|                 ), | ||||
|                 ast::BlockLevelStatement::Import { _i } => todo!(), | ||||
|                 ast::BlockLevelStatement::Expression(e) => (StmtKind::Expression(e.process()), e.1), | ||||
|                 ast::BlockLevelStatement::Return(_, e) => (StmtKind::Expression(e.process()), e.1), | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| use std::{collections::HashMap, mem}; | ||||
| 
 | ||||
| use llvm_sys::core::LLVMBuildStore; | ||||
| use reid_lib::{ | ||||
|     Block, CmpPredicate, ConstValue, Context, Function, Instr, Module, TerminatorKind as Term, | ||||
|     Type, builder::InstructionValue, | ||||
|     builder::InstructionValue, Block, CmpPredicate, ConstValue, Context, Function, Instr, Module, | ||||
|     TerminatorKind as Term, Type, | ||||
| }; | ||||
| 
 | ||||
| use crate::mir::{self, TypeKind, VariableReference, types::ReturnType}; | ||||
| use crate::mir::{self, types::ReturnType, TypeKind, VariableReference}; | ||||
| 
 | ||||
| /// Context that contains all of the given modules as complete codegenerated
 | ||||
| /// LLIR that can then be finally compiled into LLVM IR.
 | ||||
| @ -73,8 +74,14 @@ impl mir::Module { | ||||
|             let mut entry = function.block("entry"); | ||||
| 
 | ||||
|             let mut stack_values = HashMap::new(); | ||||
|             for (i, (p_name, _)) in mir_function.parameters.iter().enumerate() { | ||||
|                 stack_values.insert(p_name.clone(), entry.build(Instr::Param(i)).unwrap()); | ||||
|             for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() { | ||||
|                 stack_values.insert( | ||||
|                     p_name.clone(), | ||||
|                     StackValue( | ||||
|                         StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()), | ||||
|                         p_ty.get_type(), | ||||
|                     ), | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             let mut scope = Scope { | ||||
| @ -114,7 +121,16 @@ pub struct Scope<'ctx, 'a> { | ||||
|     function: &'ctx Function<'ctx>, | ||||
|     block: Block<'ctx>, | ||||
|     functions: &'a HashMap<String, Function<'ctx>>, | ||||
|     stack_values: HashMap<String, InstructionValue>, | ||||
|     stack_values: HashMap<String, StackValue>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||
| pub struct StackValue(StackValueKind, Type); | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||||
| pub enum StackValueKind { | ||||
|     Immutable(InstructionValue), | ||||
|     Mutable(InstructionValue), | ||||
| } | ||||
| 
 | ||||
| impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
| @ -141,11 +157,33 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
| impl mir::Statement { | ||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option<InstructionValue> { | ||||
|         match &self.0 { | ||||
|             mir::StmtKind::Let(VariableReference(_, name, _), expression) => { | ||||
|             mir::StmtKind::Let(VariableReference(ty, name, _), mutable, expression) => { | ||||
|                 let value = expression.codegen(scope).unwrap(); | ||||
|                 scope.stack_values.insert(name.clone(), value); | ||||
|                 scope.stack_values.insert( | ||||
|                     name.clone(), | ||||
|                     StackValue( | ||||
|                         match mutable { | ||||
|                             true => StackValueKind::Mutable(value), | ||||
|                             false => StackValueKind::Immutable(value), | ||||
|                         }, | ||||
|                         ty.get_type(), | ||||
|                     ), | ||||
|                 ); | ||||
|                 None | ||||
|             } | ||||
|             mir::StmtKind::Set(var, val) => { | ||||
|                 if let Some(StackValue(kind, ty)) = scope.stack_values.get(&var.1).cloned() { | ||||
|                     match kind { | ||||
|                         StackValueKind::Immutable(ptr) => { | ||||
|                             let expression = val.codegen(scope).unwrap(); | ||||
|                             Some(scope.block.build(Instr::Store(ptr, expression)).unwrap()) | ||||
|                         } | ||||
|                         StackValueKind::Mutable(_) => panic!(""), | ||||
|                     } | ||||
|                 } else { | ||||
|                     panic!("") | ||||
|                 } | ||||
|             } | ||||
|             // mir::StmtKind::If(if_expression) => if_expression.codegen(scope),
 | ||||
|             mir::StmtKind::Import(_) => todo!(), | ||||
|             mir::StmtKind::Expression(expression) => expression.codegen(scope), | ||||
| @ -218,7 +256,12 @@ impl mir::Expression { | ||||
|                     .stack_values | ||||
|                     .get(&varref.1) | ||||
|                     .expect("Variable reference not found?!"); | ||||
|                 Some(v.clone()) | ||||
|                 Some(match v.0 { | ||||
|                     StackValueKind::Immutable(val) => val.clone(), | ||||
|                     StackValueKind::Mutable(val) => { | ||||
|                         scope.block.build(Instr::Load(val, v.1.clone())).unwrap() | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|             mir::ExprKind::Literal(lit) => Some(lit.as_const(&mut scope.block)), | ||||
|             mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { | ||||
|  | ||||
| @ -94,7 +94,16 @@ impl Display for Statement { | ||||
| impl Display for StmtKind { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         match self { | ||||
|             Self::Let(var, block) => write!(f, "let {} = {}", var, block), | ||||
|             Self::Let(var, mutable, block) => { | ||||
|                 write!( | ||||
|                     f, | ||||
|                     "let{} {} = {}", | ||||
|                     if *mutable { " mut" } else { "" }, | ||||
|                     var, | ||||
|                     block | ||||
|                 ) | ||||
|             } | ||||
|             Self::Set(var, expr) => write!(f, "{} = {}", var, expr), | ||||
|             Self::Import(n) => write!(f, "import {}", n), | ||||
|             Self::Expression(exp) => Display::fmt(exp, f), | ||||
|         } | ||||
|  | ||||
| @ -257,8 +257,9 @@ pub struct Statement(pub StmtKind, pub Metadata); | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum StmtKind { | ||||
|     /// Variable name+type, evaluation
 | ||||
|     Let(VariableReference, Expression), | ||||
|     /// Variable name++mutability+type, evaluation
 | ||||
|     Let(VariableReference, bool, Expression), | ||||
|     Set(VariableReference, Expression), | ||||
|     Import(Import), | ||||
|     Expression(Expression), | ||||
| } | ||||
|  | ||||
| @ -253,9 +253,10 @@ impl Block { | ||||
| impl Statement { | ||||
|     fn pass<T: Pass>(&mut self, pass: &mut T, state: &mut State<T::TError>, scope: &mut Scope) { | ||||
|         match &mut self.0 { | ||||
|             StmtKind::Let(_, expression) => { | ||||
|             StmtKind::Let(_, mutable, expression) => { | ||||
|                 expression.pass(pass, state, scope); | ||||
|             } | ||||
|             StmtKind::Set(variable_reference, expression) => {} // TODO
 | ||||
|             StmtKind::Import(_) => todo!(), | ||||
|             StmtKind::Expression(expression) => { | ||||
|                 expression.pass(pass, state, scope); | ||||
| @ -265,10 +266,11 @@ impl Statement { | ||||
|         pass.stmt(self, PassState::from(state, scope)); | ||||
| 
 | ||||
|         match &mut self.0 { | ||||
|             StmtKind::Let(variable_reference, _) => scope | ||||
|             StmtKind::Let(variable_reference, mutable, _) => scope | ||||
|                 .variables | ||||
|                 .set(variable_reference.1.clone(), variable_reference.0) | ||||
|                 .ok(), | ||||
|             StmtKind::Set(variable_reference, expression) => None, // TODO
 | ||||
|             StmtKind::Import(_) => todo!(), | ||||
|             StmtKind::Expression(_) => None, | ||||
|         }; | ||||
|  | ||||
| @ -93,7 +93,8 @@ impl Block { | ||||
| 
 | ||||
|         for statement in &mut self.statements { | ||||
|             let ret = match &mut statement.0 { | ||||
|                 StmtKind::Let(variable_reference, expression) => { | ||||
|                 // TODO
 | ||||
|                 StmtKind::Let(variable_reference, mutable, expression) => { | ||||
|                     let res = expression.typecheck(&mut state, Some(variable_reference.0)); | ||||
| 
 | ||||
|                     // If expression resolution itself was erronous, resolve as
 | ||||
| @ -125,6 +126,7 @@ impl Block { | ||||
|                     state.ok(res, variable_reference.2); | ||||
|                     None | ||||
|                 } | ||||
|                 StmtKind::Set(variable_reference, expression) => None, // TODO
 | ||||
|                 StmtKind::Import(_) => todo!(), | ||||
|                 StmtKind::Expression(expression) => { | ||||
|                     let res = expression.typecheck(&mut state, None); | ||||
|  | ||||
| @ -26,8 +26,9 @@ impl ReturnType for Statement { | ||||
|         use StmtKind::*; | ||||
|         match &self.0 { | ||||
|             Expression(e) => e.return_type(), | ||||
|             Set(_, _) => todo!(), | ||||
|             Import(_) => Err(ReturnTypeOther::Import(self.1.range)), | ||||
|             Let(_, _) => Err(ReturnTypeOther::Let(self.1.range)), | ||||
|             Let(_, _, _) => Err(ReturnTypeOther::Let(self.1.range)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user