Skip to content

Commit

Permalink
feat: short-circuit compilation and read build artifacts from file if…
Browse files Browse the repository at this point in the history
… program is unchanged (#2743)
  • Loading branch information
TomAFrench authored Sep 20, 2023
1 parent 4392f96 commit 87fea4b
Show file tree
Hide file tree
Showing 20 changed files with 164 additions and 177 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ url = "2.2.0"
wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] }
wasm-bindgen-test = "0.3.33"
base64 = "0.21.2"
fxhash = "0.2.1"
1 change: 1 addition & 0 deletions compiler/noirc_driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ acvm.workspace = true
fm.workspace = true
serde.workspace = true
base64.workspace = true
fxhash.workspace = true
17 changes: 13 additions & 4 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub type CompilationResult<T> = Result<(T, Warnings), ErrorsAndWarnings>;
// with the restricted version which only uses one file
pub fn compile_file(context: &mut Context, root_file: &Path) -> CompilationResult<CompiledProgram> {
let crate_id = prepare_crate(context, root_file);
compile_main(context, crate_id, &CompileOptions::default())
compile_main(context, crate_id, &CompileOptions::default(), None)
}

/// Adds the file from the file system at `Path` to the crate graph as a root file
Expand Down Expand Up @@ -143,6 +143,7 @@ pub fn compile_main(
context: &mut Context,
crate_id: CrateId,
options: &CompileOptions,
cached_program: Option<CompiledProgram>,
) -> CompilationResult<CompiledProgram> {
let (_, warnings) = check_crate(context, crate_id, options.deny_warnings)?;

Expand All @@ -158,7 +159,7 @@ pub fn compile_main(
}
};

let compiled_program = compile_no_check(context, options, main)?;
let compiled_program = compile_no_check(context, options, main, cached_program)?;

if options.print_acir {
println!("Compiled ACIR for main (unoptimized):");
Expand Down Expand Up @@ -252,7 +253,7 @@ fn compile_contract_inner(
continue;
}

let function = match compile_no_check(context, options, function_id) {
let function = match compile_no_check(context, options, function_id, None) {
Ok(function) => function,
Err(new_error) => {
errors.push(new_error);
Expand Down Expand Up @@ -295,13 +296,21 @@ pub fn compile_no_check(
context: &Context,
options: &CompileOptions,
main_function: FuncId,
cached_program: Option<CompiledProgram>,
) -> Result<CompiledProgram, FileDiagnostic> {
let program = monomorphize(main_function, &context.def_interner);

let hash = fxhash::hash64(&program);
if let Some(cached_program) = cached_program {
if hash == cached_program.hash {
return Ok(cached_program);
}
}

let (circuit, debug, abi) =
create_circuit(context, program, options.show_ssa, options.show_brillig)?;

let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager);

Ok(CompiledProgram { circuit, debug, abi, file_map })
Ok(CompiledProgram { hash, circuit, debug, abi, file_map })
}
6 changes: 6 additions & 0 deletions compiler/noirc_driver/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ use super::debug::DebugFile;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CompiledProgram {
/// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`CompiledProgram`]
/// was compiled.
///
/// Used to short-circuit compilation in the case of the source code not changing since the last compilation.
pub hash: u64,

#[serde(serialize_with = "serialize_circuit", deserialize_with = "deserialize_circuit")]
pub circuit: Circuit,
pub abi: noirc_abi::Abi,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ noirc_frontend.workspace = true
noirc_errors.workspace = true
noirc_abi.workspace = true
acvm.workspace = true
fxhash = "0.2.1"
fxhash.workspace = true
iter-extended.workspace = true
thiserror.workspace = true
num-bigint = "0.4"
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl UnresolvedTypeExpression {
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
/// Represents whether the parameter is public or known only to the prover.
pub enum Visibility {
Public,
Expand All @@ -277,7 +277,7 @@ impl std::fmt::Display for Visibility {
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
/// Represents whether the return value should compromise of unique witness indices such that no
/// index occurs within the program's abi more than once.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/hir_def/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl HirExpression {
}

/// Corresponds to a variable in the source code
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct HirIdent {
pub location: Location,
pub id: DefinitionId,
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/hir_def/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub struct HirAssignStatement {
#[derive(Debug, Clone)]
pub struct HirConstrainStatement(pub ExprId, pub FileId, pub Option<String>);

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub enum HirPattern {
Identifier(HirIdent),
Mutable(Box<HirPattern>, Span),
Expand Down
34 changes: 17 additions & 17 deletions compiler/noirc_frontend/src/monomorphization/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Si
/// e.g. `let (a, b) = (1, 2)` have been split up: `let tmp = (1, 2); let a = tmp.0; let b = tmp.1;`.
/// This also affects function parameters: `fn foo((a, b): (i32, i32)` => `fn foo(a: i32, b: i32)`.
/// - All structs are replaced with tuples
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub enum Expression {
Ident(Ident),
Literal(Literal),
Expand Down Expand Up @@ -55,7 +55,7 @@ pub struct LocalId(pub u32);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FuncId(pub u32);

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Ident {
pub location: Option<Location>,
pub definition: Definition,
Expand All @@ -64,7 +64,7 @@ pub struct Ident {
pub typ: Type,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct For {
pub index_variable: LocalId,
pub index_name: String,
Expand All @@ -78,7 +78,7 @@ pub struct For {
pub end_range_location: Location,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub enum Literal {
Array(ArrayLiteral),
Integer(FieldElement, Type),
Expand All @@ -87,7 +87,7 @@ pub enum Literal {
FmtStr(String, u64, Box<Expression>),
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Unary {
pub operator: crate::UnaryOp,
pub rhs: Box<Expression>,
Expand All @@ -97,7 +97,7 @@ pub struct Unary {

pub type BinaryOp = BinaryOpKind;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Binary {
pub lhs: Box<Expression>,
pub operator: BinaryOp,
Expand All @@ -111,36 +111,36 @@ pub struct Lambda {
pub env: Ident,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct If {
pub condition: Box<Expression>,
pub consequence: Box<Expression>,
pub alternative: Option<Box<Expression>>,
pub typ: Type,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Cast {
pub lhs: Box<Expression>,
pub r#type: Type,
pub location: Location,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct ArrayLiteral {
pub contents: Vec<Expression>,
pub typ: Type,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Call {
pub func: Box<Expression>,
pub arguments: Vec<Expression>,
pub return_type: Type,
pub location: Location,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Index {
pub collection: Box<Expression>,
pub index: Box<Expression>,
Expand All @@ -160,15 +160,15 @@ pub struct Index {
/// let field1 = tmp.0; // the struct has been translated to a tuple as well
/// let field2 = tmp.1;
/// ```
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Let {
pub id: LocalId,
pub mutable: bool,
pub name: String,
pub expression: Box<Expression>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Assign {
pub lvalue: LValue,
pub expression: Box<Expression>,
Expand All @@ -182,7 +182,7 @@ pub struct BinaryStatement {
}

/// Represents an Ast form that can be assigned to
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub enum LValue {
Ident(Ident),
Index { array: Box<LValue>, index: Box<Expression>, element_type: Type, location: Location },
Expand All @@ -192,7 +192,7 @@ pub enum LValue {

pub type Parameters = Vec<(LocalId, /*mutable:*/ bool, /*name:*/ String, Type)>;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Function {
pub id: FuncId,
pub name: String,
Expand All @@ -209,7 +209,7 @@ pub struct Function {
/// - Concrete lengths for each array and string
/// - Several other variants removed (such as Type::Constant)
/// - All structs replaced with tuples
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum Type {
Field,
Array(/*len:*/ u64, Box<Type>), // Array(4, Field) = [Field; 4]
Expand All @@ -233,7 +233,7 @@ impl Type {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct Program {
pub functions: Vec<Function>,
pub main_function_signature: FunctionSignature,
Expand Down
2 changes: 1 addition & 1 deletion compiler/wasm/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ pub fn compile(args: JsValue) -> JsValue {

<JsValue as JsValueSerdeExt>::from_serde(&optimized_contract).unwrap()
} else {
let compiled_program = compile_main(&mut context, crate_id, &options.compile_options)
let compiled_program = compile_main(&mut context, crate_id, &options.compile_options, None)
.expect("Compilation failed")
.0;

Expand Down
6 changes: 6 additions & 0 deletions tooling/nargo/src/artifacts/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ use serde::{Deserialize, Serialize};
/// - Proving and verification keys have been pregenerated based on this ACIR.
#[derive(Serialize, Deserialize, Debug)]
pub struct PreprocessedProgram {
/// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`PreprocessedProgram`]
/// was compiled.
///
/// Used to short-circuit compilation in the case of the source code not changing since the last compilation.
pub hash: u64,

pub backend: String,
pub abi: Abi,

Expand Down
2 changes: 1 addition & 1 deletion tooling/nargo/src/ops/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn run_test<B: BlackBoxFunctionSolver>(
show_output: bool,
config: &CompileOptions,
) -> TestStatus {
let program = compile_no_check(context, config, test_function.get_id());
let program = compile_no_check(context, config, test_function.get_id(), None);
match program {
Ok(program) => {
// Run the backend to ensure the PWG evaluates functions like std::hash::pedersen,
Expand Down
2 changes: 1 addition & 1 deletion tooling/nargo/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Workspace {
impl Workspace {
pub fn package_build_path(&self, package: &Package) -> PathBuf {
let name: String = package.name.clone().into();
self.target_directory_path().join(name)
self.target_directory_path().join(name).with_extension("json")
}

pub fn contracts_directory_path(&self, package: &Package) -> PathBuf {
Expand Down
Loading

0 comments on commit 87fea4b

Please sign in to comment.