Start messing around with cranelift.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
**/*.o
|
||||||
@@ -16,6 +16,11 @@ path = "src/bin.rs"
|
|||||||
clap = { version = "^3.0.14", features = ["derive"] }
|
clap = { version = "^3.0.14", features = ["derive"] }
|
||||||
codespan = "0.11.1"
|
codespan = "0.11.1"
|
||||||
codespan-reporting = "0.11.1"
|
codespan-reporting = "0.11.1"
|
||||||
|
cranelift-codegen = "^0.89.2"
|
||||||
|
cranelift-frontend = "^0.89.2"
|
||||||
|
cranelift-module = "^0.89.2"
|
||||||
|
cranelift-native = "^0.89.2"
|
||||||
|
cranelift-object = "^0.89.2"
|
||||||
lalrpop-util = "^0.19.7"
|
lalrpop-util = "^0.19.7"
|
||||||
lazy_static = "^1.4.0"
|
lazy_static = "^1.4.0"
|
||||||
logos = "^0.12.0"
|
logos = "^0.12.0"
|
||||||
|
|||||||
17
runtime/rts.c
Normal file
17
runtime/rts.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print(char *variable_name, uint64_t value) {
|
||||||
|
printf("%s = %lu", variable_name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void caller() {
|
||||||
|
print("x", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void gogogo();
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
gogogo();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use pretty::{DocAllocator, DocBuilder, Pretty};
|
|||||||
|
|
||||||
pub struct Program<Annotation> {
|
pub struct Program<Annotation> {
|
||||||
pub statements: Vec<Statement<Annotation>>,
|
pub statements: Vec<Statement<Annotation>>,
|
||||||
|
pub variable_info: VariableMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Annotation> Program<Annotation> {
|
impl<Annotation> Program<Annotation> {
|
||||||
|
|||||||
0
src/backend.rs
Normal file
0
src/backend.rs
Normal file
65
src/bin.rs
65
src/bin.rs
@@ -3,9 +3,16 @@ use codespan_reporting::diagnostic::Diagnostic;
|
|||||||
use codespan_reporting::files::SimpleFiles;
|
use codespan_reporting::files::SimpleFiles;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
|
use cranelift_codegen::ir::{AbiParam, types, Signature};
|
||||||
|
use cranelift_codegen::isa::CallConv;
|
||||||
|
use cranelift_codegen::{isa, settings, CodegenError};
|
||||||
|
use cranelift_module::{default_libcall_names, ModuleError, Linkage, Module};
|
||||||
|
use cranelift_object::{ObjectBuilder, ObjectModule, object};
|
||||||
use ngr::asts::lil;
|
use ngr::asts::lil;
|
||||||
use ngr::passes::run_front_end;
|
use ngr::passes::run_front_end;
|
||||||
use pretty::Arena;
|
use pretty::Arena;
|
||||||
|
use std::io;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(author, version, about, long_about = None)]
|
#[clap(author, version, about, long_about = None)]
|
||||||
@@ -18,7 +25,25 @@ struct CommandLineArguments {
|
|||||||
file: String,
|
file: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[derive(Debug, Error)]
|
||||||
|
enum MainError {
|
||||||
|
#[error("Error parsing triple: {0}")]
|
||||||
|
Isa(#[from] isa::LookupError),
|
||||||
|
|
||||||
|
#[error("Code generation error: {0}")]
|
||||||
|
Codegen(#[from] CodegenError),
|
||||||
|
|
||||||
|
#[error("Module error: {0}")]
|
||||||
|
Module(#[from] ModuleError),
|
||||||
|
|
||||||
|
#[error("IO error: {0}")]
|
||||||
|
IO(#[from] io::Error),
|
||||||
|
|
||||||
|
#[error("Object write error: {0}")]
|
||||||
|
Object(#[from] object::write::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), MainError> {
|
||||||
let args = CommandLineArguments::parse();
|
let args = CommandLineArguments::parse();
|
||||||
let mut file_database = SimpleFiles::new();
|
let mut file_database = SimpleFiles::new();
|
||||||
let initial_file_name = &args.file;
|
let initial_file_name = &args.file;
|
||||||
@@ -46,13 +71,35 @@ fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((hil_tree, mut variable_map)) = hil_conversion_result.result {
|
if let Some((hil_tree, variable_map)) = hil_conversion_result.result {
|
||||||
let arena = Arena::new();
|
//let arena = Arena::new();
|
||||||
let lil_tree = lil::Program::convert(hil_tree, &mut variable_map);
|
let lil_tree = lil::Program::convert(hil_tree, variable_map.clone());
|
||||||
lil_tree
|
|
||||||
.pretty(&variable_map, &arena)
|
let isa = isa::lookup_by_name("aarch64-apple-darwin")?.finish(settings::Flags::new(settings::builder()))?;
|
||||||
.into_doc()
|
let object_builder = ObjectBuilder::new(isa, "example", default_libcall_names())?;
|
||||||
.render_colored(72, StandardStream::stdout(ColorChoice::Auto))
|
let mut object_module = ObjectModule::new(object_builder);
|
||||||
.unwrap()
|
|
||||||
|
let print_signature = Signature {
|
||||||
|
params: vec![AbiParam::new(types::I64)],
|
||||||
|
returns: vec![],
|
||||||
|
call_conv: CallConv::SystemV,
|
||||||
|
};
|
||||||
|
let print_func_id = object_module.declare_function("print", Linkage::Import, &print_signature)?;
|
||||||
|
|
||||||
|
let _compiled = lil_tree.into_cranelift(&mut object_module, print_func_id)?;
|
||||||
|
|
||||||
|
// something?
|
||||||
|
|
||||||
|
let bytes = object_module.finish().emit()?;
|
||||||
|
|
||||||
|
std::fs::write("output.o", bytes)?;
|
||||||
|
|
||||||
|
// lil_tree
|
||||||
|
// .pretty(&variable_map, &arena)
|
||||||
|
// .into_doc()
|
||||||
|
// .render_colored(72, StandardStream::stdout(ColorChoice::Auto))
|
||||||
|
// .unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ pub enum Error {
|
|||||||
|
|
||||||
#[error("Unbound variable '{0}'")]
|
#[error("Unbound variable '{0}'")]
|
||||||
UnboundVariable(Location, String),
|
UnboundVariable(Location, String),
|
||||||
|
|
||||||
|
#[error("Internal error: {0}")]
|
||||||
|
InternalError(Location, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locations_to_labels(start: &Location, end: &Location) -> Vec<Label<usize>> {
|
fn locations_to_labels(start: &Location, end: &Location) -> Vec<Label<usize>> {
|
||||||
@@ -168,6 +171,17 @@ impl From<Error> for Diagnostic<usize> {
|
|||||||
])
|
])
|
||||||
.with_message(format!("Unbound variable '{}'", name)),
|
.with_message(format!("Unbound variable '{}'", name)),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Error::InternalError(location, string) => match location {
|
||||||
|
Location::Manufactured => {
|
||||||
|
Diagnostic::error().with_message(format!("Internal error: {}", string))
|
||||||
|
}
|
||||||
|
Location::InFile(file_id, offset) => Diagnostic::error()
|
||||||
|
.with_labels(vec![
|
||||||
|
Label::primary(*file_id, *offset..*offset).with_message("this is related")
|
||||||
|
])
|
||||||
|
.with_message(format!("Internal error: {}", string)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod asts;
|
pub mod asts;
|
||||||
|
pub mod backend;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod passes;
|
pub mod passes;
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use std::fs;
|
|||||||
|
|
||||||
mod hil_to_lil;
|
mod hil_to_lil;
|
||||||
mod syntax_to_hil;
|
mod syntax_to_hil;
|
||||||
|
mod into_crane;
|
||||||
|
|
||||||
pub struct PassResult<T> {
|
pub struct PassResult<T> {
|
||||||
pub result: T,
|
pub result: T,
|
||||||
|
|||||||
@@ -3,14 +3,20 @@ use crate::asts::lil;
|
|||||||
use crate::variable_map::VariableMap;
|
use crate::variable_map::VariableMap;
|
||||||
|
|
||||||
impl<Annotation: Clone> lil::Program<Annotation> {
|
impl<Annotation: Clone> lil::Program<Annotation> {
|
||||||
pub fn convert(hil_program: hil::Program<Annotation>, variable_map: &mut VariableMap) -> Self {
|
pub fn convert(hil_program: hil::Program<Annotation>, mut variable_map: VariableMap) -> Self {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
for hil_statement in hil_program.statements {
|
for hil_statement in hil_program.statements {
|
||||||
statements.append(&mut lil::Statement::convert(hil_statement, variable_map));
|
statements.append(&mut lil::Statement::convert(
|
||||||
|
hil_statement,
|
||||||
|
&mut variable_map,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
lil::Program { statements }
|
lil::Program {
|
||||||
|
statements,
|
||||||
|
variable_info: variable_map,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
95
src/passes/into_crane.rs
Normal file
95
src/passes/into_crane.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
use crate::asts::lil::{Program, Statement, Primitive, SimpleExpression, Value};
|
||||||
|
use cranelift_codegen::entity::EntityRef;
|
||||||
|
use cranelift_codegen::ir::{Function, UserFuncName, UserExternalName, Signature, types, InstBuilder, entities, ExternalName, ExtFuncData, AbiParam};
|
||||||
|
use cranelift_codegen::isa::CallConv;
|
||||||
|
use cranelift_codegen::{Context};
|
||||||
|
use cranelift_frontend::{FunctionBuilderContext, FunctionBuilder, Variable};
|
||||||
|
use cranelift_module::{FuncId, Module, Linkage, ModuleError, ModuleCompiledFunction};
|
||||||
|
|
||||||
|
impl<Annotation> Program<Annotation> {
|
||||||
|
|
||||||
|
pub fn into_cranelift<M: Module>(&self, module: &mut M, print_func_id: FuncId) -> Result<ModuleCompiledFunction, ModuleError> {
|
||||||
|
let basic_signature = Signature {
|
||||||
|
params: vec![],
|
||||||
|
returns: vec![],
|
||||||
|
call_conv: CallConv::SystemV,
|
||||||
|
};
|
||||||
|
|
||||||
|
let func_id = module.declare_function("gogogo", Linkage::Export, &basic_signature)?;
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), basic_signature);
|
||||||
|
|
||||||
|
let print_func_ref = module.declare_func_in_func(print_func_id, &mut ctx.func);
|
||||||
|
|
||||||
|
let mut fctx = FunctionBuilderContext::new();
|
||||||
|
let mut builder = FunctionBuilder::new(&mut ctx.func, &mut fctx);
|
||||||
|
let main_block = builder.create_block();
|
||||||
|
builder.switch_to_block(main_block);
|
||||||
|
|
||||||
|
for stmt in self.statements.iter() {
|
||||||
|
match stmt {
|
||||||
|
Statement::Print(ann, var) => {
|
||||||
|
let var = builder.use_var(Variable::new(*var));
|
||||||
|
builder.ins().call(print_func_ref, &[var]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::ResultBinding(_, varnum, value) => {
|
||||||
|
let var = Variable::new(*varnum);
|
||||||
|
builder.declare_var(var, types::I64);
|
||||||
|
|
||||||
|
let val = match value {
|
||||||
|
Primitive::Plus(left, right) => {
|
||||||
|
let left = left.into_cranelift(&mut builder);
|
||||||
|
let right = right.into_cranelift(&mut builder);
|
||||||
|
builder.ins().iadd(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
Primitive::Minus(left, right) => {
|
||||||
|
let left = left.into_cranelift(&mut builder);
|
||||||
|
let right = right.into_cranelift(&mut builder);
|
||||||
|
builder.ins().isub(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
Primitive::Times(left, right) => {
|
||||||
|
let left = left.into_cranelift(&mut builder);
|
||||||
|
let right = right.into_cranelift(&mut builder);
|
||||||
|
builder.ins().imul(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
Primitive::Divide(left, right) => {
|
||||||
|
let left = left.into_cranelift(&mut builder);
|
||||||
|
let right = right.into_cranelift(&mut builder);
|
||||||
|
builder.ins().sdiv(left, right)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
builder.def_var(var, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::VariableBinding(_, varnum, exp) => {
|
||||||
|
let var = Variable::new(*varnum);
|
||||||
|
builder.declare_var(var, types::I64);
|
||||||
|
let val = exp.into_cranelift(&mut builder);
|
||||||
|
builder.def_var(var, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.ins().return_(&[]);
|
||||||
|
builder.seal_block(main_block);
|
||||||
|
builder.finalize();
|
||||||
|
|
||||||
|
module.define_function(func_id, &mut ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Annotation> SimpleExpression<Annotation> {
|
||||||
|
fn into_cranelift(&self, builder: &mut FunctionBuilder) -> entities::Value {
|
||||||
|
match self {
|
||||||
|
SimpleExpression::Constant(_, value) => match value {
|
||||||
|
Value::Number(_base, numval) => builder.ins().iconst(types::I64, *numval as i64),
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleExpression::Reference(_, num) => builder.use_var(Variable::new(*num)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,14 @@ use crate::syntax::Location;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub type Variable = usize;
|
pub type Variable = usize;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct VariableMap {
|
pub struct VariableMap {
|
||||||
map: HashMap<Variable, VariableInfo>,
|
map: HashMap<Variable, VariableInfo>,
|
||||||
next_index: Variable,
|
next_index: Variable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct VariableInfo {
|
struct VariableInfo {
|
||||||
name: String,
|
name: String,
|
||||||
binding_location: Location,
|
binding_location: Location,
|
||||||
|
|||||||
Reference in New Issue
Block a user