diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 6e147fd..0b2d542 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -202,6 +202,10 @@ impl Builder { } } + pub(crate) fn find_module<'ctx>(&'ctx self, value: ModuleValue) -> ModuleHolder { + unsafe { self.modules.borrow().get_unchecked(value.0).clone() } + } + pub(crate) fn get_modules(&self) -> Rc>> { self.modules.clone() } diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 3444b85..16cbc48 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -2,12 +2,13 @@ //! LLIR ([`Context`]) into LLVM IR. This module is the only one that interfaces //! with the LLVM API. -use std::{collections::HashMap, ffi::CString, ptr::null_mut}; +use std::{collections::HashMap, ffi::CString, marker::PhantomData, ptr::null_mut}; use llvm_sys::{ LLVMIntPredicate, LLVMLinkage, analysis::LLVMVerifyModule, core::*, + linker::LLVMLinkModules2, prelude::*, target::{ LLVM_InitializeAllAsmParsers, LLVM_InitializeAllAsmPrinters, LLVM_InitializeAllTargetInfos, @@ -34,8 +35,87 @@ pub struct LLVMContext { builder_ref: LLVMBuilderRef, } +impl Drop for LLVMContext { + fn drop(&mut self) { + unsafe { + LLVMDisposeBuilder(self.builder_ref); + LLVMContextDispose(self.context_ref); + } + } +} + +pub struct CompiledModule { + module_ref: LLVMModuleRef, + _context: LLVMContext, +} + +impl CompiledModule { + pub fn output(&self) { + unsafe { + LLVM_InitializeAllTargets(); + LLVM_InitializeAllTargetInfos(); + LLVM_InitializeAllTargetMCs(); + LLVM_InitializeAllAsmParsers(); + LLVM_InitializeAllAsmPrinters(); + + let triple = LLVMGetDefaultTargetTriple(); + + let mut target: _ = null_mut(); + let mut err = ErrorMessageHolder::null(); + LLVMGetTargetFromTriple(triple, &mut target, err.borrow_mut()); + println!("{:?}, {:?}", from_cstring(triple), target); + err.into_result().unwrap(); + + let target_machine = LLVMCreateTargetMachine( + target, + triple, + c"generic".as_ptr(), + c"".as_ptr(), + llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone, + llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault, + llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault, + ); + + let data_layout = LLVMCreateTargetDataLayout(target_machine); + LLVMSetTarget(self.module_ref, triple); + LLVMSetModuleDataLayout(self.module_ref, data_layout); + + let mut err = ErrorMessageHolder::null(); + LLVMVerifyModule( + self.module_ref, + llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction, + err.borrow_mut(), + ); + err.into_result().unwrap(); + + let mut err = ErrorMessageHolder::null(); + LLVMTargetMachineEmitToFile( + target_machine, + self.module_ref, + CString::new("hello.asm").unwrap().into_raw(), + LLVMCodeGenFileType::LLVMAssemblyFile, + err.borrow_mut(), + ); + err.into_result().unwrap(); + + let mut err = ErrorMessageHolder::null(); + LLVMTargetMachineEmitToFile( + target_machine, + self.module_ref, + CString::new("hello.o").unwrap().into_raw(), + LLVMCodeGenFileType::LLVMObjectFile, + err.borrow_mut(), + ); + err.into_result().unwrap(); + + let module_str = from_cstring(LLVMPrintModuleToString(self.module_ref)); + println!("{}", module_str.unwrap()); + } + } +} + impl Context { - pub fn compile(&self) { + pub fn compile(&self) -> CompiledModule { unsafe { let context_ref = LLVMContextCreate(); @@ -44,12 +124,31 @@ impl Context { builder_ref: LLVMCreateBuilderInContext(context_ref), }; - for holder in self.builder.get_modules().borrow().iter() { - holder.compile(&context, &self.builder); + let module_holders = self.builder.get_modules(); + + let main_module = module_holders + .borrow() + .iter() + .find(|m| m.data.name == "main") + .unwrap_or(module_holders.borrow().first().unwrap()) + .clone(); + + let main_module_ref = main_module.compile(&context, &self.builder); + dbg!("main"); + + for holder in module_holders.borrow().iter() { + if holder.value == main_module.value { + continue; + } + dbg!(holder.value); + let module_ref = holder.compile(&context, &self.builder); + LLVMLinkModules2(main_module_ref, module_ref); } - LLVMDisposeBuilder(context.builder_ref); - LLVMContextDispose(context.context_ref); + CompiledModule { + module_ref: main_module_ref, + _context: context, + } } } } @@ -77,7 +176,7 @@ pub struct LLVMValue { } impl ModuleHolder { - fn compile(&self, context: &LLVMContext, builder: &Builder) { + fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef { unsafe { let module_ref = LLVMModuleCreateWithNameInContext( into_cstring(&self.data.name).as_ptr(), @@ -109,64 +208,7 @@ impl ModuleHolder { function.compile(&mut module); } - LLVM_InitializeAllTargets(); - LLVM_InitializeAllTargetInfos(); - LLVM_InitializeAllTargetMCs(); - LLVM_InitializeAllAsmParsers(); - LLVM_InitializeAllAsmPrinters(); - - let triple = LLVMGetDefaultTargetTriple(); - - let mut target: _ = null_mut(); - let mut err = ErrorMessageHolder::null(); - LLVMGetTargetFromTriple(triple, &mut target, err.borrow_mut()); - println!("{:?}, {:?}", from_cstring(triple), target); - err.into_result().unwrap(); - - let target_machine = LLVMCreateTargetMachine( - target, - triple, - c"generic".as_ptr(), - c"".as_ptr(), - llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone, - llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault, - llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault, - ); - - let data_layout = LLVMCreateTargetDataLayout(target_machine); - LLVMSetTarget(module_ref, triple); - LLVMSetModuleDataLayout(module_ref, data_layout); - - let mut err = ErrorMessageHolder::null(); - LLVMVerifyModule( - module_ref, - llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction, - err.borrow_mut(), - ); - err.into_result().unwrap(); - - let mut err = ErrorMessageHolder::null(); - LLVMTargetMachineEmitToFile( - target_machine, - module_ref, - CString::new("hello.asm").unwrap().into_raw(), - LLVMCodeGenFileType::LLVMAssemblyFile, - err.borrow_mut(), - ); - err.into_result().unwrap(); - - let mut err = ErrorMessageHolder::null(); - LLVMTargetMachineEmitToFile( - target_machine, - module_ref, - CString::new("hello.o").unwrap().into_raw(), - LLVMCodeGenFileType::LLVMObjectFile, - err.borrow_mut(), - ); - err.into_result().unwrap(); - - let module_str = from_cstring(LLVMPrintModuleToString(module_ref)); - println!("{}", module_str.unwrap()); + module_ref } } } diff --git a/reid-llvm-lib/src/debug.rs b/reid-llvm-lib/src/debug.rs index 979e18c..7842092 100644 --- a/reid-llvm-lib/src/debug.rs +++ b/reid-llvm-lib/src/debug.rs @@ -1,6 +1,9 @@ //! Debug implementations for relevant types -use std::fmt::{Debug, Write}; +use std::{ + fmt::{Debug, Write}, + marker::PhantomData, +}; use crate::{CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*}; @@ -11,6 +14,17 @@ impl Debug for Builder { } } +pub struct PrintableModule<'ctx> { + pub phantom: PhantomData<&'ctx ()>, + pub module: ModuleHolder, +} + +impl<'ctx> Debug for PrintableModule<'ctx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.module.fmt(f) + } +} + impl Debug for ModuleHolder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value)) diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index a4eb318..00f878f 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -2,9 +2,10 @@ //! Low-Level IR (LLIR) using [`Context`] and [`Builder`]. This Builder can then //! be used at the end to compile said LLIR into LLVM IR. -use std::marker::PhantomData; +use std::{fmt::Debug, marker::PhantomData}; -use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue}; +use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleHolder, ModuleValue}; +use debug::PrintableModule; pub mod builder; pub mod compile; @@ -76,6 +77,13 @@ impl<'ctx> Module<'ctx> { pub fn value(&self) -> ModuleValue { self.value } + + pub fn as_printable(&self) -> PrintableModule<'ctx> { + PrintableModule { + phantom: PhantomData, + module: self.builder.find_module(self.value), + } + } } #[derive(Debug, Clone, Hash)] diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 6b2c770..a226de7 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, mem}; use reid_lib::{ - builder::InstructionValue, Block, CmpPredicate, ConstValue, Context, Function, FunctionFlags, - Instr, Module, TerminatorKind as Term, Type, + builder::InstructionValue, compile::CompiledModule, Block, CmpPredicate, ConstValue, Context, + Function, FunctionFlags, Instr, Module, TerminatorKind as Term, Type, }; use crate::mir::{self, types::ReturnType, IndexedVariableReference, NamedVariableRef, TypeKind}; @@ -11,16 +11,14 @@ use crate::mir::{self, types::ReturnType, IndexedVariableReference, NamedVariabl /// LLIR that can then be finally compiled into LLVM IR. #[derive(Debug)] pub struct CodegenContext<'ctx> { - modules: Vec>, + context: &'ctx Context, } impl<'ctx> CodegenContext<'ctx> { /// Compile contained LLIR into LLVM IR and produce `hello.o` and /// `hello.asm` - pub fn compile(&self) { - for module in &self.modules { - module.context.compile(); - } + pub fn compile(&self) -> CompiledModule { + self.context.compile() } } @@ -31,18 +29,17 @@ impl mir::Context { for module in &self.modules { modules.push(module.codegen(context)); } - CodegenContext { modules } + CodegenContext { context } } } struct ModuleCodegen<'ctx> { - pub context: &'ctx Context, - _module: Module<'ctx>, + module: Module<'ctx>, } impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.context.fmt(f) + std::fmt::Debug::fmt(&self.module.as_printable(), f) } } @@ -121,10 +118,7 @@ impl mir::Module { } } - ModuleCodegen { - context, - _module: module, - } + ModuleCodegen { module } } } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 31a0a58..939cb32 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -134,7 +134,8 @@ pub fn compile(source: &str, path: PathBuf) -> Result { let codegen_modules = mir_context.codegen(&mut context); dbg!(&codegen_modules); - codegen_modules.compile(); + let compiled = codegen_modules.compile(); + compiled.output(); Ok(String::new()) } diff --git a/reid_src/std.reid b/reid_src/std.reid index 1b69685..1d8be3c 100644 --- a/reid_src/std.reid +++ b/reid_src/std.reid @@ -5,6 +5,3 @@ pub fn print(message: string) { puts(message); } -fn main() -> u16 { - return 0; -}