From a9aad0d517869d45d496c5459f10dd50f7116f9e Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Mon, 23 Oct 2023 21:11:13 -0400 Subject: [PATCH 1/6] Checkpoint --- .../src/passes/unknown_index_sanitization.rs | 6 +-- .../src/llvm_elements/array_switch.rs | 37 ++++++++++++++++--- compiler/src/circuit_design/circuit.rs | 27 +++----------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index c4f3ac18e..c68fc0934 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -6,7 +6,7 @@ use compiler::compiler_interface::Circuit; use compiler::intermediate_representation::{Instruction, InstructionPointer, new_id}; use compiler::intermediate_representation::ir_interface::*; use compiler::num_bigint::BigInt; -use code_producers::llvm_elements::array_switch::{get_array_load_symbol, get_array_store_symbol}; +use code_producers::llvm_elements::array_switch::{get_and_schedule_array_load, get_and_schedule_array_store}; use program_structure::constants::UsefulConstants; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; @@ -255,7 +255,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn transform_load_bucket(&self, bucket: &LoadBucket) -> InstructionPointer { let bounded_fn_symbol = match self.load_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_array_load_symbol(index_range)), + Some(index_range) => Some(get_and_schedule_array_load(index_range)), None => bucket.bounded_fn.clone(), }; LoadBucket { @@ -272,7 +272,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn transform_store_bucket(&self, bucket: &StoreBucket) -> InstructionPointer { let bounded_fn_symbol = match self.store_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_array_store_symbol(index_range)), + Some(index_range) => Some(get_and_schedule_array_store(index_range)), None => bucket.bounded_fn.clone(), }; StoreBucket { diff --git a/code_producers/src/llvm_elements/array_switch.rs b/code_producers/src/llvm_elements/array_switch.rs index 7919b6734..209f9010f 100644 --- a/code_producers/src/llvm_elements/array_switch.rs +++ b/code_producers/src/llvm_elements/array_switch.rs @@ -4,6 +4,7 @@ use crate::llvm_elements::LLVMIRProducer; use super::types::bigint_type; mod array_switch { + use std::collections::HashSet; use std::convert::TryInto; use std::ops::Range; @@ -17,6 +18,9 @@ mod array_switch { use crate::llvm_elements::types::{bigint_type, bool_type, i32_type, void_type}; use crate::llvm_elements::values::zero; + static mut SCHEDULED_ARRAY_LOADS: HashSet> = HashSet::new(); + static mut SCHEDULED_ARRAY_STORES: HashSet> = HashSet::new(); + pub fn get_load_symbol(index_range: &Range) -> String { format!("__array_load__{}_to_{}", index_range.start, index_range.end) } @@ -25,6 +29,22 @@ mod array_switch { format!("__array_store__{}_to_{}", index_range.start, index_range.end) } + pub fn schedule_create_load(index_range: &Range) { + SCHEDULED_ARRAY_LOADS.insert(index_range.clone()); + } + + pub fn schedule_create_store(index_range: &Range) { + SCHEDULED_ARRAY_STORES.insert(index_range.clone()); + } + + pub fn get_scheduled_loads() -> &'static HashSet> { + &SCHEDULED_ARRAY_LOADS + } + + pub fn get_scheduled_stores() -> &'static HashSet> { + &SCHEDULED_ARRAY_STORES + } + pub fn create_array_load_fn<'a>(producer: &dyn LLVMIRProducer<'a>, index_range: &Range) { // args: array, index // return: bigint loaded from array @@ -129,15 +149,22 @@ pub fn array_ptr_ty<'a>(producer: &dyn LLVMIRProducer<'a>) -> PointerType<'a> { bigint_ty.array_type(0).ptr_type(Default::default()) } -pub fn load_array_switch<'a>(producer: &dyn LLVMIRProducer<'a>, index_range: &Range) { - array_switch::create_array_load_fn(producer, index_range); - array_switch::create_array_store_fn(producer, index_range); +pub fn load_array_switches<'a>(producer: &dyn LLVMIRProducer<'a>) { + for index_range in array_switch::get_scheduled_loads() { + array_switch::create_array_load_fn(producer, index_range); + } + + for index_range in array_switch::get_scheduled_stores() { + array_switch::create_array_store_fn(producer, index_range); + } } -pub fn get_array_load_symbol(index_range: &Range) -> String { +pub fn get_and_schedule_array_load(index_range: &Range) -> String { + array_switch::schedule_create_load(index_range); array_switch::get_load_symbol(index_range) } -pub fn get_array_store_symbol(index_range: &Range) -> String { +pub fn get_and_schedule_array_store(index_range: &Range) -> String { + array_switch::schedule_create_store(index_range); array_switch::get_store_symbol(index_range) } diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index 658ca9e25..c03b38464 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -56,22 +56,7 @@ impl WriteLLVMIR for Circuit { load_stdlib(producer); // Generate all the switch functions - let mut ranges = HashSet::new(); - let mappings = [ - &self.llvm_data.signal_index_mapping, - &self.llvm_data.variable_index_mapping, - &self.llvm_data.component_index_mapping, - ]; - for mapping in mappings { - for range_mapping in mapping.values() { - for range in range_mapping.values() { - ranges.insert(range); - } - } - } - for range in ranges { - load_array_switch(producer, range); - } + load_array_switches(producer); // Declare all the functions let mut funcs = HashMap::new(); @@ -229,7 +214,7 @@ impl WriteWasm for Circuit { code.append(&mut code_aux); code_aux = get_input_size_generator(&producer); - code.append(&mut code_aux); + code.append(&mut code_aux); code_aux = get_witness_size_generator(&producer); code.append(&mut code_aux); @@ -369,7 +354,7 @@ impl WriteWasm for Circuit { code = merge_code(code_aux); writer.write_all(code.as_bytes()).map_err(|_| {})?; writer.flush().map_err(|_| {})?; - + code_aux = get_witness_size_generator(&producer); code = merge_code(code_aux); writer.write_all(code.as_bytes()).map_err(|_| {})?; @@ -460,7 +445,7 @@ impl WriteC for Circuit { std::mem::drop(function_headers); let (func_list_no_parallel, func_list_parallel) = generate_function_list( - producer, + producer, producer.get_template_instance_list() ); @@ -476,7 +461,7 @@ impl WriteC for Circuit { "uint get_main_input_signal_start() {{return {};}}\n", producer.get_number_of_main_outputs() )); - + code.push(format!( "uint get_main_input_signal_no() {{return {};}}\n", producer.get_number_of_main_inputs() @@ -503,7 +488,7 @@ impl WriteC for Circuit { producer.get_io_map().len() )); //code.append(&mut generate_message_list_def(producer, producer.get_message_list())); - + // Functions to release the memory let mut release_component_code = generate_function_release_memory_component(); code.append(&mut release_component_code); From cdc3a1d7ff2e2799bc256944eccacdd6cc42756b Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Mon, 23 Oct 2023 21:16:52 -0400 Subject: [PATCH 2/6] Update array function tracking --- .../src/passes/conditional_flattening.rs | 4 -- .../deterministic_subcomponent_invocation.rs | 4 -- circuit_passes/src/passes/loop_unroll/mod.rs | 4 -- .../src/passes/mapped_to_indexed.rs | 4 -- circuit_passes/src/passes/mod.rs | 21 ++++++++-- circuit_passes/src/passes/simplification.rs | 2 +- .../src/passes/unknown_index_sanitization.rs | 34 +++++++++++----- .../src/llvm_elements/array_switch.rs | 40 +++++-------------- code_producers/src/llvm_elements/mod.rs | 8 +++- compiler/src/circuit_design/circuit.rs | 10 +++-- 10 files changed, 64 insertions(+), 67 deletions(-) diff --git a/circuit_passes/src/passes/conditional_flattening.rs b/circuit_passes/src/passes/conditional_flattening.rs index 56b9dce83..e60ccd0bb 100644 --- a/circuit_passes/src/passes/conditional_flattening.rs +++ b/circuit_passes/src/passes/conditional_flattening.rs @@ -121,10 +121,6 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_branch_bucket(&self, bucket: &BranchBucket) -> InstructionPointer { if let Some(side) = self.replacements.borrow().get(&bucket) { let code = if *side { &bucket.if_branch } else { &bucket.else_branch }; diff --git a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs index 94f3ab03c..91d05d241 100644 --- a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs +++ b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs @@ -139,10 +139,6 @@ impl CircuitTransformationPass for DeterministicSubCmpInvokePass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_address_type(&self, address: &AddressType) -> AddressType { let replacements = self.replacements.borrow(); match address { diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index ded6e9695..7fb085774 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -206,10 +206,6 @@ impl CircuitTransformationPass for LoopUnrollPass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_loop_bucket(&self, bucket: &LoopBucket) -> InstructionPointer { if let Some(unrolled_loop) = self.replacements.borrow().get(&bucket.id) { return self.transform_instruction(unrolled_loop); diff --git a/circuit_passes/src/passes/mapped_to_indexed.rs b/circuit_passes/src/passes/mapped_to_indexed.rs index 513fc9a1a..0d7704fa5 100644 --- a/circuit_passes/src/passes/mapped_to_indexed.rs +++ b/circuit_passes/src/passes/mapped_to_indexed.rs @@ -171,10 +171,6 @@ impl CircuitTransformationPass for MappedToIndexedPass<'_> { "MappedToIndexedPass" } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - /* iangneal: Let the interpreter run to see if we can find any replacements. If so, yield the replacement. Else, just give the default transformation diff --git a/circuit_passes/src/passes/mod.rs b/circuit_passes/src/passes/mod.rs index b7eae09bb..966261d22 100644 --- a/circuit_passes/src/passes/mod.rs +++ b/circuit_passes/src/passes/mod.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; -use std::collections::{HashMap, BTreeMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::ops::Range; use compiler::circuit_design::function::{FunctionCode, FunctionCodeInfo}; use compiler::circuit_design::template::{TemplateCode, TemplateCodeInfo}; use compiler::compiler_interface::Circuit; @@ -37,11 +38,13 @@ pub trait CircuitTransformationPass { fn transform_circuit(&self, circuit: &Circuit) -> Circuit { self.pre_hook_circuit(&circuit); let templates = circuit.templates.iter().map(|t| self.transform_template(t)).collect(); - let field_tracking = self.get_updated_field_constants(); + let field_tracking = self.get_updated_field_constants(&circuit.llvm_data.field_tracking); + let bounded_loads = self.get_updated_bounded_array_loads(&circuit.llvm_data.bounded_array_loads); + let bounded_stores = self.get_updated_bounded_array_stores(&circuit.llvm_data.bounded_array_stores); let mut new_circuit = Circuit { wasm_producer: circuit.wasm_producer.clone(), c_producer: circuit.c_producer.clone(), - llvm_data: circuit.llvm_data.clone_with_new_field_tracking(field_tracking), + llvm_data: circuit.llvm_data.clone_with_updates(field_tracking, bounded_loads, bounded_stores), templates, functions: circuit.functions.iter().map(|f| self.transform_function(f)).collect(), }; @@ -49,7 +52,17 @@ pub trait CircuitTransformationPass { new_circuit } - fn get_updated_field_constants(&self) -> Vec; + fn get_updated_field_constants(&self, old_field_constants: &Vec) -> Vec { + old_field_constants.clone() + } + + fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { + old_array_loads.clone() + } + + fn get_updated_bounded_array_stores(&self, old_array_stores: &HashSet>) -> HashSet> { + old_array_stores.clone() + } fn transform_template(&self, template: &TemplateCode) -> TemplateCode { self.pre_hook_template(template); diff --git a/circuit_passes/src/passes/simplification.rs b/circuit_passes/src/passes/simplification.rs index 81275e883..e7b7c5f8d 100644 --- a/circuit_passes/src/passes/simplification.rs +++ b/circuit_passes/src/passes/simplification.rs @@ -123,7 +123,7 @@ impl CircuitTransformationPass for SimplificationPass<'_> { "SimplificationPass" } - fn get_updated_field_constants(&self) -> Vec { + fn get_updated_field_constants(&self, _old_field_constants: &Vec) -> Vec { self.memory.get_field_constants_clone() } diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index c68fc0934..fe4986b7d 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -1,12 +1,12 @@ use std::cell::RefCell; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet}; use std::ops::Range; use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; use compiler::intermediate_representation::{Instruction, InstructionPointer, new_id}; use compiler::intermediate_representation::ir_interface::*; use compiler::num_bigint::BigInt; -use code_producers::llvm_elements::array_switch::{get_and_schedule_array_load, get_and_schedule_array_store}; +use code_producers::llvm_elements::array_switch::{get_array_load_name, get_array_store_name}; use program_structure::constants::UsefulConstants; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; @@ -87,6 +87,8 @@ pub struct UnknownIndexSanitizationPass<'d> { memory: PassMemory, load_replacements: RefCell>>, store_replacements: RefCell>>, + scheduled_bounded_loads: RefCell>>, + scheduled_bounded_stores: RefCell>>, } /** @@ -99,6 +101,8 @@ impl<'d> UnknownIndexSanitizationPass<'d> { memory: PassMemory::new(prime, "".to_string(), Default::default()), load_replacements: Default::default(), store_replacements: Default::default(), + scheduled_bounded_loads: Default::default(), + scheduled_bounded_stores: Default::default(), } } @@ -176,7 +180,8 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { let location = &bucket.src; if self.is_location_unknown(address, location, env) { let index_range = self.find_bounds(address, location, env); - self.load_replacements.borrow_mut().insert(bucket.clone(), index_range); + self.load_replacements.borrow_mut().insert(bucket.clone(), index_range.clone()); + self.scheduled_bounded_loads.borrow_mut().insert(index_range); } true } @@ -186,7 +191,8 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { let location = &bucket.dest; if self.is_location_unknown(address, location, env) { let index_range = self.find_bounds(address, location, env); - self.store_replacements.borrow_mut().insert(bucket.clone(), index_range); + self.store_replacements.borrow_mut().insert(bucket.clone(), index_range.clone()); + self.scheduled_bounded_stores.borrow_mut().insert(index_range); } true } @@ -248,14 +254,26 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { } } +fn do_array_union(a: &HashSet>, b: &HashSet>) -> HashSet> { + a.union(b).map(|e| e.clone()).collect() +} + impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn name(&self) -> &str { "UnknownIndexSanitizationPass" } + fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { + do_array_union(old_array_loads, &self.scheduled_bounded_loads.borrow()) + } + + fn get_updated_bounded_array_stores(&self, old_array_stores: &HashSet>) -> HashSet> { + do_array_union(old_array_stores, &self.scheduled_bounded_stores.borrow()) + } + fn transform_load_bucket(&self, bucket: &LoadBucket) -> InstructionPointer { let bounded_fn_symbol = match self.load_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_and_schedule_array_load(index_range)), + Some(index_range) => Some(get_array_load_name(index_range)), None => bucket.bounded_fn.clone(), }; LoadBucket { @@ -272,7 +290,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn transform_store_bucket(&self, bucket: &StoreBucket) -> InstructionPointer { let bounded_fn_symbol = match self.store_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_and_schedule_array_store(index_range)), + Some(index_range) => Some(get_array_store_name(index_range)), None => bucket.bounded_fn.clone(), }; StoreBucket { @@ -290,10 +308,6 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { .allocate() } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } diff --git a/code_producers/src/llvm_elements/array_switch.rs b/code_producers/src/llvm_elements/array_switch.rs index 209f9010f..70dc5fa63 100644 --- a/code_producers/src/llvm_elements/array_switch.rs +++ b/code_producers/src/llvm_elements/array_switch.rs @@ -1,10 +1,9 @@ -use std::ops::Range; +use std::{ops::Range, collections::HashSet}; use inkwell::types::PointerType; use crate::llvm_elements::LLVMIRProducer; use super::types::bigint_type; mod array_switch { - use std::collections::HashSet; use std::convert::TryInto; use std::ops::Range; @@ -18,9 +17,6 @@ mod array_switch { use crate::llvm_elements::types::{bigint_type, bool_type, i32_type, void_type}; use crate::llvm_elements::values::zero; - static mut SCHEDULED_ARRAY_LOADS: HashSet> = HashSet::new(); - static mut SCHEDULED_ARRAY_STORES: HashSet> = HashSet::new(); - pub fn get_load_symbol(index_range: &Range) -> String { format!("__array_load__{}_to_{}", index_range.start, index_range.end) } @@ -29,22 +25,6 @@ mod array_switch { format!("__array_store__{}_to_{}", index_range.start, index_range.end) } - pub fn schedule_create_load(index_range: &Range) { - SCHEDULED_ARRAY_LOADS.insert(index_range.clone()); - } - - pub fn schedule_create_store(index_range: &Range) { - SCHEDULED_ARRAY_STORES.insert(index_range.clone()); - } - - pub fn get_scheduled_loads() -> &'static HashSet> { - &SCHEDULED_ARRAY_LOADS - } - - pub fn get_scheduled_stores() -> &'static HashSet> { - &SCHEDULED_ARRAY_STORES - } - pub fn create_array_load_fn<'a>(producer: &dyn LLVMIRProducer<'a>, index_range: &Range) { // args: array, index // return: bigint loaded from array @@ -149,22 +129,22 @@ pub fn array_ptr_ty<'a>(producer: &dyn LLVMIRProducer<'a>) -> PointerType<'a> { bigint_ty.array_type(0).ptr_type(Default::default()) } -pub fn load_array_switches<'a>(producer: &dyn LLVMIRProducer<'a>) { - for index_range in array_switch::get_scheduled_loads() { - array_switch::create_array_load_fn(producer, index_range); +pub fn load_array_load_fns<'a>(producer: &dyn LLVMIRProducer<'a>, scheduled_array_loads: &HashSet>) { + for range in scheduled_array_loads { + array_switch::create_array_load_fn(producer, range); } +} - for index_range in array_switch::get_scheduled_stores() { - array_switch::create_array_store_fn(producer, index_range); +pub fn load_array_stores_fns<'a>(producer: &dyn LLVMIRProducer<'a>, scheduled_array_stores: &HashSet>) { + for range in scheduled_array_stores { + array_switch::create_array_store_fn(producer, range); } } -pub fn get_and_schedule_array_load(index_range: &Range) -> String { - array_switch::schedule_create_load(index_range); +pub fn get_array_load_name<'a>(index_range: &Range) -> String { array_switch::get_load_symbol(index_range) } -pub fn get_and_schedule_array_store(index_range: &Range) -> String { - array_switch::schedule_create_store(index_range); +pub fn get_array_store_name<'a>(index_range: &Range) -> String { array_switch::get_store_symbol(index_range) } diff --git a/code_producers/src/llvm_elements/mod.rs b/code_producers/src/llvm_elements/mod.rs index f57e13f26..73a70c746 100644 --- a/code_producers/src/llvm_elements/mod.rs +++ b/code_producers/src/llvm_elements/mod.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::ops::Range; use std::rc::Rc; @@ -100,16 +100,20 @@ pub struct LLVMCircuitData { pub signal_index_mapping: HashMap, pub variable_index_mapping: HashMap, pub component_index_mapping: HashMap, + pub bounded_array_loads: HashSet>, + pub bounded_array_stores: HashSet>, } impl LLVMCircuitData { - pub fn clone_with_new_field_tracking(&self, field_tracking: Vec) -> Self { + pub fn clone_with_updates(&self, field_tracking: Vec, array_loads: HashSet>, array_stores: HashSet>) -> Self { LLVMCircuitData { field_tracking, io_map: self.io_map.clone(), signal_index_mapping: self.signal_index_mapping.clone(), variable_index_mapping: self.variable_index_mapping.clone(), component_index_mapping: self.component_index_mapping.clone(), + bounded_array_loads: array_loads, + bounded_array_stores: array_stores, } } } diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index c03b38464..1bfc2ed0c 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::io::Write; use super::function::{FunctionCode, FunctionCodeInfo}; use super::template::{TemplateCode, TemplateCodeInfo}; @@ -7,8 +7,9 @@ use crate::hir::very_concrete_program::VCP; use crate::intermediate_representation::ir_interface::ObtainMeta; use crate::translating_traits::*; use code_producers::c_elements::*; +use code_producers::llvm_elements::array_switch::{load_array_stores_fns, load_array_load_fns}; +use code_producers::wasm_elements::*; use code_producers::llvm_elements::*; -use code_producers::llvm_elements::array_switch::load_array_switch; use code_producers::llvm_elements::fr::load_fr; use code_producers::llvm_elements::functions::{ create_function, FunctionLLVMIRProducer, ExtractedFunctionLLVMIRProducer, @@ -55,8 +56,9 @@ impl WriteLLVMIR for Circuit { load_fr(producer); load_stdlib(producer); - // Generate all the switch functions - load_array_switches(producer); + // Code for bounded array switch functions + load_array_load_fns(producer, &self.llvm_data.bounded_array_loads); + load_array_stores_fns(producer, &self.llvm_data.bounded_array_stores); // Declare all the functions let mut funcs = HashMap::new(); From 798ce360b76e5e70a07b57ec4efe8b5783da52b2 Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Mon, 23 Oct 2023 20:46:14 -0400 Subject: [PATCH 3/6] Update test --- .../tests/arrays/unknown_index_load_store.circom | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/circom/tests/arrays/unknown_index_load_store.circom b/circom/tests/arrays/unknown_index_load_store.circom index de890b36f..583868139 100644 --- a/circom/tests/arrays/unknown_index_load_store.circom +++ b/circom/tests/arrays/unknown_index_load_store.circom @@ -4,13 +4,20 @@ pragma circom 2.0.0; template UnknownIndexLoadStore() { signal input in; - signal output out[10]; + signal output out[8]; - var arr1[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var arr1[9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; var arr2[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - var arr3[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var arr3[11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; out[in] <-- arr2[in]; } -component main = UnknownIndexLoadStore(); \ No newline at end of file +component main = UnknownIndexLoadStore(); + +// CHECK: define void @__array_store__0_to_8([0 x i256]* %0, i32 %1, i256 %2) +// CHECK: define i256 @__array_load__9_to_19([0 x i256]* %0, i32 %1) +// CHECK-NOT: @__array_load__0_to_8 +// CHECK-NOT: @__array_store__9_to_19 +// CHECK-NOT: @__array_load__20_to_31 +// CHECK-NOT: @__array_store__20_to_31 \ No newline at end of file From 03e51eff75b92995b3d81135fdcee08bdeb02701 Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Mon, 23 Oct 2023 21:17:27 -0400 Subject: [PATCH 4/6] Clean up compiler output --- compiler/src/circuit_design/circuit.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index 1bfc2ed0c..be32bf435 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -145,6 +145,9 @@ impl WriteLLVMIR for Circuit { // Code for the templates for t in &self.templates { + if cfg!(debug_assertions) { + println!("Generating code for {}", t.header); + } t.produce_llvm_ir(producer); } From b223aa27124fe371e0fc068e8bc9fb4dfc18c663 Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Mon, 23 Oct 2023 21:20:39 -0400 Subject: [PATCH 5/6] Fix merge compile errors --- circuit_passes/src/passes/const_arg_deduplication.rs | 2 +- compiler/src/circuit_design/circuit.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/circuit_passes/src/passes/const_arg_deduplication.rs b/circuit_passes/src/passes/const_arg_deduplication.rs index d9af385b9..8f8ff144b 100644 --- a/circuit_passes/src/passes/const_arg_deduplication.rs +++ b/circuit_passes/src/passes/const_arg_deduplication.rs @@ -124,7 +124,7 @@ impl CircuitTransformationPass for ConstArgDeduplicationPass<'_> { "ConstArgDeduplicationPass" } - fn get_updated_field_constants(&self) -> Vec { + fn get_updated_field_constants(&self, _old_field_elements: &Vec) -> Vec { self.memory.get_field_constants_clone() } diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index be32bf435..ea6afd011 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -8,7 +8,6 @@ use crate::intermediate_representation::ir_interface::ObtainMeta; use crate::translating_traits::*; use code_producers::c_elements::*; use code_producers::llvm_elements::array_switch::{load_array_stores_fns, load_array_load_fns}; -use code_producers::wasm_elements::*; use code_producers::llvm_elements::*; use code_producers::llvm_elements::fr::load_fr; use code_producers::llvm_elements::functions::{ From ef5e2568b74f7f94223f0e17520ff71bfedde4c8 Mon Sep 17 00:00:00 2001 From: Ian Glen Neal Date: Tue, 24 Oct 2023 12:47:03 -0400 Subject: [PATCH 6/6] Address review comments --- circuit_passes/src/passes/conditional_flattening.rs | 4 ++++ circuit_passes/src/passes/const_arg_deduplication.rs | 2 +- .../src/passes/deterministic_subcomponent_invocation.rs | 4 ++++ circuit_passes/src/passes/loop_unroll/mod.rs | 4 ++++ circuit_passes/src/passes/mapped_to_indexed.rs | 4 ++++ circuit_passes/src/passes/mod.rs | 6 ++---- circuit_passes/src/passes/simplification.rs | 2 +- circuit_passes/src/passes/unknown_index_sanitization.rs | 4 ++++ code_producers/src/llvm_elements/array_switch.rs | 4 ++-- compiler/src/circuit_design/circuit.rs | 3 --- compiler/src/circuit_design/template.rs | 4 +++- 11 files changed, 29 insertions(+), 12 deletions(-) diff --git a/circuit_passes/src/passes/conditional_flattening.rs b/circuit_passes/src/passes/conditional_flattening.rs index e60ccd0bb..a2b469cae 100644 --- a/circuit_passes/src/passes/conditional_flattening.rs +++ b/circuit_passes/src/passes/conditional_flattening.rs @@ -112,6 +112,10 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { "ConditionalFlattening" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } diff --git a/circuit_passes/src/passes/const_arg_deduplication.rs b/circuit_passes/src/passes/const_arg_deduplication.rs index 8f8ff144b..d9af385b9 100644 --- a/circuit_passes/src/passes/const_arg_deduplication.rs +++ b/circuit_passes/src/passes/const_arg_deduplication.rs @@ -124,7 +124,7 @@ impl CircuitTransformationPass for ConstArgDeduplicationPass<'_> { "ConstArgDeduplicationPass" } - fn get_updated_field_constants(&self, _old_field_elements: &Vec) -> Vec { + fn get_updated_field_constants(&self) -> Vec { self.memory.get_field_constants_clone() } diff --git a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs index 91d05d241..1e9b9e5c6 100644 --- a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs +++ b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs @@ -130,6 +130,10 @@ impl CircuitTransformationPass for DeterministicSubCmpInvokePass<'_> { "DeterministicSubCmpInvokePass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index 7fb085774..b7b8aaf50 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -190,6 +190,10 @@ impl CircuitTransformationPass for LoopUnrollPass<'_> { "LoopUnrollPass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } diff --git a/circuit_passes/src/passes/mapped_to_indexed.rs b/circuit_passes/src/passes/mapped_to_indexed.rs index 0d7704fa5..513fc9a1a 100644 --- a/circuit_passes/src/passes/mapped_to_indexed.rs +++ b/circuit_passes/src/passes/mapped_to_indexed.rs @@ -171,6 +171,10 @@ impl CircuitTransformationPass for MappedToIndexedPass<'_> { "MappedToIndexedPass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + /* iangneal: Let the interpreter run to see if we can find any replacements. If so, yield the replacement. Else, just give the default transformation diff --git a/circuit_passes/src/passes/mod.rs b/circuit_passes/src/passes/mod.rs index 966261d22..5e105b757 100644 --- a/circuit_passes/src/passes/mod.rs +++ b/circuit_passes/src/passes/mod.rs @@ -38,7 +38,7 @@ pub trait CircuitTransformationPass { fn transform_circuit(&self, circuit: &Circuit) -> Circuit { self.pre_hook_circuit(&circuit); let templates = circuit.templates.iter().map(|t| self.transform_template(t)).collect(); - let field_tracking = self.get_updated_field_constants(&circuit.llvm_data.field_tracking); + let field_tracking = self.get_updated_field_constants(); let bounded_loads = self.get_updated_bounded_array_loads(&circuit.llvm_data.bounded_array_loads); let bounded_stores = self.get_updated_bounded_array_stores(&circuit.llvm_data.bounded_array_stores); let mut new_circuit = Circuit { @@ -52,9 +52,7 @@ pub trait CircuitTransformationPass { new_circuit } - fn get_updated_field_constants(&self, old_field_constants: &Vec) -> Vec { - old_field_constants.clone() - } + fn get_updated_field_constants(&self) -> Vec; fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { old_array_loads.clone() diff --git a/circuit_passes/src/passes/simplification.rs b/circuit_passes/src/passes/simplification.rs index e7b7c5f8d..81275e883 100644 --- a/circuit_passes/src/passes/simplification.rs +++ b/circuit_passes/src/passes/simplification.rs @@ -123,7 +123,7 @@ impl CircuitTransformationPass for SimplificationPass<'_> { "SimplificationPass" } - fn get_updated_field_constants(&self, _old_field_constants: &Vec) -> Vec { + fn get_updated_field_constants(&self) -> Vec { self.memory.get_field_constants_clone() } diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index fe4986b7d..fa59e046b 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -263,6 +263,10 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { "UnknownIndexSanitizationPass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { do_array_union(old_array_loads, &self.scheduled_bounded_loads.borrow()) } diff --git a/code_producers/src/llvm_elements/array_switch.rs b/code_producers/src/llvm_elements/array_switch.rs index 70dc5fa63..946132476 100644 --- a/code_producers/src/llvm_elements/array_switch.rs +++ b/code_producers/src/llvm_elements/array_switch.rs @@ -141,10 +141,10 @@ pub fn load_array_stores_fns<'a>(producer: &dyn LLVMIRProducer<'a>, scheduled_ar } } -pub fn get_array_load_name<'a>(index_range: &Range) -> String { +pub fn get_array_load_name(index_range: &Range) -> String { array_switch::get_load_symbol(index_range) } -pub fn get_array_store_name<'a>(index_range: &Range) -> String { +pub fn get_array_store_name(index_range: &Range) -> String { array_switch::get_store_symbol(index_range) } diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index ea6afd011..ec89db5d6 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -144,9 +144,6 @@ impl WriteLLVMIR for Circuit { // Code for the templates for t in &self.templates { - if cfg!(debug_assertions) { - println!("Generating code for {}", t.header); - } t.produce_llvm_ir(producer); } diff --git a/compiler/src/circuit_design/template.rs b/compiler/src/circuit_design/template.rs index c0605aed2..8feb335d1 100644 --- a/compiler/src/circuit_design/template.rs +++ b/compiler/src/circuit_design/template.rs @@ -59,7 +59,9 @@ impl ToString for TemplateCodeInfo { impl WriteLLVMIR for TemplateCodeInfo { fn produce_llvm_ir<'ctx, 'prod>(&self, producer: &'prod dyn LLVMIRProducer<'ctx>) -> Option> { - println!("Generating code for {}", self.header); + if cfg!(debug_assertions) { + println!("Generating code for {}", self.header); + } let void = void_type(producer); let n_signals = self.number_of_inputs + self.number_of_outputs + self.number_of_intermediates; let template_struct = create_template_struct(producer, n_signals);