diff --git a/compiler/eight-driver/src/bin/eightc.rs b/compiler/eight-driver/src/bin/eightc.rs index 2d540ac..1bb9c54 100644 --- a/compiler/eight-driver/src/bin/eightc.rs +++ b/compiler/eight-driver/src/bin/eightc.rs @@ -1,7 +1,7 @@ use clap::{Parser, ValueEnum}; -use eight_diagnostics::context::{DiagnosticContext, DiagnosticSource}; +use eight_diagnostics::context::DiagnosticSource; use eight_driver::pipeline::{ - execute_compilation_pipeline, PipelineError, PipelineOptions, TerminationStep, + execute_compilation_pipeline, Pipeline, PipelineError, PipelineOptions, TerminationStep, }; use eight_driver::query::{EmitQuery, QueryError}; use std::io::Read; @@ -98,15 +98,15 @@ fn main() -> miette::Result<()> { } }; - let dcx = DiagnosticContext::new(&source, 16); let options = args.try_into()?; - match execute_compilation_pipeline(options, &source) { + let pipeline = Pipeline::new(options, &source); + match execute_compilation_pipeline(&pipeline) { Err(PipelineError::StopToken(msg)) => { eprintln!("eightc: early termination due to: {}", msg); std::process::exit(1); } - Err(e) => dcx.emit_fatal_diagnostic(e), + Err(e) => pipeline.dcx().emit_fatal_diagnostic(e), _ => {} }; - std::process::exit(dcx.is_empty() as i32); + std::process::exit(pipeline.dcx().is_empty() as i32); } diff --git a/compiler/eight-driver/src/pipeline.rs b/compiler/eight-driver/src/pipeline.rs index 51ba552..a661312 100644 --- a/compiler/eight-driver/src/pipeline.rs +++ b/compiler/eight-driver/src/pipeline.rs @@ -9,7 +9,7 @@ use crate::operations::mir_codegen_llvm::MirCodegenLLVMPass; use crate::operations::mir_emit::MirEmitPass; use crate::query::EmitQuery; use eight_codegen_llvm::error::LLVMBackendError; -use eight_diagnostics::context::DiagnosticSource; +use eight_diagnostics::context::{DiagnosticContext, DiagnosticSource}; use eight_diagnostics::errors::hir::HirError; use eight_diagnostics::errors::mir::MirError; use eight_diagnostics::errors::syntax::ParseError; @@ -21,14 +21,12 @@ use std::mem::ManuallyDrop; use thiserror::Error; /// Execute the entire compilation pipeline. -pub fn execute_compilation_pipeline( - opts: PipelineOptions, - input: &DiagnosticSource, +pub fn execute_compilation_pipeline<'session>( + pipeline: &'session Pipeline<'session>, ) -> Result<(), PipelineError> { - let pipeline = Pipeline::new(opts); // Syntax passes are always ran, otherwise there's nothing for the compiler to do. - let module = AstParsePass::execute(&pipeline, input.source())?; - let module = AstEmitPass::execute(&pipeline, module)?; + let module = AstParsePass::execute(pipeline, pipeline.source().source())?; + let module = AstEmitPass::execute(pipeline, module)?; // Gate the HIR passes behind --terminator=syntax let module = pipeline.run_pass_collection_if(pipeline.is_requesting_hir(), move |pipeline| { @@ -101,21 +99,32 @@ pub struct PipelineOptions { } /// A compilation pipeline for the compiler. -pub struct Pipeline<'c> { +pub struct Pipeline<'session> { pub(crate) opts: PipelineOptions, - pub(crate) session: ManuallyDrop>, - pub(crate) ast_arena: ManuallyDrop>, + pub(crate) session: ManuallyDrop>, + pub(crate) ast_arena: ManuallyDrop>, + source: &'session DiagnosticSource, } -impl<'c> Pipeline<'c> { - pub fn new(opts: PipelineOptions) -> Self { +impl<'session> Pipeline<'session> { + pub fn new(opts: PipelineOptions, source: &'session DiagnosticSource) -> Self { Self { opts, - session: ManuallyDrop::new(CompileSession::new()), + source, + session: ManuallyDrop::new(CompileSession::new(source)), ast_arena: ManuallyDrop::new(AstArena::default()), } } + /// Get the source for the pipeline. + pub fn source(&self) -> &DiagnosticSource { + self.source + } + + pub fn dcx(&self) -> &DiagnosticContext<'session> { + self.session.dcx() + } + /// Codegen passes run if the stop token is not set to MIR. pub fn is_requesting_codegen(&self) -> bool { !matches!( @@ -154,9 +163,9 @@ impl<'c> Pipeline<'c> { /// This is used for grouping passes under conditions. This can for example, disable codegen if /// compiler arguments specify to not run the backend. pub fn run_pass_collection_if( - &'c self, + &'session self, cond: bool, - operation: impl FnOnce(&'c Pipeline<'c>) -> Result, + operation: impl FnOnce(&'session Pipeline<'session>) -> Result, ) -> Result { if cond { operation(self) diff --git a/compiler/eight-middle/src/context.rs b/compiler/eight-middle/src/context.rs index f20beb6..60c579c 100644 --- a/compiler/eight-middle/src/context.rs +++ b/compiler/eight-middle/src/context.rs @@ -7,32 +7,35 @@ use crate::mir::{ MirBoolType, MirFunctionType, MirInteger32Type, MirPointerType, MirTy, MirTyId, MirVoidType, }; use bumpalo::Bump; +use eight_diagnostics::context::{DiagnosticContext, DiagnosticSource}; use eight_span::Span; use std::rc::Rc; /// A shared context for the middle-end and backend components. -pub struct CompileSession<'be> { +pub struct CompileSession<'session> { + dcx: DiagnosticContext<'session>, allocator: Rc, - strings: StringInterner<'be>, - mir_types: TypedInterner<'be, MirTyId, MirTy<'be>>, - hir_types: TypedInterner<'be, HirTyId, HirTy<'be>>, + strings: StringInterner<'session>, + mir_types: TypedInterner<'session, MirTyId, MirTy<'session>>, + hir_types: TypedInterner<'session, HirTyId, HirTy<'session>>, } -impl Default for CompileSession<'_> { - fn default() -> Self { +impl<'be> CompileSession<'be> { + pub fn new(source: &'be DiagnosticSource) -> Self { + let dcx = DiagnosticContext::new(source, 16); let alloc = Rc::new(Bump::new()); Self { - allocator: Rc::new(Bump::new()), + dcx, strings: StringInterner::new(alloc.clone()), mir_types: TypedInterner::new(alloc.clone()), - hir_types: TypedInterner::new(alloc), + hir_types: TypedInterner::new(alloc.clone()), + allocator: alloc, } } -} -impl<'be> CompileSession<'be> { - pub fn new() -> Self { - Self::default() + /// Get a reference to the diagnostic context. + pub fn dcx(&self) -> &DiagnosticContext<'be> { + &self.dcx } /// Allocate a value into the arena.