Skip to content

Commit

Permalink
fix: properly handle emitting final artifacts in midenc-compile
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwalker committed Nov 20, 2023
1 parent f426ae3 commit 8c08e8a
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 3 deletions.
35 changes: 35 additions & 0 deletions codegen/masm/src/masm/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,41 @@ impl Program {
Ok(Self::from_masl_library(&library, codemap))
}

pub fn to_masl_library<S: AsRef<str>>(
&self,
root_ns: S,
codemap: &miden_diagnostics::CodeMap,
) -> Result<miden_assembly::MaslLibrary, miden_assembly::LibraryError> {
use miden_assembly::{LibraryNamespace, MaslLibrary, Version};
use std::collections::BTreeSet;

let ns = LibraryNamespace::new(root_ns)?;
let version = Version::default();
let has_source_locations = false;
let mut modules = Vec::with_capacity(self.modules.iter().count());
let mut dependencies = BTreeSet::default();
for module in self.modules() {
for import in module.imports.iter() {
if self.modules.get(&import.name).is_some() {
continue;
}
let root = match import.name.as_str().split_once("::") {
None => LibraryNamespace::new(import.name.as_str())?,
Some((root, _)) => LibraryNamespace::new(root)?,
};
dependencies.insert(root);
}
modules.push(module.to_module_ast(codemap));
}
MaslLibrary::new(
ns,
version,
has_source_locations,
modules,
dependencies.into_iter().collect(),
)
}

/// Convert a [miden_assembly::MaslLibrary] into a [Program]
pub fn from_masl_library(
library: &miden_assembly::MaslLibrary,
Expand Down
52 changes: 49 additions & 3 deletions midenc-compile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use self::stages::*;

use std::sync::Arc;

use miden_hir::pass::AnalysisManager;
use midenc_session::Session;
use miden_codegen_masm as masm;
use miden_hir::{pass::AnalysisManager, Symbol};
use midenc_session::{OutputType, Session};

pub use self::stages::Compiled;

Expand Down Expand Up @@ -44,6 +45,9 @@ pub enum CompilerError {
/// An error occurred while linking a program
#[error(transparent)]
Linker(#[from] miden_hir::LinkerError),
/// An error occurred while emitting a MASL library
#[error(transparent)]
Masl(#[from] miden_assembly::LibraryError),
/// An error ocurred when reading a file
#[error(transparent)]
Io(#[from] std::io::Error),
Expand Down Expand Up @@ -122,7 +126,49 @@ pub fn compile(session: Arc<Session>) -> CompilerResult<()> {
let inputs = vec![session.input.clone()];
let mut analyses = AnalysisManager::new();
match compile_inputs(inputs, &mut analyses, &session) {
Ok(_) | Err(CompilerError::Stopped) => return Ok(()),
Ok(Compiled::Program(ref program)) => {
if let Some(path) = session.emit_to(OutputType::Masl, None) {
use miden_assembly::utils::Serializable;
let masl = program.to_masl_library(session.name(), &session.codemap)?;
let bytes = masl.to_bytes();
std::fs::write(&path, bytes)?;
}
if session.should_emit(OutputType::Masm) {
for module in program.modules() {
session.emit(module)?;
}
if program.is_executable() {
use miden_assembly::LibraryPath;
let ast = program.to_program_ast(&session.codemap);
if let Some(path) = session.emit_to(
OutputType::Masm,
Some(Symbol::intern(LibraryPath::EXEC_PATH)),
) {
ast.write_to_file(path)?;
} else {
println!("{ast}");
}
}
}
}
Ok(Compiled::Modules(modules)) => {
let mut program = masm::Program::new();
for module in modules.into_iter() {
program.insert(module);
}
if let Some(path) = session.emit_to(OutputType::Masl, None) {
use miden_assembly::utils::Serializable;
let masl = program.to_masl_library(session.name(), &session.codemap)?;
let bytes = masl.to_bytes();
std::fs::write(&path, bytes)?;
}
if session.should_emit(OutputType::Masm) {
for module in program.modules() {
session.emit(module)?;
}
}
}
Err(CompilerError::Stopped) => return Ok(()),
Err(CompilerError::Reported) => return Err(CompilerError::Reported),
Err(err) => {
session.diagnostics.error(err);
Expand Down
4 changes: 4 additions & 0 deletions midenc-session/src/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ impl InputFile {
}
}

pub fn is_real(&self) -> bool {
matches!(self.file, InputType::Real(_))
}

pub fn filestem(&self) -> &str {
match &self.file {
InputType::Real(ref path) => path.file_stem().unwrap().to_str().unwrap(),
Expand Down
39 changes: 39 additions & 0 deletions midenc-session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,28 @@ impl Session {
&self.arg_matches
}

/// The name of this session (used as the name of the project, output file, etc.)
pub fn name(&self) -> String {
self.options
.name
.clone()
.or_else(|| {
if self.input.is_real() {
Some(self.input.filestem().to_string())
} else {
None
}
})
.unwrap_or_else(|| {
self.options
.current_dir
.file_name()
.unwrap()
.to_string_lossy()
.into_owned()
})
}

pub fn out_filename(&self, outputs: &OutputFiles, progname: Symbol) -> OutputFile {
let default_filename = self.filename_for_input(outputs, progname);
let out_filename = outputs
Expand Down Expand Up @@ -240,6 +262,23 @@ impl Session {
self.options.output_types.contains_key(&ty)
}

/// Get the path to emit the given [OutputType] to
pub fn emit_to(&self, ty: OutputType, name: Option<Symbol>) -> Option<PathBuf> {
if self.should_emit(ty) {
match self.output_files.path(ty) {
OutputFile::Real(path) => name
.map(|name| {
path.with_file_name(name.as_str())
.with_extension(ty.extension())
})
.or(Some(path)),
OutputFile::Stdout => None,
}
} else {
None
}
}

/// Emit an item to stdout/file system depending on the current configuration
pub fn emit<E: Emit>(&self, item: &E) -> std::io::Result<()> {
let output_type = item.output_type();
Expand Down

0 comments on commit 8c08e8a

Please sign in to comment.