Make linking modules together work, fix printing modules

This commit is contained in:
Sofia 2025-07-14 21:10:13 +03:00
parent 848347e4a8
commit 2b47c4efc7
7 changed files with 147 additions and 87 deletions

View File

@ -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()
}

View File

@ -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
}
}
}

View File

@ -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))

View File

@ -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)]

View File

@ -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 }
}
}

View File

@ -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())
}

View File

@ -5,6 +5,3 @@ pub fn print(message: string) {
puts(message);
}
fn main() -> u16 {
return 0;
}