diff --git a/crates/nargo_cli/src/cli/info_cmd.rs b/crates/nargo_cli/src/cli/info_cmd.rs index 7ad0a2caf8c..519ecff9f0b 100644 --- a/crates/nargo_cli/src/cli/info_cmd.rs +++ b/crates/nargo_cli/src/cli/info_cmd.rs @@ -1,19 +1,27 @@ +use super::compile_cmd::report_errors; +use super::NargoConfig; +use crate::cli::compile_cmd::compile_circuit; +use crate::errors::CliError; +use crate::resolver::resolve_root_manifest; use acvm::Backend; use clap::Args; -use noirc_driver::CompileOptions; +use noirc_driver::{compile_contracts, CompileOptions}; use std::path::Path; -use crate::cli::compile_cmd::compile_circuit; -use crate::errors::CliError; - -use super::NargoConfig; - -/// Provides detailed informaton on a circuit +/// Provides detailed information on a circuit /// Current information provided: /// 1. The number of ACIR opcodes /// 2. Counts the final number gates in the circuit used by a backend #[derive(Debug, Clone, Args)] pub(crate) struct InfoCommand { + /// Get information of all contracts used within the program + #[arg(short, long)] + contracts: bool, + + /// Get information of a contract used within the program + #[arg(short, long)] + contract: Option, + #[clap(flatten)] compile_options: CompileOptions, } @@ -23,28 +31,135 @@ pub(crate) fn run( args: InfoCommand, config: NargoConfig, ) -> Result<(), CliError> { - count_opcodes_and_gates_with_path(backend, config.program_dir, &args.compile_options) + count_opcodes_and_gates_with_path(backend, config.program_dir, args) } fn count_opcodes_and_gates_with_path>( backend: &B, program_dir: P, - compile_options: &CompileOptions, + args: InfoCommand, ) -> Result<(), CliError> { - let (compiled_program, _) = - compile_circuit(backend, None, program_dir.as_ref(), compile_options)?; - let num_opcodes = compiled_program.circuit.opcodes.len(); - - println!( - "Total ACIR opcodes generated for language {:?}: {}", - backend.np_language(), - num_opcodes - ); - - let exact_circuit_size = backend - .get_exact_circuit_size(&compiled_program.circuit) - .map_err(CliError::ProofSystemCompilerError)?; - println!("Backend circuit size: {exact_circuit_size}"); + if args.contracts { + let (mut context, crate_id) = resolve_root_manifest(program_dir.as_ref(), None)?; + + let result = compile_contracts(&mut context, crate_id, &args.compile_options); + let contracts = report_errors(result, &context, args.compile_options.deny_warnings)?; + + let mut total_num_opcodes_in_all_contracts = 0; + let mut total_num_circuit_size_in_all_contracts = 0; + + for contract in contracts { + let mut total_num_opcodes = 0; + let mut total_circuit_size = 0; + let mut function_info = Vec::new(); + for function in contract.functions { + let num_opcodes = function.bytecode.opcodes.len(); + let exact_circuit_size = backend + .get_exact_circuit_size(&function.bytecode) + .map_err(CliError::ProofSystemCompilerError)?; + total_num_opcodes += num_opcodes; + total_circuit_size += exact_circuit_size; + function_info.push((function.name, num_opcodes, exact_circuit_size)); + } + total_num_opcodes_in_all_contracts += total_num_opcodes; + total_num_circuit_size_in_all_contracts += total_circuit_size; + + println!( + "Total ACIR opcodes generated for language {:?} in contract {}: {}", + backend.np_language(), + contract.name, + total_num_opcodes + ); + println!( + "Backend circuit size for contract {}: {total_circuit_size} \n", + contract.name + ); + + for info in function_info { + println!( + "Total ACIR opcodes generated for function {} in contract {}: {}", + info.0, contract.name, info.1, + ); + println!( + "Backend circuit size for function {} in contract {}: {}", + info.0, contract.name, info.2 + ); + } + } + + println!( + "\nTotal ACIR opcodes generated for language {:?} in All Contracts: {}", + backend.np_language(), + total_num_opcodes_in_all_contracts + ); + println!( + "Backend circuit size for All Contracts: {total_num_circuit_size_in_all_contracts}" + ); + } else if args.contract.is_some() { + let contract_name = args.contract.unwrap(); + let (mut context, crate_id) = resolve_root_manifest(program_dir.as_ref(), None)?; + let result = compile_contracts(&mut context, crate_id, &args.compile_options); + let contracts = report_errors(result, &context, args.compile_options.deny_warnings)?; + + for contract in contracts { + if contract.name == contract_name { + let mut total_num_opcodes = 0; + let mut total_circuit_size = 0; + let mut function_info = Vec::new(); + for function in contract.functions { + let num_opcodes = function.bytecode.opcodes.len(); + let exact_circuit_size = backend + .get_exact_circuit_size(&function.bytecode) + .map_err(CliError::ProofSystemCompilerError)?; + total_num_opcodes += num_opcodes; + total_circuit_size += exact_circuit_size; + function_info.push((function.name, num_opcodes, exact_circuit_size)); + } + + println!( + "Total ACIR opcodes generated for language {:?} in contract {}: {}", + backend.np_language(), + contract.name, + total_num_opcodes + ); + println!( + "Backend circuit size for contract {}: {total_circuit_size}", + contract.name + ); + println!(); + + for info in function_info { + println!( + "Total ACIR opcodes generated for function {} in contract {}: {}", + info.0, contract.name, info.1, + ); + println!( + "Backend circuit size for function {} in contract {}: {}", + info.0, contract.name, info.2 + ); + } + + break; + } + + println!("Cannot find contract"); + } + } else { + let (compiled_program, _) = + compile_circuit(backend, None, program_dir.as_ref(), &args.compile_options)?; + let num_opcodes = compiled_program.circuit.opcodes.len(); + + println!( + "Total ACIR opcodes generated for language {:?}: {}", + backend.np_language(), + num_opcodes + ); + + let exact_circuit_size = backend + .get_exact_circuit_size(&compiled_program.circuit) + .map_err(CliError::ProofSystemCompilerError)?; + println!("Backend circuit size: {exact_circuit_size}"); + } Ok(()) }