Compile to LLVM bitcode

This commit is contained in:
Michael Zhang 2022-04-05 22:07:34 -05:00
parent d674c92199
commit fdb0a266b1
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
9 changed files with 200 additions and 16 deletions

15
.gitignore vendored
View file

@ -1,14 +1,5 @@
_build
# Added by cargo
result*
/target
# Added by cargo
#
# already existing elements were commented out
#/target
*.bc
*.ll

76
Cargo.lock generated
View file

@ -64,6 +64,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -139,6 +145,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"inkwell",
"lalrpop",
"lalrpop-util",
]
@ -206,6 +213,29 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inkwell"
version = "0.1.0"
source = "git+https://github.com/TheDan64/inkwell?branch=master#36c3b106e61b1b45295a35f94023d93d9328c76f"
dependencies = [
"either",
"inkwell_internals",
"libc",
"llvm-sys",
"once_cell",
"parking_lot",
]
[[package]]
name = "inkwell_internals"
version = "0.5.0"
source = "git+https://github.com/TheDan64/inkwell?branch=master#36c3b106e61b1b45295a35f94023d93d9328c76f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "itertools"
version = "0.10.3"
@ -259,6 +289,19 @@ version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
[[package]]
name = "llvm-sys"
version = "120.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce76f8393b7a607a906087666db398d872db739622e644e58552c198ccdfdf45"
dependencies = [
"cc",
"lazy_static",
"libc",
"regex",
"semver",
]
[[package]]
name = "lock_api"
version = "0.4.7"
@ -328,6 +371,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "petgraph"
version = "0.5.1"
@ -450,6 +502,24 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]]
name = "siphasher"
version = "0.3.10"
@ -547,6 +617,12 @@ dependencies = [
"crunchy",
]
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-xid"
version = "0.2.2"

View file

@ -8,5 +8,10 @@ anyhow = "1.0.56"
clap = { version = "3.1.8", features = ["derive"] }
lalrpop-util = { version = "0.19.7", features = ["lexer"] }
[dependencies.inkwell]
git = "https://github.com/TheDan64/inkwell"
branch = "master"
features = ["llvm12-0"]
[build-dependencies]
lalrpop = "0.19.7"

15
default.nix Normal file
View file

@ -0,0 +1,15 @@
{ rustPlatform, lib, nix-gitignore, llvmPackages_12 }:
let llvmPkgs = llvmPackages_12;
in with llvmPkgs;
rustPlatform.buildRustPackage {
name = "e0";
src = nix-gitignore.gitignoreSource [ ./.gitignore ] ./.;
buildInputs = [ llvmPkgs.llvm.dev ];
cargoSha256 = lib.fakeSha256;
# cargoSha256 = "sha256-rWMnlkb/XoycP69NOOmg7Wd4qPgliuvOKGWaEth/8tg=";
}

41
flake.lock Normal file
View file

@ -0,0 +1,41 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1648219316,
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"utils": {
"locked": {
"lastModified": 1648297722,
"narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

16
flake.nix Normal file
View file

@ -0,0 +1,16 @@
{
description = "A very basic flake";
inputs = { utils.url = "github:numtide/flake-utils"; };
outputs = { self, nixpkgs, utils }:
utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
myPkgs = rec { e0 = pkgs.callPackage ./. { }; };
in rec {
packages = utils.lib.flattenTree myPkgs;
defaultPackage = packages.e0;
});
}

View file

@ -1,10 +1,20 @@
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,
@ -27,6 +37,22 @@ pub enum Type {
Int,
}
pub fn convert(program: Vec<Decl>) -> Result<String> {
Ok(String::new())
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)
}

View file

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

View file

@ -9,7 +9,8 @@ Decl: Decl = {
};
Func: Func = {
"fn" <name:Ident> "(" ")" "->" <return_ty:Type> "{" <stmts:Stmt*> "}" => Func { name, return_ty, stmts },
"fn" <name:Ident> "(" ")" "->" <return_ty:Type> "{" <stmts:Stmt*> "}" =>
Func { name, return_ty, stmts },
};
Stmt: Stmt = {