diff --git a/src/ast/llvm.rs b/src/ast/llvm.rs index eff7e17..00e286a 100644 --- a/src/ast/llvm.rs +++ b/src/ast/llvm.rs @@ -1,37 +1,82 @@ use anyhow::Result; use inkwell::{ + builder::Builder, context::Context, module::Module, - types::{AnyType, AnyTypeEnum}, + types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicTypeEnum, FunctionType}, + values::{ + AnyValue, AnyValueEnum, BasicValue, BasicValueEnum, FunctionValue, IntValue, + }, }; -use super::{Decl, Type}; +use super::{Decl, Expr, Stmt, Type}; -impl Type { - pub fn into_llvm_type<'ctx>( +impl Expr { + pub fn into_llvm<'ctx>( &self, context: &'ctx Context, - ) -> AnyTypeEnum<'ctx> { + builder: &Builder, + ) -> Result> { match self { - Type::Int => AnyTypeEnum::IntType(context.i64_type()), + Expr::Int(n) => Ok(BasicValueEnum::IntValue( + context.i64_type().const_int(*n as u64, false), + )), } } } +impl Type { + pub fn into_llvm_basic_type<'ctx>( + &self, + context: &'ctx Context, + ) -> BasicTypeEnum<'ctx> { + match self { + Type::Int => BasicTypeEnum::IntType(context.i64_type()), + } + } +} + +fn fn_type_basic<'ctx>( + return_ty: BasicTypeEnum<'ctx>, + args: &[BasicMetadataTypeEnum<'ctx>], + is_var_args: bool, +) -> FunctionType<'ctx> { + match return_ty { + BasicTypeEnum::ArrayType(ty) => ty.fn_type(args, is_var_args), + BasicTypeEnum::FloatType(ty) => ty.fn_type(args, is_var_args), + BasicTypeEnum::IntType(ty) => ty.fn_type(args, is_var_args), + BasicTypeEnum::PointerType(ty) => ty.fn_type(args, is_var_args), + BasicTypeEnum::StructType(ty) => ty.fn_type(args, is_var_args), + BasicTypeEnum::VectorType(ty) => ty.fn_type(args, is_var_args), + } +} + pub fn convert(context: &mut Context, program: Vec) -> Result { let module = context.create_module("program"); let builder = context.create_builder(); for func in program.iter().filter_map(Decl::unwrap_func) { - let return_ty = func.return_ty.into_llvm_type(context); - let llvm_func_ty = return_ty.fn_type(); + let return_ty = func.return_ty.into_llvm_basic_type(context); + let llvm_func_ty = fn_type_basic(return_ty, &[], false); let llvm_func = module.add_function(&func.name, llvm_func_ty, None); let entry_block = context.append_basic_block(llvm_func, "entry"); builder.position_at_end(entry_block); - builder.build_return(None); + for stmt in func.stmts.iter() { + match stmt { + Stmt::Return(ret_val) => { + if let Some(ret_val) = ret_val { + let value = ret_val.into_llvm(context, &builder)?; + builder.build_return(Some(&value)); + } else { + builder.build_return(None); + } + println!("Emitted return."); + } + } + } } Ok(module)