Skip to content

Commit

Permalink
refactor: integrate diagnostic context into compilation session
Browse files Browse the repository at this point in the history
  • Loading branch information
junlarsen committed Feb 9, 2025
1 parent 0948212 commit e13b2ce
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 33 deletions.
12 changes: 6 additions & 6 deletions compiler/eight-driver/src/bin/eightc.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
}
39 changes: 24 additions & 15 deletions compiler/eight-driver/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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| {
Expand Down Expand Up @@ -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<CompileSession<'c>>,
pub(crate) ast_arena: ManuallyDrop<AstArena<'c>>,
pub(crate) session: ManuallyDrop<CompileSession<'session>>,
pub(crate) ast_arena: ManuallyDrop<AstArena<'session>>,
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!(
Expand Down Expand Up @@ -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<O>(
&'c self,
&'session self,
cond: bool,
operation: impl FnOnce(&'c Pipeline<'c>) -> Result<O, PipelineError>,
operation: impl FnOnce(&'session Pipeline<'session>) -> Result<O, PipelineError>,
) -> Result<O, PipelineError> {
if cond {
operation(self)
Expand Down
27 changes: 15 additions & 12 deletions compiler/eight-middle/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Bump>,
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.
Expand Down

0 comments on commit e13b2ce

Please sign in to comment.