This commit is contained in:
Michael Zhang 2022-04-05 22:17:53 -05:00
parent fdb0a266b1
commit 0eb2b9ec04
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 94 additions and 75 deletions

View file

@ -1,3 +1,3 @@
fn main() { fn main() {
lalrpop::process_root().unwrap(); lalrpop::process_root().unwrap();
} }

2
rustfmt.toml Normal file
View file

@ -0,0 +1,2 @@
max_width = 80
tab_spaces = 2

View file

@ -1,58 +0,0 @@
use anyhow::Result;
use inkwell::{context::Context, module::Module};
#[derive(Debug)]
pub enum Decl {
Func(Func),
}
impl Decl {
pub fn unwrap_func(&self) -> Option<&Func> {
match self {
Decl::Func(func) => Some(func),
_ => None,
}
}
}
#[derive(Debug)]
pub struct Func {
pub name: String,
pub return_ty: Type,
pub stmts: Vec<Stmt>,
}
#[derive(Debug)]
pub enum Stmt {
Return(Option<Expr>),
}
#[derive(Debug)]
pub enum Expr {
Int(i64),
}
#[derive(Debug)]
pub enum Type {
Int,
}
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) {
// TODO: hardcoded void -> int function
let i64_ty = context.i64_type();
let llvm_func_ty = i64_ty.fn_type(&[], 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);
}
Ok(module)
}

38
src/ast/llvm.rs Normal file
View file

@ -0,0 +1,38 @@
use anyhow::Result;
use inkwell::{
context::Context,
module::Module,
types::{AnyType, AnyTypeEnum},
};
use super::{Decl, Type};
impl Type {
pub fn into_llvm_type<'ctx>(
&self,
context: &'ctx Context,
) -> AnyTypeEnum<'ctx> {
match self {
Type::Int => AnyTypeEnum::IntType(context.i64_type()),
}
}
}
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 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);
}
Ok(module)
}

37
src/ast/mod.rs Normal file
View file

@ -0,0 +1,37 @@
pub mod llvm;
#[derive(Debug)]
pub enum Decl {
Func(Func),
}
impl Decl {
pub fn unwrap_func(&self) -> Option<&Func> {
match self {
Decl::Func(func) => Some(func),
_ => None,
}
}
}
#[derive(Debug)]
pub struct Func {
pub name: String,
pub return_ty: Type,
pub stmts: Vec<Stmt>,
}
#[derive(Debug)]
pub enum Stmt {
Return(Option<Expr>),
}
#[derive(Debug)]
pub enum Expr {
Int(i64),
}
#[derive(Debug)]
pub enum Type {
Int,
}

View file

@ -18,29 +18,29 @@ use crate::parser::ProgramParser;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
struct Opt { struct Opt {
path: PathBuf, path: PathBuf,
#[clap(short = 'o', long = "out")] #[clap(short = 'o', long = "out")]
out_path: PathBuf, out_path: PathBuf,
} }
fn main() -> Result<()> { fn main() -> Result<()> {
let opts = Opt::parse(); let opts = Opt::parse();
let contents = fs::read_to_string(opts.path)?; let contents = fs::read_to_string(opts.path)?;
let parser = ProgramParser::new(); let parser = ProgramParser::new();
let ast = parser.parse(&contents).unwrap(); let ast = parser.parse(&contents).unwrap();
println!("AST: {ast:?}"); println!("AST: {ast:?}");
let mut context = Context::create(); let mut context = Context::create();
let module = ast::convert(&mut context, ast)?; let module = ast::llvm::convert(&mut context, ast)?;
{ {
let file = File::create(&opts.out_path)?; let file = File::create(&opts.out_path)?;
module.write_bitcode_to_file(&file, true, true); module.write_bitcode_to_file(&file, true, true);
println!("Emitted."); println!("Emitted.");
} }
Ok(()) Ok(())
} }