Write to .ll files
This commit is contained in:
parent
4d6ad1bb2c
commit
16cde4377c
16 changed files with 314 additions and 148 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,6 +3,8 @@ result*
|
||||||
|
|
||||||
*.bc
|
*.bc
|
||||||
*.ll
|
*.ll
|
||||||
|
*.ast
|
||||||
|
|
||||||
a.out
|
a.out
|
||||||
.direnv
|
.direnv
|
||||||
|
|
||||||
|
|
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -64,12 +64,6 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.73"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -154,9 +148,9 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"inkwell",
|
|
||||||
"lalrpop",
|
"lalrpop",
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -174,6 +168,15 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixedbitset"
|
name = "fixedbitset"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -223,26 +226,12 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inkwell"
|
name = "instant"
|
||||||
version = "0.1.0"
|
version = "0.1.12"
|
||||||
source = "git+https://github.com/TheDan64/inkwell?branch=master#25b9fc5870370211504e874e7c81dc53573bca79"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"cfg-if",
|
||||||
"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#25b9fc5870370211504e874e7c81dc53573bca79"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -286,31 +275,12 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.126"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "llvm-sys"
|
|
||||||
version = "120.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09b716322964966a62377cf86e64f00ca7043505fdf27bd2ec7d41ae6682d1e7"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"regex",
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
@ -377,15 +347,6 @@ dependencies = [
|
||||||
"windows-sys",
|
"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]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
@ -496,6 +457,15 @@ version = "0.6.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "remove_dir_all"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
|
@ -508,24 +478,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
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]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "0.3.10"
|
version = "0.3.10"
|
||||||
|
@ -568,6 +520,20 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"remove_dir_all",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "term"
|
name = "term"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -623,12 +589,6 @@ dependencies = [
|
||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ucd-trie"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
|
@ -7,11 +7,7 @@ edition = "2021"
|
||||||
anyhow = "1.0.56"
|
anyhow = "1.0.56"
|
||||||
clap = { version = "3.1.8", features = ["derive"] }
|
clap = { version = "3.1.8", features = ["derive"] }
|
||||||
lalrpop-util = { version = "0.19.7", features = ["lexer"] }
|
lalrpop-util = { version = "0.19.7", features = ["lexer"] }
|
||||||
|
tempfile = "3.3.0"
|
||||||
[dependencies.inkwell]
|
|
||||||
git = "https://github.com/TheDan64/inkwell"
|
|
||||||
branch = "master"
|
|
||||||
features = ["llvm12-0"]
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
lalrpop = "0.19.7"
|
lalrpop = "0.19.7"
|
||||||
|
|
17
default.nix
17
default.nix
|
@ -1,6 +1,4 @@
|
||||||
{ fenix, makeRustPlatform, lib, nix-gitignore, llvmPkgs, libffi }:
|
{ fenix, makeRustPlatform, lib, nix-gitignore, libffi, libgcc }:
|
||||||
|
|
||||||
with llvmPkgs;
|
|
||||||
|
|
||||||
let rustPlatform = makeRustPlatform { inherit (fenix.minimal) cargo rustc; };
|
let rustPlatform = makeRustPlatform { inherit (fenix.minimal) cargo rustc; };
|
||||||
|
|
||||||
|
@ -8,15 +6,8 @@ in rustPlatform.buildRustPackage {
|
||||||
name = "e0";
|
name = "e0";
|
||||||
src = nix-gitignore.gitignoreSource [ ./.gitignore ] ./.;
|
src = nix-gitignore.gitignoreSource [ ./.gitignore ] ./.;
|
||||||
|
|
||||||
nativeBuildInputs = [ llvm.dev ];
|
nativeBuildInputs = [ ];
|
||||||
buildInputs = [ libffi llvm ];
|
buildInputs = [ libffi ];
|
||||||
|
|
||||||
LLVM_SYS_120_PREFIX = "${llvm.dev}";
|
cargoLock = { lockFile = ./Cargo.lock; };
|
||||||
|
|
||||||
cargoLock = {
|
|
||||||
lockFile = ./Cargo.lock;
|
|
||||||
outputHashes = {
|
|
||||||
"inkwell-0.1.0" = "sha256-+ih3SO0n6YmZ/mcf+rLDwPAy/1MEZ/A+tI4pM1pUhvU=";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
fn main() -> int {
|
fn main() -> int {
|
||||||
let x = 5;
|
let x = 25;
|
||||||
|
|
||||||
if x < 3 {
|
if x < 10 {
|
||||||
return 3;
|
|
||||||
} else if x > 10 {
|
|
||||||
return 10;
|
return 10;
|
||||||
|
} else if x > 50 {
|
||||||
|
return 50;
|
||||||
} else {
|
} else {
|
||||||
return x;
|
if x < 20 {
|
||||||
|
return 20;
|
||||||
|
} else if x > 40 {
|
||||||
|
return 40;
|
||||||
|
} else {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
flake.nix
11
flake.nix
|
@ -12,16 +12,17 @@
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [ fenix.overlay ];
|
overlays = [ fenix.overlay ];
|
||||||
};
|
};
|
||||||
# https://github.com/NixOS/nixpkgs/issues/148117
|
myPkgs = rec { e0 = pkgs.callPackage ./. { }; };
|
||||||
llvmPkgs = pkgs.pkgsStatic.llvmPackages_12;
|
|
||||||
myPkgs = rec { e0 = pkgs.callPackage ./. { inherit llvmPkgs; }; };
|
|
||||||
|
|
||||||
in rec {
|
in rec {
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
packages = with pkgs; [ llvmPkgs.clangUseLLVM cargo-watch ];
|
packages = with pkgs;
|
||||||
|
with pkgs.llvmPackages_12; [
|
||||||
|
cargo-watch
|
||||||
|
clangUseLLVM
|
||||||
|
];
|
||||||
inputsFrom = with myPkgs; [ e0 ];
|
inputsFrom = with myPkgs; [ e0 ];
|
||||||
CARGO_UNSTABLE_SPARSE_REGISTRY = "true";
|
CARGO_UNSTABLE_SPARSE_REGISTRY = "true";
|
||||||
LLVM_SYS_120_PREFIX = "${llvmPkgs.llvm.dev}";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = utils.lib.flattenTree myPkgs;
|
packages = utils.lib.flattenTree myPkgs;
|
||||||
|
|
12
src/ast/cranelift.rs
Normal file
12
src/ast/cranelift.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use cranelift_codegen::Context as ClifContext;
|
||||||
|
|
||||||
|
use super::{Decl, Type};
|
||||||
|
|
||||||
|
pub fn convert(
|
||||||
|
file_name: String,
|
||||||
|
context: &Context,
|
||||||
|
program: Vec<Decl<Type>>,
|
||||||
|
) -> Result<ClifContext> {
|
||||||
|
todo!()
|
||||||
|
}
|
|
@ -6,10 +6,7 @@ use inkwell::{
|
||||||
context::Context,
|
context::Context,
|
||||||
module::Module,
|
module::Module,
|
||||||
types::{BasicMetadataTypeEnum, BasicTypeEnum, FunctionType},
|
types::{BasicMetadataTypeEnum, BasicTypeEnum, FunctionType},
|
||||||
values::{
|
values::{BasicValue, BasicValueEnum, FunctionValue, IntValue},
|
||||||
BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue,
|
|
||||||
IntValue, PointerValue,
|
|
||||||
},
|
|
||||||
IntPredicate,
|
IntPredicate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod llvm;
|
// pub mod llvm;
|
||||||
|
// pub mod cranelift;
|
||||||
pub mod typed;
|
pub mod typed;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
41
src/codegen/llvm_ir/expr.rs
Normal file
41
src/codegen/llvm_ir/expr.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::ast::{Expr, ExprKind, Stmt, Type};
|
||||||
|
|
||||||
|
use super::{type_to_llvm, LlvmIrCodegen};
|
||||||
|
|
||||||
|
pub struct ExprLlvm<'a>(String, &'a Expr<Type>);
|
||||||
|
|
||||||
|
impl<'a> ExprLlvm<'a> {
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> LlvmIrCodegen<W> {
|
||||||
|
pub(super) fn convert_expr<'a>(
|
||||||
|
&mut self,
|
||||||
|
expr: &'a Expr<Type>,
|
||||||
|
) -> Result<ExprLlvm<'a>> {
|
||||||
|
let expr_id = self.gensym("expr");
|
||||||
|
|
||||||
|
match &expr.kind {
|
||||||
|
ExprKind::Int(n) => {
|
||||||
|
let ty_str = type_to_llvm(&expr.ty);
|
||||||
|
writeln!(self.writer, "%{} = alloca {}", expr_id, ty_str)?;
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"store {} {}, {}* %{}",
|
||||||
|
ty_str, n, ty_str, expr_id
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
ExprKind::Var(_) => todo!(),
|
||||||
|
ExprKind::BinOp(_, _, _) => todo!(),
|
||||||
|
ExprKind::Call(_, _) => todo!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ExprLlvm(expr_id, expr))
|
||||||
|
}
|
||||||
|
}
|
19
src/codegen/llvm_ir/if_else.rs
Normal file
19
src/codegen/llvm_ir/if_else.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::ast::{IfElse, Stmt, Type};
|
||||||
|
|
||||||
|
use super::LlvmIrCodegen;
|
||||||
|
|
||||||
|
impl<W: Write> LlvmIrCodegen<W> {
|
||||||
|
pub(super) fn convert_if_else(
|
||||||
|
&mut self,
|
||||||
|
if_else: &IfElse<Type>,
|
||||||
|
) -> Result<()> {
|
||||||
|
// Build condition
|
||||||
|
let cond = self.convert_expr(&if_else.cond);
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
76
src/codegen/llvm_ir/mod.rs
Normal file
76
src/codegen/llvm_ir/mod.rs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
mod expr;
|
||||||
|
mod if_else;
|
||||||
|
mod stmts;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::ast::{Decl, Type};
|
||||||
|
use crate::utils::LayeredEnv;
|
||||||
|
|
||||||
|
use super::CodegenBackend;
|
||||||
|
|
||||||
|
pub struct LlvmIrCodegen<W> {
|
||||||
|
ctr: usize,
|
||||||
|
env: LayeredEnv<String, ()>,
|
||||||
|
writer: W,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> LlvmIrCodegen<W> {
|
||||||
|
pub fn new(writer: W) -> Self {
|
||||||
|
let env = LayeredEnv::default();
|
||||||
|
LlvmIrCodegen {
|
||||||
|
ctr: 0,
|
||||||
|
env,
|
||||||
|
writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gensym(&mut self, name: impl AsRef<str>) -> String {
|
||||||
|
let ctr = self.ctr;
|
||||||
|
self.ctr += 1;
|
||||||
|
format!("{}.{}", name.as_ref(), ctr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_to_llvm(ty: &Type) -> String {
|
||||||
|
match ty {
|
||||||
|
Type::Int => String::from("i32"),
|
||||||
|
Type::Bool => String::from("i1"),
|
||||||
|
Type::StructInst(_) => todo!(),
|
||||||
|
Type::Func(_, _) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> CodegenBackend for LlvmIrCodegen<W> {
|
||||||
|
fn convert(&mut self, program: Vec<Decl<Type>>) -> Result<()> {
|
||||||
|
// Convert all functions
|
||||||
|
for func in program.iter().filter_map(|decl| match decl {
|
||||||
|
Decl::Func(v) => Some(v),
|
||||||
|
_ => None,
|
||||||
|
}) {
|
||||||
|
// Write the function header
|
||||||
|
println!("Func type: {:?}", func.ty);
|
||||||
|
let (func_args_ty, ret_ty) = match &func.ty {
|
||||||
|
Type::Func(args, ret) => (args, ret),
|
||||||
|
_ => unreachable!(""),
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"define {} @{} () {{",
|
||||||
|
type_to_llvm(ret_ty),
|
||||||
|
func.name
|
||||||
|
)?;
|
||||||
|
let entry_block_name = self.gensym("entry");
|
||||||
|
writeln!(self.writer, "{}:", entry_block_name)?;
|
||||||
|
|
||||||
|
self.convert_stmts(&func.stmts)?;
|
||||||
|
|
||||||
|
writeln!(self.writer, "}}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
42
src/codegen/llvm_ir/stmts.rs
Normal file
42
src/codegen/llvm_ir/stmts.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::ast::{Stmt, Type};
|
||||||
|
|
||||||
|
use super::{type_to_llvm, LlvmIrCodegen};
|
||||||
|
|
||||||
|
impl<W: Write> LlvmIrCodegen<W> {
|
||||||
|
pub(super) fn convert_stmts(
|
||||||
|
&mut self,
|
||||||
|
stmts: impl AsRef<[Stmt<Type>]>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let stmts = stmts.as_ref();
|
||||||
|
|
||||||
|
for stmt in stmts.iter() {
|
||||||
|
match stmt {
|
||||||
|
Stmt::Let(_, _, _) => todo!(),
|
||||||
|
Stmt::Return(expr) => match expr {
|
||||||
|
Some(ret_val) => {
|
||||||
|
let ret_ty = type_to_llvm(&ret_val.ty);
|
||||||
|
let ret_val = self.convert_expr(ret_val)?;
|
||||||
|
let ret_name = self.gensym("ret");
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"%{} = load {}, {}* %{}",
|
||||||
|
ret_name,
|
||||||
|
ret_ty,
|
||||||
|
ret_ty,
|
||||||
|
ret_val.name()
|
||||||
|
)?;
|
||||||
|
writeln!(self.writer, "ret {} %{}", ret_ty, ret_name)?;
|
||||||
|
}
|
||||||
|
None => writeln!(self.writer, "ret void")?,
|
||||||
|
},
|
||||||
|
Stmt::IfElse(if_else) => self.convert_if_else(if_else)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
9
src/codegen/mod.rs
Normal file
9
src/codegen/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
pub mod llvm_ir;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::ast::{Decl, Type};
|
||||||
|
|
||||||
|
pub trait CodegenBackend {
|
||||||
|
fn convert(&mut self, program: Vec<Decl<Type>>) -> Result<()>;
|
||||||
|
}
|
26
src/main.rs
26
src/main.rs
|
@ -6,15 +6,17 @@ extern crate anyhow;
|
||||||
lalrpop_mod!(parser);
|
lalrpop_mod!(parser);
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
|
pub mod codegen;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use inkwell::context::Context;
|
|
||||||
|
|
||||||
|
use crate::codegen::{llvm_ir::LlvmIrCodegen, CodegenBackend};
|
||||||
use crate::parser::ProgramParser;
|
use crate::parser::ProgramParser;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
|
@ -40,15 +42,27 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
let typed_ast = ast::typed::convert(ast)?;
|
let typed_ast = ast::typed::convert(ast)?;
|
||||||
|
|
||||||
let context = Context::create();
|
if let Some(path) = opts.emit_ast {
|
||||||
let module =
|
let mut file = File::create(&path)?;
|
||||||
ast::llvm::convert(opts.path.display().to_string(), &context, typed_ast)?;
|
file.write(format!("{:#?}", typed_ast).as_bytes())?;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let file = File::create(&opts.out_path)?;
|
let file = File::create(&opts.out_path)?;
|
||||||
module.write_bitcode_to_file(&file, true, true);
|
let mut codegen = LlvmIrCodegen::new(file);
|
||||||
println!("Emitted.");
|
codegen.convert(typed_ast)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let ctx = ast::cranelift::convert(
|
||||||
|
// opts.path.display().to_string(),
|
||||||
|
// typed_ast,
|
||||||
|
// )?;
|
||||||
|
|
||||||
|
// {
|
||||||
|
// let file = File::create(&opts.out_path)?;
|
||||||
|
// ctx.compile_and_emit();
|
||||||
|
// println!("Emitted.");
|
||||||
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
61
src/utils.rs
61
src/utils.rs
|
@ -1,36 +1,35 @@
|
||||||
// TODO: put layered environment here?
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
use inkwell::{
|
#[derive(Default)]
|
||||||
types::{BasicMetadataTypeEnum, BasicTypeEnum},
|
pub struct LayeredEnv<K, V> {
|
||||||
values::{BasicMetadataValueEnum, BasicValueEnum},
|
parent: Option<Box<LayeredEnv<K, V>>>,
|
||||||
};
|
inner_map: HashMap<K, V>,
|
||||||
|
|
||||||
pub fn convert_type_to_metadata_type(
|
|
||||||
a: BasicTypeEnum,
|
|
||||||
) -> BasicMetadataTypeEnum {
|
|
||||||
use BasicMetadataTypeEnum as B;
|
|
||||||
use BasicTypeEnum as A;
|
|
||||||
match a {
|
|
||||||
A::IntType(a) => B::IntType(a),
|
|
||||||
A::ArrayType(a) => B::ArrayType(a),
|
|
||||||
A::FloatType(a) => B::FloatType(a),
|
|
||||||
A::StructType(a) => B::StructType(a),
|
|
||||||
A::VectorType(a) => B::VectorType(a),
|
|
||||||
A::PointerType(a) => B::PointerType(a),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_value_to_metadata_value(
|
impl<K: Hash + Eq, V> LayeredEnv<K, V> {
|
||||||
a: BasicValueEnum,
|
pub fn insert(&mut self, key: K, value: V) {
|
||||||
) -> BasicMetadataValueEnum {
|
self.inner_map.insert(key, value);
|
||||||
use BasicMetadataValueEnum as B;
|
}
|
||||||
use BasicValueEnum as A;
|
|
||||||
match a {
|
pub fn push(self) -> LayeredEnv<K, V> {
|
||||||
A::ArrayValue(a) => B::ArrayValue(a),
|
LayeredEnv {
|
||||||
A::IntValue(a) => B::IntValue(a),
|
parent: Some(Box::new(self)),
|
||||||
A::FloatValue(a) => B::FloatValue(a),
|
inner_map: HashMap::new(),
|
||||||
A::PointerValue(a) => B::PointerValue(a),
|
}
|
||||||
A::StructValue(a) => B::StructValue(a),
|
}
|
||||||
A::VectorValue(a) => B::VectorValue(a),
|
|
||||||
|
pub fn pop(self) -> LayeredEnv<K, V> {
|
||||||
|
*self.parent.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup(&self, key: &K) -> Option<&V> {
|
||||||
|
match self.inner_map.get(key) {
|
||||||
|
Some(v) => Some(v),
|
||||||
|
None => match self.parent.as_ref() {
|
||||||
|
Some(p) => p.lookup(key),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue