This commit is contained in:
Edgar 2024-02-03 20:14:29 +01:00
parent cdc52cef39
commit 8f1c094b60
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
11 changed files with 493 additions and 1642 deletions

764
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,12 +12,11 @@ categories = ["compilers"]
[dependencies] [dependencies]
bumpalo = { version = "3.14.0", features = ["std"] } bumpalo = { version = "3.14.0", features = ["std"] }
edlang_ast = { version = "0.1.0", path = "../edlang_ast" } edlang_ir = { version = "0.1.0", path = "../edlang_ir" }
edlang_parser = { version = "0.1.0", path = "../edlang_parser" } edlang_parser = { version = "0.1.0", path = "../edlang_parser" }
edlang_session = { version = "0.1.0", path = "../edlang_session" } edlang_session = { version = "0.1.0", path = "../edlang_session" }
llvm-sys = "170.0.1" llvm-sys = "170.0.1"
melior = { version = "0.15.2", features = ["ods-dialects"] } inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "0cdaa34bd612464f310b3fdefa00a75d1324687d", features = ["llvm17-0"] }
mlir-sys = "0.2.1"
tracing = { workspace = true } tracing = { workspace = true }
[build-dependencies] [build-dependencies]

File diff suppressed because it is too large Load diff

View file

@ -1,91 +0,0 @@
use std::error::Error;
use edlang_ast::Module;
use edlang_session::Session;
use melior::{
dialect::DialectRegistry,
ir::{operation::OperationPrintingFlags, Location, Module as MeliorModule},
pass::{self, PassManager},
utility::{register_all_dialects, register_all_llvm_translations, register_all_passes},
Context as MeliorContext,
};
#[derive(Debug, Eq, PartialEq)]
pub struct Context {
melior_context: MeliorContext,
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
impl Context {
pub fn new() -> Self {
let melior_context = initialize_mlir();
Self { melior_context }
}
pub fn compile(
&self,
session: &Session,
module: &Module,
) -> Result<MeliorModule, Box<dyn Error>> {
let file_path = session.file_path.display().to_string();
let location = Location::new(&self.melior_context, &file_path, 0, 0);
let mut melior_module = MeliorModule::new(location);
super::codegen::compile_module(session, &self.melior_context, &melior_module, module)?;
assert!(melior_module.as_operation().verify());
tracing::debug!(
"MLIR Code before passes:\n{}",
melior_module.as_operation().to_string_with_flags(
OperationPrintingFlags::new().enable_debug_info(true, true)
)?
);
// TODO: Add proper error handling.
self.run_pass_manager(&mut melior_module)?;
tracing::debug!(
"MLIR Code after passes:\n{}",
melior_module.as_operation().to_string_with_flags(
OperationPrintingFlags::new().enable_debug_info(true, true)
)?
);
Ok(melior_module)
}
fn run_pass_manager(&self, module: &mut MeliorModule) -> Result<(), melior::Error> {
let pass_manager = PassManager::new(&self.melior_context);
pass_manager.enable_verifier(true);
pass_manager.add_pass(pass::transform::create_canonicalizer());
pass_manager.add_pass(pass::conversion::create_scf_to_control_flow());
pass_manager.add_pass(pass::conversion::create_arith_to_llvm());
pass_manager.add_pass(pass::conversion::create_control_flow_to_llvm());
pass_manager.add_pass(pass::conversion::create_func_to_llvm());
pass_manager.add_pass(pass::conversion::create_index_to_llvm());
pass_manager.add_pass(pass::conversion::create_finalize_mem_ref_to_llvm());
pass_manager.add_pass(pass::conversion::create_reconcile_unrealized_casts());
pass_manager.run(module)
}
}
/// Initialize an MLIR context.
pub fn initialize_mlir() -> MeliorContext {
let context = MeliorContext::new();
context.append_dialect_registry(&{
let registry = DialectRegistry::new();
register_all_dialects(&registry);
registry
});
context.load_all_available_dialects();
register_all_passes();
register_all_llvm_translations(&context);
context
}

View file

@ -1,10 +0,0 @@
use llvm_sys::prelude::{LLVMContextRef, LLVMModuleRef};
extern "C" {
/// Translate operation that satisfies LLVM dialect module requirements into an LLVM IR module living in the given context.
/// This translates operations from any dilalect that has a registered implementation of LLVMTranslationDialectInterface.
pub fn mlirTranslateModuleToLLVMIR(
module_operation_ptr: mlir_sys::MlirOperation,
llvm_context: LLVMContextRef,
) -> LLVMModuleRef;
}

View file

@ -1,6 +1,8 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use edlang_ir as ir;
use std::{ use std::{
collections::HashMap,
ffi::{CStr, CString}, ffi::{CStr, CString},
mem::MaybeUninit, mem::MaybeUninit,
path::PathBuf, path::PathBuf,
@ -8,9 +10,10 @@ use std::{
sync::OnceLock, sync::OnceLock,
}; };
use context::Context;
use edlang_ast::Module;
use edlang_session::{OptLevel, Session}; use edlang_session::{OptLevel, Session};
use inkwell::context::Context;
use ir::DefId;
/*
use llvm_sys::{ use llvm_sys::{
core::{LLVMContextCreate, LLVMContextDispose, LLVMDisposeMessage, LLVMDisposeModule}, core::{LLVMContextCreate, LLVMContextDispose, LLVMDisposeMessage, LLVMDisposeModule},
target::{ target::{
@ -24,41 +27,26 @@ use llvm_sys::{
LLVMTargetRef, LLVMTargetRef,
}, },
}; };
use melior::ir::{operation::OperationPrintingFlags, Module as MeliorModule}; */
use crate::ffi::mlirTranslateModuleToLLVMIR;
pub mod codegen; pub mod codegen;
mod context;
mod ffi;
pub mod linker; pub mod linker;
pub fn compile_mlir( pub fn compile(
session: &Session, session: &Session,
program: &Module, modules: &HashMap<DefId, ir::ModuleBody>,
) -> Result<String, Box<dyn std::error::Error>> { symbols: HashMap<DefId, String>,
let context = Context::new(); ) -> Result<PathBuf, Box<dyn std::error::Error>> {
let mlir_module = context.compile(session, program)?; codegen::compile(session, modules, &symbols)
Ok(mlir_module
.as_operation()
.to_string_with_flags(OperationPrintingFlags::new().enable_debug_info(true, false))?)
} }
pub fn compile(session: &Session, program: &Module) -> Result<PathBuf, Box<dyn std::error::Error>> { // Converts a module to an object.
let context = Context::new(); // The object will be written to the specified target path.
let mlir_module = context.compile(session, program)?; // TODO: error handling
//
// Returns the path to the object.ç
let object_path = compile_to_object(session, &mlir_module)?; /*
Ok(object_path)
}
/// Converts a module to an object.
/// The object will be written to the specified target path.
/// TODO: error handling
///
/// Returns the path to the object.
pub fn compile_to_object( pub fn compile_to_object(
session: &Session, session: &Session,
module: &MeliorModule, module: &MeliorModule,
@ -175,3 +163,4 @@ pub fn compile_to_object(
Ok(target_path) Ok(target_path)
} }
} }
*/

View file

@ -85,19 +85,14 @@ pub fn main() -> Result<(), Box<dyn Error>> {
return Ok(()); return Ok(());
} }
let (_symbols, module_irs) = lower_modules(&[module.clone()]); let (symbols, module_irs) = lower_modules(&[module.clone()]);
if args.ir { if args.ir {
println!("{:#?}", module_irs); println!("{:#?}", module_irs);
return Ok(()); return Ok(());
} }
if args.mlir { let object_path = edlang_codegen_mlir::compile(&session, &module_irs, symbols)?;
println!("{}", edlang_codegen_mlir::compile_mlir(&session, &module)?);
return Ok(());
}
let object_path = edlang_codegen_mlir::compile(&session, &module)?;
if session.library { if session.library {
link_shared_lib(&object_path, &session.output_file.with_extension("so"))?; link_shared_lib(&object_path, &session.output_file.with_extension("so"))?;

View file

@ -22,6 +22,15 @@ pub struct DefId {
pub id: usize, pub id: usize,
} }
impl DefId {
pub fn get_module_defid(&self) -> Self {
Self {
module_id: self.module_id,
id: 0,
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Body { pub struct Body {
pub def_id: DefId, pub def_id: DefId,
@ -33,6 +42,24 @@ pub struct Body {
pub fn_span: Span, pub fn_span: Span,
} }
impl Body {
pub fn get_args(&self) -> SmallVec<[Local; 4]> {
let mut args = SmallVec::default();
for x in &self.locals {
if let LocalKind::Arg = x.kind {
args.push(x.clone());
}
}
args
}
pub fn get_return_local(&self) -> Local {
self.locals[0].clone()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DebugInfo { pub struct DebugInfo {
pub id: usize, pub id: usize,

View file

@ -12,7 +12,7 @@ impl IdGenerator {
pub const fn new(module_id: usize) -> Self { pub const fn new(module_id: usize) -> Self {
Self { Self {
current_id: 0, current_id: 0,
module_id: 0, module_id,
} }
} }

View file

@ -7,7 +7,9 @@ use ir::{ConstData, ConstKind, DefId, Local, Operand, Place, Statement, Terminat
mod common; mod common;
pub fn lower_modules(modules: &[ast::Module]) -> (HashMap<DefId, String>, Vec<ir::ModuleBody>) { pub fn lower_modules(
modules: &[ast::Module],
) -> (HashMap<DefId, String>, HashMap<DefId, ir::ModuleBody>) {
let mut ctx = BuildCtx::default(); let mut ctx = BuildCtx::default();
for m in modules { for m in modules {
@ -28,14 +30,14 @@ pub fn lower_modules(modules: &[ast::Module]) -> (HashMap<DefId, String>, Vec<ir
ctx.gen.next_module_defid(); ctx.gen.next_module_defid();
} }
let mut lowered_modules = Vec::with_capacity(modules.len()); let mut lowered_modules = HashMap::with_capacity(modules.len());
// todo: maybe should do a prepass here populating all symbols // todo: maybe should do a prepass here populating all symbols
for module in modules { for module in modules {
let ir; let ir;
(ctx, ir) = lower_module(ctx, module); (ctx, ir) = lower_module(ctx, module);
lowered_modules.push(ir); lowered_modules.insert(ir.module_id, ir);
} }
(ctx.symbol_names, lowered_modules) (ctx.symbol_names, lowered_modules)

View file

@ -1,13 +1,8 @@
mod Main { mod Main {
fn main(argc: i32) -> i32 { pub fn main(argc: i32) -> i32 {
let mut x: i32 = 2; let mut x: i32 = 2;
x = 4; x = 4;
let y: i32 = other(2);
return x; return x;
} }
fn other(a: i32) -> i32 {
return a;
}
} }