Make linking modules together work, fix printing modules
This commit is contained in:
		
							parent
							
								
									848347e4a8
								
							
						
					
					
						commit
						2b47c4efc7
					
				| @ -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<RefCell<Vec<ModuleHolder>>> { | ||||
|         self.modules.clone() | ||||
|     } | ||||
|  | ||||
| @ -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 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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)) | ||||
|  | ||||
| @ -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)] | ||||
|  | ||||
| @ -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<ModuleCodegen<'ctx>>, | ||||
|     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 } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -134,7 +134,8 @@ pub fn compile(source: &str, path: PathBuf) -> Result<String, ReidError> { | ||||
|     let codegen_modules = mir_context.codegen(&mut context); | ||||
| 
 | ||||
|     dbg!(&codegen_modules); | ||||
|     codegen_modules.compile(); | ||||
|     let compiled = codegen_modules.compile(); | ||||
|     compiled.output(); | ||||
| 
 | ||||
|     Ok(String::new()) | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,3 @@ pub fn print(message: string) { | ||||
|     puts(message); | ||||
| } | ||||
| 
 | ||||
| fn main() -> u16 { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user