diff --git a/reid/examples/reid/arithmetic.reid b/reid/examples/reid/arithmetic.reid index 20fcde6..d80436b 100644 --- a/reid/examples/reid/arithmetic.reid +++ b/reid/examples/reid/arithmetic.reid @@ -9,5 +9,5 @@ fn main() { return 3; } - return test + simpleSub; + return arithmetic + simpleSub + boop; } \ No newline at end of file diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 2180d32..23cd825 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -316,11 +316,13 @@ impl ast::Block { Ok(t) => InferredType::Static(*t, s_let.2), Err(e) => InferredType::DownstreamError(e.clone(), s_let.2), }; - scope.set_var(VirtualVariable { - name: s_let.0.clone(), - inferred, - meta: s_let.2.into(), - }); + state + .note(scope.set_var(VirtualVariable { + name: s_let.0.clone(), + inferred, + meta: s_let.2.into(), + })) + .ok(); ( collapsed.ok().and_then(|t| { @@ -356,6 +358,7 @@ impl ast::Block { if let Some(expr) = r.1.process(state, scope) { Some((r.0.into(), Box::new(expr))) } else { + state.fatal = true; None? } } else { diff --git a/reid/src/old_codegen/llvm.rs b/reid/src/old_codegen/llvm.rs deleted file mode 100644 index 1b74f7b..0000000 --- a/reid/src/old_codegen/llvm.rs +++ /dev/null @@ -1,287 +0,0 @@ -use std::borrow::BorrowMut; -use std::ffi::{CStr, CString}; -use std::mem; -use std::ptr::null_mut; - -use llvm_sys::analysis::LLVMVerifyModule; -use llvm_sys::transforms::pass_manager_builder::{ - self, LLVMOpaquePassManagerBuilder, LLVMPassManagerBuilderCreate, - LLVMPassManagerBuilderSetOptLevel, -}; -use llvm_sys::{ - core::*, prelude::*, LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue, -}; - -use crate::parser; - -fn into_cstring>(value: T) -> CString { - let string = value.into(); - unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Type mismatch: {0:?} vs {1:?}")] - TypeMismatch(IRType, IRType), -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum IRType { - I32, - Boolean, -} - -impl IRType { - fn in_context(&self, context: &IRContext) -> *mut LLVMType { - use IRType::*; - unsafe { - return match self { - I32 => LLVMInt32TypeInContext(context.context), - Boolean => LLVMInt1TypeInContext(context.context), - }; - } - } -} - -#[derive(Clone)] -pub struct IRValue(pub IRType, *mut LLVMValue); - -impl IRValue { - pub fn from_literal(literal: &parser::Literal, module: &IRModule) -> Self { - use parser::Literal; - match literal { - Literal::I32(v) => { - let ir_type = IRType::I32; - unsafe { - let ir_value = LLVMConstInt( - ir_type.in_context(module.context), - mem::transmute(*v as i64), - 1, - ); - return IRValue(ir_type, ir_value); - } - } - }; - } -} - -pub struct IRContext { - context: *mut LLVMContext, - builder: *mut LLVMBuilder, -} - -impl IRContext { - pub fn new() -> IRContext { - unsafe { - // Set up a context, module and builder in that context. - let context = LLVMContextCreate(); - let builder = LLVMCreateBuilderInContext(context); - IRContext { context, builder } - } - } - - pub fn module<'a>(&'a mut self, name: String) -> IRModule<'a> { - IRModule::new(self, name) - } -} - -impl Drop for IRContext { - fn drop(&mut self) { - // Clean up. Values created in the context mostly get cleaned up there. - unsafe { - LLVMDisposeBuilder(self.builder); - LLVMContextDispose(self.context); - } - } -} - -pub struct IRModule<'a> { - context: &'a mut IRContext, - module: *mut LLVMModule, -} - -impl<'a> IRModule<'a> { - fn new<'b: 'a>(context: &'b mut IRContext, name: String) -> IRModule<'a> { - unsafe { - let module = - LLVMModuleCreateWithNameInContext(into_cstring(name).as_ptr(), context.context); - - IRModule { context, module } - } - } - - pub fn print_to_string(&mut self) -> Result<&str, std::str::Utf8Error> { - unsafe { - LLVMVerifyModule( - self.module, - llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction, - null_mut(), - ); - CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str() - } - } -} - -impl<'a> Drop for IRModule<'a> { - fn drop(&mut self) { - // Clean up. Values created in the context mostly get cleaned up there. - unsafe { - LLVMDisposeModule(self.module); - } - } -} - -pub struct IRFunction<'a, 'b> { - pub module: &'b IRModule<'a>, - /// The actual function - value: *mut LLVMValue, -} - -impl<'a, 'b> IRFunction<'a, 'b> { - pub fn new(name: &String, module: &'b IRModule<'a>) -> IRFunction<'a, 'b> { - unsafe { - // TODO, fix later! - - let return_type = LLVMInt32TypeInContext(module.context.context); - let mut argts = []; - let func_type = - LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0); - - let function = LLVMAddFunction(module.module, into_cstring(name).as_ptr(), func_type); - - IRFunction { - module, - value: function, - } - } - } -} - -pub struct IRBlock<'a, 'b, 'c> { - pub function: &'c IRFunction<'a, 'b>, - blockref: *mut LLVMBasicBlock, -} - -impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> { - pub fn new(function: &'c IRFunction<'a, 'b>, name: &CStr) -> IRBlock<'a, 'b, 'c> { - unsafe { - let blockref = - LLVMCreateBasicBlockInContext(function.module.context.context, name.as_ptr()); - - IRBlock { function, blockref } - } - } - - pub fn add( - &mut self, - IRValue(lhs_t, lhs_v): IRValue, - IRValue(rhs_t, rhs_v): IRValue, - ) -> Result { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - if lhs_t == rhs_t { - Ok(IRValue( - lhs_t, - LLVMBuildAdd( - self.function.module.context.builder, - lhs_v, - rhs_v, - c"tmpadd".as_ptr(), - ), - )) - } else { - Err(Error::TypeMismatch(lhs_t, rhs_t)) - } - } - } - - pub fn mult( - &mut self, - IRValue(lhs_t, lhs_v): IRValue, - IRValue(rhs_t, rhs_v): IRValue, - ) -> Result { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - if lhs_t == rhs_t { - Ok(IRValue( - lhs_t, - LLVMBuildMul( - self.function.module.context.builder, - lhs_v, - rhs_v, - c"tmpadd".as_ptr(), - ), - )) - } else { - Err(Error::TypeMismatch(lhs_t, rhs_t)) - } - } - } - - pub fn less_than( - &mut self, - IRValue(lhs_t, lhs_v): IRValue, - IRValue(rhs_t, rhs_v): IRValue, - ) -> Result { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - if lhs_t == rhs_t { - Ok(IRValue( - IRType::Boolean, - LLVMBuildICmp( - self.function.module.context.builder, - llvm_sys::LLVMIntPredicate::LLVMIntULT, - lhs_v, - rhs_v, - c"IntULT".as_ptr(), - ), - )) - } else { - Err(Error::TypeMismatch(lhs_t, rhs_t)) - } - } - } - - pub fn add_return(&mut self, value: Option) { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - if let Some(IRValue(_, value)) = value { - LLVMBuildRet(self.function.module.context.builder, value); - } else { - LLVMBuildRetVoid(self.function.module.context.builder); - } - } - } - - pub fn branch( - &mut self, - IRValue(_, condition): IRValue, - then_block: &mut IRBlock, - else_block: &mut IRBlock, - ) { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - LLVMBuildCondBr( - self.function.module.context.builder, - condition, - then_block.blockref, - else_block.blockref, - ); - } - } - - pub fn move_into(&mut self, block: &mut IRBlock) { - unsafe { - LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref); - LLVMBuildBr(self.function.module.context.builder, block.blockref); - } - } -} - -impl<'a, 'b, 'c> Drop for IRBlock<'a, 'b, 'c> { - fn drop(&mut self) { - unsafe { - LLVMAppendExistingBasicBlock(self.function.value, self.blockref); - } - } -} diff --git a/reid/src/old_codegen/mod.rs b/reid/src/old_codegen/mod.rs deleted file mode 100644 index d709c41..0000000 --- a/reid/src/old_codegen/mod.rs +++ /dev/null @@ -1,176 +0,0 @@ -mod llvm; - -use std::collections::HashMap; - -use llvm::{Error, IRBlock, IRContext, IRFunction, IRModule, IRValue}; - -use crate::{ - parser::{ - Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition, IfExpression, - LetStatement, ReturnType, - }, - TopLevelStatement, -}; - -pub fn form_context() -> IRContext { - IRContext::new() -} - -pub fn from_statements( - context: &mut IRContext, - statements: Vec, -) -> Result { - let mut module = context.module("testmod".to_owned()); - let mut scope = ScopeData::new(); - for statement in statements { - statement.codegen(&mut scope, &mut module); - } - - Ok(module) -} - -impl TopLevelStatement { - fn codegen(&self, scope: &mut ScopeData, module: &mut IRModule) { - match self { - Self::FunctionDefinition(func) => func.codegen(scope, module), - Self::Import(_) => panic!("not implemented"), - } - } -} - -impl FunctionDefinition { - fn codegen(&self, scope: &mut ScopeData, module: &mut IRModule) { - let FunctionDefinition(signature, block, _) = self; - let ir_function = IRFunction::new(&signature.name, module); - - let ir_block = IRBlock::new(&ir_function, c"entry"); - let mut scope = scope.inner(ir_block); - if let Some((_, val)) = block.codegen(&mut scope) { - scope.block.add_return(Some(val)); - } else { - scope.block.add_return(None); - } - } -} - -impl Block { - #[must_use] - fn codegen(&self, scope: &mut Scope) -> Option<(ReturnType, IRValue)> { - for statement in &self.0 { - statement.codegen(scope); - } - - if let Some((ret_type, return_exp)) = &self.1 { - let value = return_exp.codegen(scope); - Some((*ret_type, value)) - } else { - None - } - } -} - -impl BlockLevelStatement { - fn codegen(&self, scope: &mut Scope) { - use BlockLevelStatement::*; - match self { - Expression(exp) | Return(ReturnType::Soft, exp) => { - exp.codegen(scope); - } - Let(LetStatement(name, exp, _)) => { - let val = exp.codegen(scope); - scope.data.insert(name, val); - } - Return(ReturnType::Hard, _) => panic!("hard returns here should not be possible.."), - Import(_) => panic!("block level import not supported"), - } - } -} - -impl Expression { - fn codegen(&self, scope: &mut Scope) -> IRValue { - let Expression(kind, _) = self; - - use ExpressionKind::*; - match kind { - Literal(lit) => IRValue::from_literal(lit, &scope.block.function.module), - VariableName(v) => scope.data.fetch(v), - Binop(op, lhs, rhs) => { - let lhs = lhs.codegen(scope); - let rhs = rhs.codegen(scope); - use crate::parser::BinaryOperator::*; - match op { - Add => scope.block.add(lhs, rhs).unwrap(), - Mult => scope.block.mult(lhs, rhs).unwrap(), - LessThan => scope.block.less_than(lhs, rhs).unwrap(), - _ => panic!("operator not supported: {:?}", op), - } - } - IfExpr(ifx) => { - let IfExpression(expr, block, _) = ifx.as_ref(); - let condition = expr.codegen(scope); - - let mut thenb = IRBlock::new(scope.block.function, c"then"); - let mut afterb = IRBlock::new(scope.block.function, c"merge"); - - scope.block.branch(condition, &mut thenb, &mut afterb); - scope.block = afterb; - - let mut then = scope.inner(thenb); - match block.codegen(&mut then) { - Some((ReturnType::Hard, v)) => then.block.add_return(Some(v)), - _ => then.block.move_into(&mut scope.block), - } - - IRValue::from_literal(&crate::parser::Literal::I32(1), scope.block.function.module) - } - BlockExpr(_) => panic!("block expr not supported"), - FunctionCall(_) => panic!("function call expr not supported"), - } - } -} - -#[derive(Clone)] -struct ScopeData { - vars: HashMap, -} - -impl ScopeData { - fn new() -> ScopeData { - ScopeData { - vars: HashMap::new(), - } - } - - fn with_block<'a, 'b, 'c>(self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> { - Scope { data: self, block } - } - - fn inner<'a, 'b, 'c>(&self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> { - self.clone().with_block(block) - } - - fn fetch(&self, name: &String) -> IRValue { - match self.vars.get(name) { - Some(val) => val.clone(), - _ => panic!("No such variable in scope: {}", name), - } - } - - fn insert(&mut self, name: &String, value: IRValue) { - match self.vars.insert(name.clone(), value) { - Some(_) => panic!("{} was already defined in scope", name), - _ => {} - } - } -} - -struct Scope<'a, 'b, 'c> { - data: ScopeData, - block: IRBlock<'a, 'b, 'c>, -} - -impl<'a, 'b, 'c> Scope<'a, 'b, 'c> { - fn inner(&self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> { - self.data.clone().with_block(block) - } -} diff --git a/reid/src/old_llvm/codegen.rs b/reid/src/old_llvm/codegen.rs deleted file mode 100644 index 83b1e12..0000000 --- a/reid/src/old_llvm/codegen.rs +++ /dev/null @@ -1,222 +0,0 @@ -use std::collections::{hash_map, HashMap}; - -use crate::{ - ast::{ - BinaryOperator, Block, BlockLevelStatement, Expression, FunctionCallExpression, - FunctionDefinition, FunctionSignature, ReturnType, TopLevelStatement, - }, - llvm_ir::{self, IRBlock, IRFunction, IRModule, IRValue, IRValueType}, -}; - -#[derive(Clone)] -pub struct ScopeData { - named_vars: HashMap, - defined_functions: HashMap)>, -} - -impl ScopeData { - pub fn inner<'a, 'b>(&self, block: &'b mut IRBlock<'a>) -> Scope<'a, 'b> { - Scope { - block, - data: self.clone(), - } - } - - pub fn var(&self, name: &String) -> Option<&IRValue> { - self.named_vars.get(name) - } - - pub fn set_var(&mut self, name: &str, val: IRValue) -> Result<(), Error> { - if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) { - e.insert(val); - Ok(()) - } else { - Err(Error::VariableAlreadyDefined(name.to_owned())) - } - } - - pub fn function( - &mut self, - name: &String, - ) -> Option<&mut (FunctionSignature, Option)> { - self.defined_functions.get_mut(name) - } - - pub fn set_function_signature( - &mut self, - name: &str, - sig: FunctionSignature, - ir: IRFunction, - ) -> Result<(), Error> { - if let hash_map::Entry::Vacant(e) = self.defined_functions.entry(name.to_owned()) { - e.insert((sig, Some(ir))); - Ok(()) - } else { - Err(Error::VariableAlreadyDefined(name.to_owned())) - } - } -} - -pub struct Scope<'a, 'b> { - pub block: &'b mut IRBlock<'a>, - pub data: ScopeData, -} - -impl<'a, 'b> Scope<'a, 'b> { - pub fn inner<'c>(&'c mut self) -> Scope<'a, 'c> { - Scope { - block: self.block, - data: self.data.clone(), - } - } -} - -pub fn codegen_from_statements(statements: Vec) -> Result { - let mut module = IRModule::new("testmod"); - - let mut scope = ScopeData { - defined_functions: HashMap::new(), - named_vars: HashMap::new(), - }; - - for statement in &statements { - match statement { - TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, _)) => { - let function = module.create_func(&sig.name, IRValueType::I32); - scope.set_function_signature(&sig.name.clone(), sig.clone(), function)?; - } - TopLevelStatement::Import(_) => {} - } - } - - for statement in &statements { - statement.codegen(&mut module, &mut scope)?; - } - - Ok(module) -} - -impl TopLevelStatement { - pub fn codegen(&self, module: &mut IRModule, root_data: &mut ScopeData) -> Result<(), Error> { - match self { - TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { - if let Some((_, ir)) = root_data.function(&sig.name) { - if let Some(ir_function) = ir.take() { - let mut ir_block = module.create_block(); - let mut scope = root_data.inner(&mut ir_block); - - let (_, value) = match block.codegen(&mut scope)? { - Some(v) => v, - None => panic!("Void-return type function not yet implemented!"), - }; - - ir_function.add_definition(value, ir_block); - } else { - Err(Error::FunctionAlreadyDefined(sig.name.clone()))? - } - } else { - panic!("Function was not declared before it's definition") - } - } - TopLevelStatement::Import(_) => {} - } - Ok(()) - } -} - -impl Block { - pub fn codegen(&self, scope: &mut Scope) -> Result, Error> { - for statement in &self.0 { - statement.codegen(scope)?; - } - - let value = if let Some((rt, exp)) = &self.1 { - Some((*rt, exp.codegen(scope)?)) - } else { - None - }; - - Ok(value) - } -} - -impl BlockLevelStatement { - pub fn codegen(&self, scope: &mut Scope) -> Result<(), Error> { - match self { - BlockLevelStatement::Let(let_statement) => { - let val = let_statement.1.codegen(scope)?; - scope.data.set_var(&let_statement.0, val)?; - Ok(()) - } - BlockLevelStatement::Return(_) => panic!("Should never happen"), - BlockLevelStatement::Import(_) => Ok(()), // TODO: To implement - BlockLevelStatement::Expression(e) => { - let _value = e.codegen(scope)?; - Ok(()) - } - } - } -} - -impl Expression { - pub fn codegen(&self, scope: &mut Scope) -> Result { - use Expression::*; - match self { - Binop(op, lhs, rhs) => match op { - BinaryOperator::Add => { - let lhs = lhs.codegen(scope)?; - let rhs = rhs.codegen(scope)?; - Ok(scope.block.add(lhs, rhs)?) - } - BinaryOperator::Mult => { - let lhs = lhs.codegen(scope)?; - let rhs = rhs.codegen(scope)?; - Ok(scope.block.mul(lhs, rhs)?) - } - _ => panic!("Other binary operators not supported yet!"), - }, - BlockExpr(block) => { - let mut inner = scope.inner(); - - Ok(match block.codegen(&mut inner)? { - Some((r_type, value)) => match r_type { - ReturnType::Soft => value, - ReturnType::Hard => { - panic!("Hard returns in inner blocks not supported yet") - } - }, - None => panic!("Void-return type block not yet implemented!"), - }) - } - FunctionCall(fc) => { - let FunctionCallExpression(name, _) = &**fc; - if let Some((sig, _)) = scope.data.function(name) { - Ok(scope.block.function_call(sig)?) - } else { - Err(Error::UndefinedFunction(name.clone()))? - } - } - VariableName(name) => scope - .data - .var(name) - .cloned() - .ok_or(Error::UndefinedVariable(name.clone())), - Literal(lit) => Ok(scope.block.get_const(lit)), - IfExpr(_) => panic!("if expressions not yet supported"), - } - } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Variable '{0}' already defined")] - VariableAlreadyDefined(String), - #[error("Variable '{0}' not yet defined")] - UndefinedVariable(String), - #[error("Function '{0}' not defined")] - UndefinedFunction(String), - #[error("Function '{0}' already defined")] - FunctionAlreadyDefined(String), - #[error(transparent)] - Deeper(#[from] llvm_ir::Error), -} diff --git a/reid/src/old_llvm/llvm_ir.rs b/reid/src/old_llvm/llvm_ir.rs deleted file mode 100644 index d0c754f..0000000 --- a/reid/src/old_llvm/llvm_ir.rs +++ /dev/null @@ -1,203 +0,0 @@ -use std::ffi::{CStr, CString}; -use std::mem; - -use llvm_sys::{core::*, prelude::*, LLVMBuilder, LLVMContext, LLVMModule}; - -use crate::ast::{FunctionSignature, Literal}; - -macro_rules! cstr { - ($string:expr) => { - core::ffi::CStr::from_bytes_with_nul_unchecked(concat!($string, "\0").as_bytes()).as_ptr() - }; -} - -#[derive(Clone, Debug)] -#[must_use = "value contains raw pointer and must be inserted somewhere"] -pub struct IRValue(IRValueType, LLVMValueRef); - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum IRValueType { - I32, -} - -impl IRValueType { - unsafe fn get_llvm_type(&self, module: &mut IRModule) -> LLVMTypeRef { - match *self { - Self::I32 => LLVMInt32TypeInContext(module.context), - } - } -} - -fn into_cstring>(value: T) -> CString { - let string = value.into(); - unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) } -} - -pub struct IRModule { - context: *mut LLVMContext, - module: *mut LLVMModule, - builder: *mut LLVMBuilder, -} - -impl IRModule { - pub fn new>(name: T) -> IRModule { - unsafe { - // Set up a context, module and builder in that context. - let context = LLVMContextCreate(); - let module = LLVMModuleCreateWithNameInContext(into_cstring(name).as_ptr(), context); - let builder = LLVMCreateBuilderInContext(context); - - IRModule { - context, - module, - builder, - } - } - } - - pub fn create_block(&mut self) -> IRBlock { - IRBlock::create("entry", self) - } - - pub fn create_func>( - &mut self, - name: T, - return_type: IRValueType, - ) -> IRFunction { - unsafe { - let mut argts = []; - let func_type = LLVMFunctionType( - return_type.get_llvm_type(self), - argts.as_mut_ptr(), - argts.len() as u32, - 0, - ); - - let anon_func = LLVMAddFunction(self.module, into_cstring(name).as_ptr(), func_type); - IRFunction { - value: IRValue(return_type, anon_func), - } - } - } - - pub fn print_to_string(&mut self) -> Result<&str, std::str::Utf8Error> { - unsafe { CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str() } - } -} - -impl Drop for IRModule { - fn drop(&mut self) { - // Clean up. Values created in the context mostly get cleaned up there. - unsafe { - LLVMDisposeBuilder(self.builder); - LLVMDisposeModule(self.module); - LLVMContextDispose(self.context); - } - } -} - -#[derive(Clone, Debug)] -pub struct IRFunction { - value: IRValue, -} - -impl IRFunction { - pub fn add_definition(self, ret: IRValue, block: IRBlock) { - unsafe { - LLVMAppendExistingBasicBlock(self.value.1, block.blockref); - LLVMBuildRet(block.module.builder, ret.1); - } - } -} - -pub struct IRBlock<'a> { - module: &'a mut IRModule, - blockref: LLVMBasicBlockRef, -} - -impl<'a> IRBlock<'a> { - fn create>(name: T, codegen: &'a mut IRModule) -> IRBlock<'a> { - unsafe { - let blockref = - LLVMCreateBasicBlockInContext(codegen.context, into_cstring(name).as_ptr()); - LLVMPositionBuilderAtEnd(codegen.builder, blockref); - IRBlock { - module: codegen, - blockref, - } - } - } - - pub fn get_const(&mut self, literal_type: &Literal) -> IRValue { - unsafe { - match *literal_type { - Literal::I32(v) => IRValue( - IRValueType::I32, - LLVMConstInt( - LLVMInt32TypeInContext(self.module.context), - mem::transmute(v as i64), - 1, - ), - ), - } - } - } - - pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result { - unsafe { - if lhs.0 == rhs.0 { - Ok(IRValue( - lhs.0, - LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), - )) - } else { - Err(Error::TypeMismatch(lhs.0, rhs.0)) - } - } - } - - pub fn mul(&mut self, lhs: IRValue, rhs: IRValue) -> Result { - unsafe { - if lhs.0 == rhs.0 { - Ok(IRValue( - lhs.0, - LLVMBuildMul(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), - )) - } else { - Err(Error::TypeMismatch(lhs.0, rhs.0)) - } - } - } - - pub fn function_call(&mut self, callee: &FunctionSignature) -> Result { - unsafe { - let function = LLVMGetNamedFunction( - self.module.module, - into_cstring(callee.name.clone()).as_ptr(), - ); - - let ret_t = LLVMInt32TypeInContext(self.module.context); - let mut argts = []; - let mut args = []; - - let fun_t = LLVMFunctionType(ret_t, argts.as_mut_ptr(), argts.len() as u32, 0); - - let call = LLVMBuildCall2( - self.module.builder, - fun_t, - function, - args.as_mut_ptr(), - args.len() as u32, - into_cstring(&callee.name).as_ptr(), - ); - - Ok(IRValue(IRValueType::I32, call)) - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Type Mismatch: {0:?} {1:?}")] - TypeMismatch(IRValueType, IRValueType), -}