Skip to content

Commit

Permalink
feat: Separate compilation and expression narrowing in nargo interf…
Browse files Browse the repository at this point in the history
…ace (#4100)

# Description

## Problem\*

## Summary\*

This PR moves the responsibility for transforming a circuit into a
certain expression width into `nargo_cli`. This gives us better
separation of concerns where we no longer need to know the target
backend before we compile a circuit (i.e. we can save a generic artifact
and then target multiple backends using this)

## Additional Context



## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
TomAFrench authored Jan 23, 2024
1 parent c29f85f commit 62a4e37
Show file tree
Hide file tree
Showing 18 changed files with 95 additions and 96 deletions.
4 changes: 2 additions & 2 deletions compiler/noirc_driver/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub enum ContractFunctionType {
Unconstrained,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CompiledContract {
pub noir_version: String,

Expand All @@ -51,7 +51,7 @@ pub struct CompiledContract {
/// A contract function unlike a regular Noir program
/// however can have additional properties.
/// One of these being a function type.
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContractFunction {
pub name: String,

Expand Down
5 changes: 3 additions & 2 deletions compiler/wasm/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ pub fn compile(
})?
.0;

let optimized_contract = nargo::ops::optimize_contract(compiled_contract, expression_width);
let optimized_contract =
nargo::ops::transform_contract(compiled_contract, expression_width);

let compile_output = generate_contract_artifact(optimized_contract);
Ok(JsCompileResult::new(compile_output))
Expand All @@ -205,7 +206,7 @@ pub fn compile(
})?
.0;

let optimized_program = nargo::ops::optimize_program(compiled_program, expression_width);
let optimized_program = nargo::ops::transform_program(compiled_program, expression_width);

let compile_output = generate_program_artifact(optimized_program);
Ok(JsCompileResult::new(compile_output))
Expand Down
4 changes: 2 additions & 2 deletions compiler/wasm/src/compile_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl CompilerContext {
})?
.0;

let optimized_program = nargo::ops::optimize_program(compiled_program, np_language);
let optimized_program = nargo::ops::transform_program(compiled_program, np_language);

let compile_output = generate_program_artifact(optimized_program);
Ok(JsCompileResult::new(compile_output))
Expand All @@ -134,7 +134,7 @@ impl CompilerContext {
})?
.0;

let optimized_contract = nargo::ops::optimize_contract(compiled_contract, np_language);
let optimized_contract = nargo::ops::transform_contract(compiled_contract, np_language);

let compile_output = generate_contract_artifact(optimized_contract);
Ok(JsCompileResult::new(compile_output))
Expand Down
20 changes: 13 additions & 7 deletions tooling/lsp/src/requests/profile_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,32 @@ fn on_profile_run_request_inner(
&workspace_file_manager,
&parsed_files,
&workspace,
expression_width,
&CompileOptions::default(),
)
.map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?;

let mut opcodes_counts: HashMap<Location, OpCodesCount> = HashMap::new();
let mut file_map: BTreeMap<FileId, DebugFile> = BTreeMap::new();
for compiled_program in &compiled_programs {
for compiled_program in compiled_programs {
let compiled_program =
nargo::ops::transform_program(compiled_program, expression_width);

let span_opcodes = compiled_program.debug.count_span_opcodes();
let debug_artifact: DebugArtifact = compiled_program.clone().into();
opcodes_counts.extend(span_opcodes);
file_map.extend(debug_artifact.file_map);
}

for compiled_contract in &compiled_contracts {
let functions = &compiled_contract.functions;
let debug_artifact: DebugArtifact = compiled_contract.clone().into();
for compiled_contract in compiled_contracts {
let compiled_contract =
nargo::ops::transform_contract(compiled_contract, expression_width);

let function_debug_info: Vec<_> =
compiled_contract.functions.iter().map(|func| &func.debug).cloned().collect();
let debug_artifact: DebugArtifact = compiled_contract.into();
file_map.extend(debug_artifact.file_map);
for contract_function in functions {
let span_opcodes = contract_function.debug.count_span_opcodes();
for contract_function_debug in function_debug_info {
let span_opcodes = contract_function_debug.count_span_opcodes();
opcodes_counts.extend(span_opcodes);
}
}
Expand Down
12 changes: 6 additions & 6 deletions tooling/nargo/src/artifacts/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,18 @@ impl From<CompiledProgram> for DebugArtifact {
}
}

impl From<&CompiledContract> for DebugArtifact {
fn from(compiled_artifact: &CompiledContract) -> Self {
impl From<CompiledContract> for DebugArtifact {
fn from(compiled_artifact: CompiledContract) -> Self {
let all_functions_debug: Vec<DebugInfo> = compiled_artifact
.functions
.iter()
.map(|contract_function| contract_function.debug.clone())
.into_iter()
.map(|contract_function| contract_function.debug)
.collect();

DebugArtifact {
debug_symbols: all_functions_debug,
file_map: compiled_artifact.file_map.clone(),
warnings: compiled_artifact.warnings.clone(),
file_map: compiled_artifact.file_map,
warnings: compiled_artifact.warnings,
}
}
}
Expand Down
35 changes: 4 additions & 31 deletions tooling/nargo/src/ops/compile.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use acvm::ExpressionWidth;
use fm::FileManager;
use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram};
use noirc_frontend::hir::ParsedFiles;
Expand All @@ -18,7 +17,6 @@ pub fn compile_workspace(
file_manager: &FileManager,
parsed_files: &ParsedFiles,
workspace: &Workspace,
expression_width: ExpressionWidth,
compile_options: &CompileOptions,
) -> Result<(Vec<CompiledProgram>, Vec<CompiledContract>), CompileError> {
let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace
Expand All @@ -30,22 +28,11 @@ pub fn compile_workspace(
// Compile all of the packages in parallel.
let program_results: Vec<CompilationResult<CompiledProgram>> = binary_packages
.par_iter()
.map(|package| {
compile_program(
file_manager,
parsed_files,
package,
compile_options,
expression_width,
None,
)
})
.map(|package| compile_program(file_manager, parsed_files, package, compile_options, None))
.collect();
let contract_results: Vec<CompilationResult<CompiledContract>> = contract_packages
.par_iter()
.map(|package| {
compile_contract(file_manager, parsed_files, package, compile_options, expression_width)
})
.map(|package| compile_contract(file_manager, parsed_files, package, compile_options))
.collect();

// Report any warnings/errors which were encountered during compilation.
Expand Down Expand Up @@ -80,34 +67,20 @@ pub fn compile_program(
parsed_files: &ParsedFiles,
package: &Package,
compile_options: &CompileOptions,
expression_width: ExpressionWidth,
cached_program: Option<CompiledProgram>,
) -> CompilationResult<CompiledProgram> {
let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package);

let (program, warnings) =
noirc_driver::compile_main(&mut context, crate_id, compile_options, cached_program)?;

// Apply backend specific optimizations.
let optimized_program = crate::ops::optimize_program(program, expression_width);

Ok((optimized_program, warnings))
noirc_driver::compile_main(&mut context, crate_id, compile_options, cached_program)
}

pub fn compile_contract(
file_manager: &FileManager,
parsed_files: &ParsedFiles,
package: &Package,
compile_options: &CompileOptions,
expression_width: ExpressionWidth,
) -> CompilationResult<CompiledContract> {
let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package);
let (contract, warnings) =
noirc_driver::compile_contract(&mut context, crate_id, compile_options)?;

let optimized_contract = crate::ops::optimize_contract(contract, expression_width);

Ok((optimized_contract, warnings))
noirc_driver::compile_contract(&mut context, crate_id, compile_options)
}

pub(crate) fn report_errors<T>(
Expand Down
3 changes: 3 additions & 0 deletions tooling/nargo/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ pub use self::compile::{compile_contract, compile_program, compile_workspace};
pub use self::execute::execute_circuit;
pub use self::foreign_calls::{DefaultForeignCallExecutor, ForeignCallExecutor};
pub use self::optimize::{optimize_contract, optimize_program};
pub use self::transform::{transform_contract, transform_program};

pub use self::test::{run_test, TestStatus};

mod compile;
mod execute;
mod foreign_calls;
mod optimize;
mod test;
mod transform;
18 changes: 4 additions & 14 deletions tooling/nargo/src/ops/optimize.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
use acvm::ExpressionWidth;
use iter_extended::vecmap;
use noirc_driver::{CompiledContract, CompiledProgram};

pub fn optimize_program(
mut program: CompiledProgram,
expression_width: ExpressionWidth,
) -> CompiledProgram {
let (optimized_circuit, location_map) =
acvm::compiler::compile(program.circuit, expression_width);

pub fn optimize_program(mut program: CompiledProgram) -> CompiledProgram {
let (optimized_circuit, location_map) = acvm::compiler::optimize(program.circuit);
program.circuit = optimized_circuit;
program.debug.update_acir(location_map);
program
}

pub fn optimize_contract(
contract: CompiledContract,
expression_width: ExpressionWidth,
) -> CompiledContract {
pub fn optimize_contract(contract: CompiledContract) -> CompiledContract {
let functions = vecmap(contract.functions, |mut func| {
let (optimized_bytecode, location_map) =
acvm::compiler::compile(func.bytecode, expression_width);
let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode);
func.bytecode = optimized_bytecode;
func.debug.update_acir(location_map);
func
Expand Down
30 changes: 30 additions & 0 deletions tooling/nargo/src/ops/transform.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use acvm::ExpressionWidth;
use iter_extended::vecmap;
use noirc_driver::{CompiledContract, CompiledProgram};

pub fn transform_program(
mut program: CompiledProgram,
expression_width: ExpressionWidth,
) -> CompiledProgram {
let (optimized_circuit, location_map) =
acvm::compiler::compile(program.circuit, expression_width);

program.circuit = optimized_circuit;
program.debug.update_acir(location_map);
program
}

pub fn transform_contract(
contract: CompiledContract,
expression_width: ExpressionWidth,
) -> CompiledContract {
let functions = vecmap(contract.functions, |mut func| {
let (optimized_bytecode, location_map) =
acvm::compiler::compile(func.bytecode, expression_width);
func.bytecode = optimized_bytecode;
func.debug.update_acir(location_map);
func
});

CompiledContract { functions, ..contract }
}
3 changes: 2 additions & 1 deletion tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ pub(crate) fn run(
&parsed_files,
package,
&args.compile_options,
expression_width,
None,
);

Expand All @@ -64,6 +63,8 @@ pub(crate) fn run(
args.compile_options.silence_warnings,
)?;

let program = nargo::ops::transform_program(program, expression_width);

let smart_contract_string = backend.eth_contract(&program.circuit)?;

let contract_dir = workspace.contracts_directory_path(package);
Expand Down
19 changes: 4 additions & 15 deletions tooling/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::path::Path;

use acvm::ExpressionWidth;

use fm::FileManager;
use nargo::artifacts::program::ProgramArtifact;
use nargo::errors::CompileError;
Expand Down Expand Up @@ -68,7 +66,6 @@ pub(crate) fn run(
&workspace_file_manager,
&parsed_files,
&workspace,
expression_width,
&args.compile_options,
)?;

Expand All @@ -81,9 +78,11 @@ pub(crate) fn run(
// Save build artifacts to disk.
let only_acir = args.compile_options.only_acir;
for (package, program) in binary_packages.into_iter().zip(compiled_program) {
let program = nargo::ops::transform_program(program, expression_width);
save_program(program.clone(), &package, &workspace.target_directory_path(), only_acir);
}
for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) {
let contract = nargo::ops::transform_contract(contract, expression_width);
save_contract(contract, &package, &circuit_dir);
}

Expand All @@ -94,7 +93,6 @@ pub(super) fn compile_workspace(
file_manager: &FileManager,
parsed_files: &ParsedFiles,
workspace: &Workspace,
expression_width: ExpressionWidth,
compile_options: &CompileOptions,
) -> Result<(Vec<CompiledProgram>, Vec<CompiledContract>), CliError> {
let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace
Expand All @@ -114,21 +112,12 @@ pub(super) fn compile_workspace(
.filter(|p| p.noir_version == NOIR_ARTIFACT_VERSION_STRING)
.map(|p| p.into());

compile_program(
file_manager,
parsed_files,
package,
compile_options,
expression_width,
cached_program,
)
compile_program(file_manager, parsed_files, package, compile_options, cached_program)
})
.collect();
let contract_results: Vec<CompilationResult<CompiledContract>> = contract_packages
.par_iter()
.map(|package| {
compile_contract(file_manager, parsed_files, package, compile_options, expression_width)
})
.map(|package| compile_contract(file_manager, parsed_files, package, compile_options))
.collect();

// Report any warnings/errors which were encountered during compilation.
Expand Down
12 changes: 4 additions & 8 deletions tooling/nargo_cli/src/cli/dap_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,8 @@ fn load_and_compile_project(
let parsed_files = parse_all(&workspace_file_manager);

let compile_options = CompileOptions::default();
let compilation_result = compile_program(
&workspace_file_manager,
&parsed_files,
package,
&compile_options,
expression_width,
None,
);
let compilation_result =
compile_program(&workspace_file_manager, &parsed_files, package, &compile_options, None);

let compiled_program = report_errors(
compilation_result,
Expand All @@ -91,6 +85,8 @@ fn load_and_compile_project(
)
.map_err(|_| LoadError("Failed to compile project"))?;

let compiled_program = nargo::ops::transform_program(compiled_program, expression_width);

let (inputs_map, _) =
read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)
.map_err(|_| LoadError("Failed to read program inputs"))?;
Expand Down
3 changes: 2 additions & 1 deletion tooling/nargo_cli/src/cli/debug_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ pub(crate) fn run(
&parsed_files,
package,
&args.compile_options,
expression_width,
None,
);

Expand All @@ -83,6 +82,8 @@ pub(crate) fn run(
args.compile_options.silence_warnings,
)?;

let compiled_program = nargo::ops::transform_program(compiled_program, expression_width);

run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir)
}

Expand Down
Loading

0 comments on commit 62a4e37

Please sign in to comment.