Execute statements

This commit is contained in:
Michael Zhang 2022-04-05 22:36:05 -05:00
parent 0eb2b9ec04
commit bcc2bf937f
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B

View file

@ -1,38 +1,83 @@
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<BasicValueEnum<'ctx>> {
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<Decl>) -> Result<Module> {
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);
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)
}