diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 4529d2224a3..131a78095e7 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -203,8 +203,8 @@ impl Driver { ) -> Result { let functions = try_btree_map(&contract.functions, |function| { let function_name = self.function_name(*function).to_owned(); - - self.compile_no_check(options, *function).map(|program| (function_name, program)) + let program = self.compile_no_check(options, *function)?; + Ok((function_name, program)) })?; Ok(CompiledContract { name: contract.name, functions }) @@ -225,10 +225,7 @@ impl Driver { }; // All Binaries should have a main function - match local_crate.main_function() { - Some(func_id) => Ok(func_id), - None => Err(ReportedError), - } + local_crate.main_function().ok_or(ReportedError) } /// Compile the current crate. Assumes self.check_crate is called beforehand! diff --git a/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs b/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs index 1133b4c052f..89dbc6b1e7f 100644 --- a/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -258,11 +258,10 @@ fn resolve_globals( globals: Vec, crate_id: CrateId, ) -> Vec<(FileId, StmtId)> { - let mut global_ids = Vec::new(); - - for global in globals { - let path_resolver = - StandardPathResolver::new(ModuleId { local_id: global.module_id, krate: crate_id }); + vecmap(globals, |global| { + let module_id = ModuleId { local_id: global.module_id, krate: crate_id }; + let path_resolver = StandardPathResolver::new(module_id); + let storage_slot = context.next_storage_slot(module_id); let mut resolver = Resolver::new( &mut context.def_interner, @@ -277,11 +276,10 @@ fn resolve_globals( context.def_interner.update_global(global.stmt_id, hir_stmt); - context.def_interner.push_global(global.stmt_id, name.clone(), global.module_id); + context.def_interner.push_global(global.stmt_id, name, global.module_id, storage_slot); - global_ids.push((global.file_id, global.stmt_id)); - } - global_ids + (global.file_id, global.stmt_id) + }) } fn type_check_globals( diff --git a/crates/noirc_frontend/src/hir/mod.rs b/crates/noirc_frontend/src/hir/mod.rs index 984231545be..d52278421a2 100644 --- a/crates/noirc_frontend/src/hir/mod.rs +++ b/crates/noirc_frontend/src/hir/mod.rs @@ -20,8 +20,14 @@ pub struct Context { pub crate_graph: CrateGraph, pub(crate) def_maps: HashMap, pub file_manager: FileManager, + + /// Maps a given (contract) module id to the next available storage slot + /// for that contract. + pub storage_slots: HashMap, } +pub type StorageSlot = u32; + impl Context { pub fn new(file_manager: FileManager, crate_graph: CrateGraph, language: Language) -> Context { let mut ctx = Context { @@ -29,10 +35,12 @@ impl Context { def_maps: HashMap::new(), crate_graph, file_manager, + storage_slots: HashMap::new(), }; ctx.def_interner.set_language(&language); ctx } + /// Returns the CrateDefMap for a given CrateId. /// It is perfectly valid for the compiler to look /// up a CrateDefMap and it is not available. @@ -46,4 +54,20 @@ impl Context { pub fn crates(&self) -> impl Iterator + '_ { self.crate_graph.iter_keys() } + + fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { + &self.def_maps[&module_id.krate].modules()[module_id.local_id.0] + } + + /// Returns the next available storage slot in the given module. + /// Returns None if the given module is not a contract module. + fn next_storage_slot(&mut self, module_id: def_map::ModuleId) -> Option { + let module = self.module(module_id); + + module.is_contract.then(|| { + let next_slot = self.storage_slots.entry(module_id).or_insert(0); + *next_slot += 1; + *next_slot + }) + } } diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index a6da1b3df1b..709751e8176 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -725,6 +725,7 @@ impl<'a> Resolver<'a> { pub fn resolve_global_let(&mut self, let_stmt: crate::LetStatement) -> HirStatement { let expression = self.resolve_expression(let_stmt.expression); let definition = DefinitionKind::Global(expression); + HirStatement::Let(HirLetStatement { pattern: self.resolve_pattern(let_stmt.pattern, definition), r#type: self.resolve_type(let_stmt.r#type), diff --git a/crates/noirc_frontend/src/node_interner.rs b/crates/noirc_frontend/src/node_interner.rs index 5516f12d3e4..2489c4aba3c 100644 --- a/crates/noirc_frontend/src/node_interner.rs +++ b/crates/noirc_frontend/src/node_interner.rs @@ -11,6 +11,7 @@ use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::UnresolvedStruct; use crate::hir::def_map::{LocalModuleId, ModuleId}; use crate::hir::type_check::TypeCheckError; +use crate::hir::StorageSlot; use crate::hir_def::stmt::HirLetStatement; use crate::hir_def::types::{StructType, Type}; use crate::hir_def::{ @@ -202,6 +203,7 @@ impl DefinitionInfo { #[derive(Debug, Clone, Eq, PartialEq)] pub enum DefinitionKind { Function(FuncId), + Global(ExprId), /// Locals may be defined in let statements or parameters, @@ -217,7 +219,7 @@ impl DefinitionKind { /// True if this definition is for a global variable. /// Note that this returns false for top-level functions. pub fn is_global(&self) -> bool { - matches!(self, DefinitionKind::Global(_)) + matches!(self, DefinitionKind::Global(..)) } pub fn get_rhs(self) -> Option { @@ -234,6 +236,10 @@ impl DefinitionKind { pub struct GlobalInfo { pub ident: Ident, pub local_id: LocalModuleId, + + /// Global definitions have an associated storage slot if they are defined within + /// a contract. If they're defined elsewhere, this value is None. + pub storage_slot: Option, } impl Default for NodeInterner { @@ -331,8 +337,14 @@ impl NodeInterner { self.id_to_type.insert(definition_id.into(), typ); } - pub fn push_global(&mut self, stmt_id: StmtId, ident: Ident, local_id: LocalModuleId) { - self.globals.insert(stmt_id, GlobalInfo { ident, local_id }); + pub fn push_global( + &mut self, + stmt_id: StmtId, + ident: Ident, + local_id: LocalModuleId, + storage_slot: Option, + ) { + self.globals.insert(stmt_id, GlobalInfo { ident, local_id, storage_slot }); } /// Intern an empty global stmt. Used for collecting globals