Merge pull request #2295 from AleoHQ/feat/toggle-dce

Add an option to (dis/en)able DCE in the compiler.
This commit is contained in:
d0cd 2023-03-20 08:53:56 -07:00 committed by GitHub
commit abd25b0896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 27 deletions

View File

@ -30,7 +30,7 @@ use sha2::{Digest, Sha256};
use std::fs;
use std::path::PathBuf;
use crate::OutputOptions;
use crate::CompilerOptions;
/// The primary entry point of the Leo compiler.
#[derive(Clone)]
@ -49,8 +49,8 @@ pub struct Compiler<'a> {
pub ast: Ast,
/// The input ast for the program if it exists.
pub input_ast: Option<InputAst>,
/// Compiler options on some optional output files.
output_options: OutputOptions,
/// Options configuring compilation.
compiler_options: CompilerOptions,
}
impl<'a> Compiler<'a> {
@ -61,7 +61,7 @@ impl<'a> Compiler<'a> {
handler: &'a Handler,
main_file_path: PathBuf,
output_directory: PathBuf,
output_options: Option<OutputOptions>,
compiler_options: Option<CompilerOptions>,
) -> Self {
Self {
handler,
@ -71,7 +71,7 @@ impl<'a> Compiler<'a> {
network,
ast: Ast::new(Program::default()),
input_ast: None,
output_options: output_options.unwrap_or_default(),
compiler_options: compiler_options.unwrap_or_default(),
}
}
@ -111,7 +111,7 @@ impl<'a> Compiler<'a> {
.into());
}
if self.output_options.initial_ast {
if self.compiler_options.initial_ast {
self.write_ast_to_json("initial_ast.json")?;
}
@ -136,9 +136,9 @@ impl<'a> Compiler<'a> {
// Parse and serialize it.
let input_ast = leo_parser::parse_input(self.handler, &input_sf.src, input_sf.start_pos)?;
if self.output_options.initial_ast {
if self.compiler_options.initial_ast {
// Write the input AST snapshot post parsing.
if self.output_options.spans_enabled {
if self.compiler_options.spans_enabled {
input_ast.to_json_file(
self.output_directory.clone(),
&format!("{}.initial_input_ast.json", self.program_name),
@ -172,7 +172,7 @@ impl<'a> Compiler<'a> {
let (ast, symbol_table) = Unroller::do_pass((std::mem::take(&mut self.ast), self.handler, symbol_table))?;
self.ast = ast;
if self.output_options.unrolled_ast {
if self.compiler_options.unrolled_ast {
self.write_ast_to_json("unrolled_ast.json")?;
}
@ -184,7 +184,7 @@ impl<'a> Compiler<'a> {
let (ast, assigner) = StaticSingleAssigner::do_pass((std::mem::take(&mut self.ast), symbol_table))?;
self.ast = ast;
if self.output_options.ssa_ast {
if self.compiler_options.ssa_ast {
self.write_ast_to_json("ssa_ast.json")?;
}
@ -196,7 +196,7 @@ impl<'a> Compiler<'a> {
let (ast, assigner) = Flattener::do_pass((std::mem::take(&mut self.ast), symbol_table, assigner))?;
self.ast = ast;
if self.output_options.flattened_ast {
if self.compiler_options.flattened_ast {
self.write_ast_to_json("flattened_ast.json")?;
}
@ -208,7 +208,7 @@ impl<'a> Compiler<'a> {
let (ast, assigner) = FunctionInliner::do_pass((std::mem::take(&mut self.ast), call_graph, assigner))?;
self.ast = ast;
if self.output_options.inlined_ast {
if self.compiler_options.inlined_ast {
self.write_ast_to_json("inlined_ast.json")?;
}
@ -217,9 +217,11 @@ impl<'a> Compiler<'a> {
/// Runs the dead code elimination pass.
pub fn dead_code_elimination_pass(&mut self) -> Result<()> {
self.ast = DeadCodeEliminator::do_pass(std::mem::take(&mut self.ast))?;
if self.compiler_options.dce_enabled {
self.ast = DeadCodeEliminator::do_pass(std::mem::take(&mut self.ast))?;
}
if self.output_options.dce_ast {
if self.compiler_options.dce_ast {
self.write_ast_to_json("dce_ast.json")?;
}
@ -270,7 +272,7 @@ impl<'a> Compiler<'a> {
/// Writes the AST to a JSON file.
fn write_ast_to_json(&self, file_suffix: &str) -> Result<()> {
// Remove `Span`s if they are not enabled.
if self.output_options.spans_enabled {
if self.compiler_options.spans_enabled {
self.ast.to_json_file(
self.output_directory.clone(),
&format!("{}.{file_suffix}", self.program_name),

View File

@ -17,9 +17,11 @@
// NOTE: If compiler passes are made optional, pass preconditions and invariants may not necessarily hold true.
#[derive(Clone, Default)]
pub struct OutputOptions {
pub struct CompilerOptions {
/// Whether spans are enabled in the output ASTs.
pub spans_enabled: bool,
/// Whether to enable dead code elimination.
pub dce_enabled: bool,
/// If enabled writes the AST after parsing.
pub initial_ast: bool,
/// If enabled writes the input AST after parsing.

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_compiler::{Compiler, OutputOptions};
use leo_compiler::{Compiler, CompilerOptions};
use leo_errors::{
emitter::{Buffer, Emitter, Handler},
LeoError, LeoWarning,
@ -95,8 +95,9 @@ pub fn new_compiler(handler: &Handler, main_file_path: PathBuf) -> Compiler<'_>
handler,
main_file_path,
output_dir,
Some(OutputOptions {
Some(CompilerOptions {
spans_enabled: false,
dce_enabled: true,
initial_input_ast: true,
initial_ast: true,
unrolled_ast: true,

View File

@ -18,7 +18,7 @@ use crate::commands::ALEO_CLI_COMMAND;
use crate::{commands::Command, context::Context};
use leo_ast::Struct;
use leo_compiler::{Compiler, InputAst, OutputOptions};
use leo_compiler::{Compiler, CompilerOptions, InputAst};
use leo_errors::{CliError, CompilerError, PackageError, Result};
use leo_package::source::SourceDirectory;
use leo_package::{inputs::InputFile, outputs::OutputsDirectory};
@ -46,6 +46,8 @@ pub struct BuildOptions {
pub offline: bool,
#[structopt(long, help = "Enable spans in AST snapshots.")]
pub enable_spans: bool,
#[structopt(long, help = "Enables dead code elimination in the compiler.")]
pub enable_dce: bool,
#[structopt(long, help = "Writes all AST snapshots for the different compiler phases.")]
pub enable_all_ast_snapshots: bool,
#[structopt(long, help = "Writes Input AST snapshot of the initial parse.")]
@ -64,10 +66,11 @@ pub struct BuildOptions {
pub enable_dce_ast_snapshot: bool,
}
impl From<BuildOptions> for OutputOptions {
impl From<BuildOptions> for CompilerOptions {
fn from(options: BuildOptions) -> Self {
let mut out_options = Self {
spans_enabled: options.enable_spans,
dce_enabled: options.enable_dce,
initial_input_ast: options.enable_initial_input_ast_snapshot,
initial_ast: options.enable_initial_ast_snapshot,
unrolled_ast: options.enable_unrolled_ast_snapshot,
@ -94,7 +97,7 @@ impl From<BuildOptions> for OutputOptions {
#[derive(StructOpt, Debug)]
pub struct Build {
#[structopt(flatten)]
pub(crate) compiler_options: BuildOptions,
pub(crate) options: BuildOptions,
}
impl Command for Build {
@ -144,7 +147,7 @@ impl Command for Build {
&outputs_directory,
&build_directory,
&handler,
self.compiler_options.clone(),
self.options.clone(),
false,
)?);
}
@ -165,7 +168,7 @@ impl Command for Build {
&outputs_directory,
&build_imports_directory,
&handler,
self.compiler_options.clone(),
self.options.clone(),
true,
)?);
}
@ -197,7 +200,7 @@ impl Command for Build {
// Call the `aleo build` command with the appropriate from the Aleo SDK.
let mut args = vec![ALEO_CLI_COMMAND];
if self.compiler_options.offline {
if self.options.offline {
args.push("--offline");
}
let command = AleoBuild::try_parse_from(&args).map_err(CliError::failed_to_execute_aleo_build)?;

View File

@ -54,7 +54,7 @@ impl Command for Run {
fn prelude(&self, context: Context) -> Result<Self::Input> {
(Build {
compiler_options: self.compiler_options.clone(),
options: self.compiler_options.clone(),
})
.execute(context)
}

View File

@ -16,7 +16,7 @@
//! This file contains tools for benchmarking the Leo compiler and its stages.
use leo_compiler::Compiler;
use leo_compiler::{Compiler, CompilerOptions};
use leo_errors::emitter::{Emitter, Handler};
use leo_span::{source_map::FileName, symbol::SESSION_GLOBALS};
use leo_test_framework::get_benches;
@ -85,7 +85,17 @@ fn new_compiler(handler: &Handler) -> Compiler<'_> {
handler,
PathBuf::from(String::new()),
PathBuf::from(String::new()),
None,
Some(CompilerOptions {
spans_enabled: false,
dce_enabled: true,
initial_ast: false,
initial_input_ast: false,
unrolled_ast: false,
ssa_ast: false,
flattened_ast: false,
inlined_ast: false,
dce_ast: false,
}),
)
}