From 443f42c95b7eab053e2f9b9ca80e75c27eded906 Mon Sep 17 00:00:00 2001 From: Mohammad Fawaz Date: Wed, 1 Jun 2022 07:34:30 -0400 Subject: [PATCH] Eliminating the need for `new()` to use `StorageMap` (#1776) --- .../src/asm_generation/expression/mod.rs | 1 + sway-core/src/asm_generation/from_ir.rs | 58 ++++++++-- sway-core/src/constants.rs | 2 - .../dead_code_analysis.rs | 2 +- sway-core/src/convert_parse_tree.rs | 12 +- sway-core/src/optimize.rs | 34 ++++-- sway-core/src/parse_tree/expression/mod.rs | 4 +- .../ast_node/expression/typed_expression.rs | 9 +- .../typed_expression/function_application.rs | 8 ++ .../typed_expression/method_application.rs | 40 ++++++- .../expression/typed_expression_variant.rs | 7 +- .../semantic_analysis/node_dependencies.rs | 2 +- .../src/type_engine/unresolved_type_check.rs | 2 +- sway-core/tests/ir_to_asm/generate_uid.asm | 26 ----- sway-core/tests/ir_to_asm/generate_uid.ir | 40 ------- sway-core/tests/ir_to_asm/get_storage_key.asm | 28 +++++ sway-core/tests/ir_to_asm/get_storage_key.ir | 39 +++++++ sway-core/tests/sway_to_ir/generate_uid.ir | 42 ------- sway-core/tests/sway_to_ir/generate_uid.sw | 11 -- sway-core/tests/sway_to_ir/get_storage_key.ir | 33 ++++++ sway-core/tests/sway_to_ir/get_storage_key.sw | 28 +++++ sway-ir/src/block.rs | 2 +- sway-ir/src/instruction.rs | 84 ++++++++++---- sway-ir/src/metadata.rs | 14 +++ sway-ir/src/optimize/constants.rs | 1 + sway-ir/src/optimize/inline.rs | 14 ++- sway-ir/src/parser.rs | 107 +++++++++++++----- sway-ir/src/printer.rs | 15 ++- sway-ir/src/value.rs | 14 +++ sway-ir/src/verify.rs | 2 +- sway-ir/tests/inline/get_storage_key.ir | 30 +++++ sway-lib-std/src/storage.sw | 12 +- sway-lsp/src/core/token.rs | 2 +- sway-lsp/src/core/traverse_typed_tree.rs | 2 +- sway-parse/src/intrinsics.rs | 4 +- test/src/e2e_vm_tests/mod.rs | 16 +-- .../language/generate_uid/Forc.lock | 11 -- .../language/generate_uid/src/main.sw | 41 ------- .../get_storage_key_caller/Forc.lock | 18 +++ .../get_storage_key_caller}/Forc.toml | 3 +- .../json_abi_oracle.json | 1 + .../get_storage_key_caller/src/main.sw | 30 +++++ .../test_abis/get_storage_key_abi/Forc.lock | 3 + .../test_abis/get_storage_key_abi/Forc.toml | 6 + .../get_storage_key_abi/json_abi_oracle.json | 1 + .../test_abis/get_storage_key_abi/src/main.sw | 8 ++ .../get_storage_key_contract/Forc.lock | 7 ++ .../get_storage_key_contract/Forc.toml | 9 ++ .../json_abi_oracle.json | 50 ++++++++ .../get_storage_key_contract/src/main.sw | 36 ++++++ .../test_projects/storage_map/mod.rs | 36 ------ .../test_projects/storage_map/src/main.sw | 27 ----- 52 files changed, 680 insertions(+), 354 deletions(-) delete mode 100644 sway-core/tests/ir_to_asm/generate_uid.asm delete mode 100644 sway-core/tests/ir_to_asm/generate_uid.ir create mode 100644 sway-core/tests/ir_to_asm/get_storage_key.asm create mode 100644 sway-core/tests/ir_to_asm/get_storage_key.ir delete mode 100644 sway-core/tests/sway_to_ir/generate_uid.ir delete mode 100644 sway-core/tests/sway_to_ir/generate_uid.sw create mode 100644 sway-core/tests/sway_to_ir/get_storage_key.ir create mode 100644 sway-core/tests/sway_to_ir/get_storage_key.sw create mode 100644 sway-ir/tests/inline/get_storage_key.ir delete mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.lock delete mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.lock rename test/src/e2e_vm_tests/test_programs/should_pass/{language/generate_uid => require_contract_deployment/get_storage_key_caller}/Forc.toml (61%) create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/src/main.sw diff --git a/sway-core/src/asm_generation/expression/mod.rs b/sway-core/src/asm_generation/expression/mod.rs index e3e57e0287e..61b1e339453 100644 --- a/sway-core/src/asm_generation/expression/mod.rs +++ b/sway-core/src/asm_generation/expression/mod.rs @@ -53,6 +53,7 @@ pub(crate) fn convert_expression_to_asm( arguments, function_body, selector, + .. } => { if let Some(metadata) = selector { convert_contract_call_to_asm( diff --git a/sway-core/src/asm_generation/from_ir.rs b/sway-core/src/asm_generation/from_ir.rs index 866397a8bd2..320e5ea66fc 100644 --- a/sway-core/src/asm_generation/from_ir.rs +++ b/sway-core/src/asm_generation/from_ir.rs @@ -8,7 +8,6 @@ // - AsmNamespace is tied to data structures from other stages like Ident and Literal. use fuel_crypto::Hasher; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::{collections::HashMap, sync::Arc}; use crate::{ @@ -501,7 +500,14 @@ impl<'ir> AsmBuilder<'ir> { Instruction::ExtractValue { aggregate, indices, .. } => self.compile_extract_value(instr_val, aggregate, indices), - Instruction::GenerateUid => self.compile_generate_uid(instr_val), + Instruction::GetStorageKey => { + check!( + self.compile_get_storage_key(instr_val), + return err(warnings, errors), + warnings, + errors + ) + } Instruction::GetPointer { base_ptr, ptr_ty, @@ -1035,15 +1041,41 @@ impl<'ir> AsmBuilder<'ir> { self.reg_map.insert(*instr_val, instr_reg); } - fn compile_generate_uid(&mut self, instr_val: &Value) { - // Replace each call to __generate_uid with a new value - static COUNTER: AtomicUsize = AtomicUsize::new(0); - let storage_slot_to_hash = format!( - "{}{}", - crate::constants::GENERATE_UID_STORAGE_SEPARATOR, - COUNTER.load(Ordering::SeqCst) - ); - COUNTER.fetch_add(1, Ordering::SeqCst); + fn compile_get_storage_key(&mut self, instr_val: &Value) -> CompileResult<()> { + let warnings: Vec = Vec::new(); + let mut errors: Vec = Vec::new(); + + let state_idx = instr_val.get_storage_key(self.context); + + // Instead of calling `instr_span.get_span()` directly, do error checking first. This is a + // temporary workaround so that the IR test for `get_storage_key` pass because that test + // has invalid filepath. This can be changed when we refactor Span to not need a valid + // source string + let instr_span = match self.context.values[instr_val.0] + .span_md_idx + .map(|idx| idx.to_span(self.context)) + .transpose() + { + Ok(span) => span, + Err(_) => None, + }; + + let storage_slot_to_hash = match state_idx { + Some(state_idx) => { + format!( + "{}{}", + sway_utils::constants::STORAGE_DOMAIN_SEPARATOR, + state_idx + ) + } + None => { + errors.push(CompileError::Internal( + "State index for __get_storage_key is not available as a metadata", + instr_span.unwrap_or_else(Self::empty_span), + )); + return err(warnings, errors); + } + }; let hashed_storage_slot = Hasher::hash(storage_slot_to_hash); @@ -1053,12 +1085,14 @@ impl<'ir> AsmBuilder<'ir> { // Allocate a register for it, and a load instruction. let reg = self.reg_seqr.next(); + self.bytecode.push(Op { opcode: either::Either::Left(VirtualOp::LWDataId(reg.clone(), data_id)), comment: "literal instantiation".into(), - owning_span: instr_val.get_span(self.context), + owning_span: instr_span, }); self.reg_map.insert(*instr_val, reg); + ok((), warnings, errors) } fn compile_get_pointer( diff --git a/sway-core/src/constants.rs b/sway-core/src/constants.rs index d145f6215b5..f7d8bcd5ef0 100644 --- a/sway-core/src/constants.rs +++ b/sway-core/src/constants.rs @@ -24,8 +24,6 @@ pub const DEFAULT_ENTRY_POINT_FN_NAME: &str = "main"; /// The default prefix for the compiler generated names of tuples pub const TUPLE_NAME_PREFIX: &str = "__tuple_"; -pub const GENERATE_UID_STORAGE_SEPARATOR: &str = "__generate_uid_storage_separator_"; - /// The valid attribute strings related to storage and purity. pub const STORAGE_PURITY_ATTRIBUTE_NAME: &str = "storage"; pub const STORAGE_PURITY_READ_NAME: &str = "read"; diff --git a/sway-core/src/control_flow_analysis/dead_code_analysis.rs b/sway-core/src/control_flow_analysis/dead_code_analysis.rs index 2ae6faa2e45..45ed069c76c 100644 --- a/sway-core/src/control_flow_analysis/dead_code_analysis.rs +++ b/sway-core/src/control_flow_analysis/dead_code_analysis.rs @@ -1008,7 +1008,7 @@ fn connect_expression( )?; Ok(expr) } - GenerateUid { .. } => { + GetStorageKey { .. } => { let node = graph.add_node("Generate B256 Seed".into()); for leaf in leaves { graph.add_edge(*leaf, node, "".into()); diff --git a/sway-core/src/convert_parse_tree.rs b/sway-core/src/convert_parse_tree.rs index 3dd3d860b7b..191587821eb 100644 --- a/sway-core/src/convert_parse_tree.rs +++ b/sway-core/src/convert_parse_tree.rs @@ -178,8 +178,8 @@ pub enum ConvertParseTreeError { InvalidAttributeArgument { attribute: String, span: Span }, #[error("cannot find type \"{ty_name}\" in this scope")] ConstrainedNonExistentType { ty_name: Ident, span: Span }, - #[error("__generate_uid does not take arguments")] - GenerateUidTooManyArgs { span: Span }, + #[error("__get_storage_key does not take arguments")] + GetStorageKeyTooManyArgs { span: Span }, #[error("recursive types are not supported")] RecursiveType { span: Span }, } @@ -231,7 +231,7 @@ impl ConvertParseTreeError { ConvertParseTreeError::ContractCallerNamedTypeGenericArg { span } => span.clone(), ConvertParseTreeError::InvalidAttributeArgument { span, .. } => span.clone(), ConvertParseTreeError::ConstrainedNonExistentType { span, .. } => span.clone(), - ConvertParseTreeError::GenerateUidTooManyArgs { span, .. } => span.clone(), + ConvertParseTreeError::GetStorageKeyTooManyArgs { span, .. } => span.clone(), ConvertParseTreeError::RecursiveType { span } => span.clone(), } } @@ -1399,17 +1399,17 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { if let Some(metadata) = selector { @@ -619,6 +620,7 @@ impl FnCompiler { name.suffix.as_str(), arguments, Some(function_body), + self_state_idx, span_md_idx, ) } @@ -737,20 +739,23 @@ impl FnCompiler { self.compile_unsafe_downcast(context, exp, variant) } TypedExpressionVariant::EnumTag { exp } => self.compile_enum_tag(context, exp), - TypedExpressionVariant::GenerateUid { span } => { + TypedExpressionVariant::GetStorageKey { span } => { let span_md_idx = MetadataIndex::from_span(context, &span); - self.compile_generate_uid(context, span_md_idx) + self.compile_get_storage_key(context, span_md_idx) } } } // --------------------------------------------------------------------------------------------- - fn compile_generate_uid( + fn compile_get_storage_key( &mut self, context: &mut Context, span_md_idx: Option, ) -> Result { - Ok(self.current_block.ins(context).generate_uid(span_md_idx)) + Ok(self + .current_block + .ins(context) + .get_storage_key(span_md_idx, None)) } fn compile_return_statement( @@ -1042,6 +1047,7 @@ impl FnCompiler { _ast_name: &str, ast_args: Vec<(Ident, TypedExpression)>, callee_body: Option, + self_state_idx: Option, span_md_idx: Option, ) -> Result { // XXX OK, now, the old compiler inlines everything very lazily. Function calls include @@ -1104,10 +1110,18 @@ impl FnCompiler { .into_iter() .map(|(_, expr)| self.compile_expression(context, expr)) .collect::, CompileError>>()?; - Ok(self - .current_block - .ins(context) - .call(callee.unwrap(), &args, span_md_idx)) + let state_idx_md_idx = match self_state_idx { + Some(self_state_idx) => { + MetadataIndex::from_state_idx(context, self_state_idx.to_usize()) + } + None => None, + }; + Ok(self.current_block.ins(context).call( + callee.unwrap(), + &args, + span_md_idx, + state_idx_md_idx, + )) } } @@ -2566,13 +2580,13 @@ mod tests { let parsed_ctx = match sway_ir::parser::parse(&input) { Ok(p) => p, Err(e) => { - tracing::error!("{}: {}", path.display(), e); + println!("{}: {}", path.display(), e); panic!(); } }; let printed = sway_ir::printer::to_string(&parsed_ctx); if printed != input { - tracing::error!("{}", prettydiff::diff_lines(&input, &printed)); + println!("{}", prettydiff::diff_lines(&input, &printed)); panic!("{} failed.", path.display()); } } diff --git a/sway-core/src/parse_tree/expression/mod.rs b/sway-core/src/parse_tree/expression/mod.rs index a40bd6d2b08..c2fda31d9d0 100644 --- a/sway-core/src/parse_tree/expression/mod.rs +++ b/sway-core/src/parse_tree/expression/mod.rs @@ -146,7 +146,7 @@ pub enum Expression { type_span: Span, span: Span, }, - BuiltinGenerateUid { + BuiltinGetStorageKey { span: Span, }, } @@ -225,7 +225,7 @@ impl Expression { StorageAccess { span, .. } => span, SizeOfVal { span, .. } => span, BuiltinGetTypeProperty { span, .. } => span, - BuiltinGenerateUid { span, .. } => span, + BuiltinGetStorageKey { span, .. } => span, }) .clone() } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 59402053a47..cd43773aba8 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -107,6 +107,7 @@ impl TypedExpression { method, None, IsConstant::No, + None, span, ) } @@ -141,7 +142,7 @@ impl TypedExpression { | Literal(_) | StorageAccess { .. } | TypeProperty { .. } - | GenerateUid { .. } + | GetStorageKey { .. } | VariableExpression { .. } | FunctionParameter | TupleElemAccess { .. } => false, @@ -230,7 +231,7 @@ impl TypedExpression { | TypedExpressionVariant::FunctionApplication { .. } | TypedExpressionVariant::EnumTag { .. } | TypedExpressionVariant::UnsafeDowncast { .. } - | TypedExpressionVariant::GenerateUid { .. } => vec![], + | TypedExpressionVariant::GetStorageKey { .. } => vec![], } } @@ -460,9 +461,9 @@ impl TypedExpression { }, span, ), - Expression::BuiltinGenerateUid { span } => ok( + Expression::BuiltinGetStorageKey { span } => ok( TypedExpression { - expression: TypedExpressionVariant::GenerateUid { span: span.clone() }, + expression: TypedExpressionVariant::GetStorageKey { span: span.clone() }, return_type: insert_type(TypeInfo::B256), is_constant: IsConstant::No, span, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs index 9696b3a5e49..5e6bc3cda05 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs @@ -4,6 +4,7 @@ use crate::{ type_engine::TypeId, }; use std::collections::{hash_map::RandomState, HashMap, VecDeque}; +use sway_types::state::StateIndex; #[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_function_application( @@ -76,6 +77,7 @@ pub(crate) fn instantiate_function_application( function_decl, None, IsConstant::No, + None, span, ), return err(warnings, errors), @@ -85,6 +87,7 @@ pub(crate) fn instantiate_function_application( ok(exp, warnings, errors) } +#[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_function_application_simple( call_path: CallPath, contract_call_params: HashMap, @@ -92,6 +95,7 @@ pub(crate) fn instantiate_function_application_simple( function_decl: TypedFunctionDeclaration, selector: Option, is_constant: IsConstant, + self_state_idx: Option, span: Span, ) -> CompileResult { let args_and_names = function_decl @@ -107,10 +111,12 @@ pub(crate) fn instantiate_function_application_simple( function_decl, selector, is_constant, + self_state_idx, span, ) } +#[allow(clippy::too_many_arguments)] #[allow(clippy::comparison_chain)] fn instantiate_function_application_inner( call_path: CallPath, @@ -119,6 +125,7 @@ fn instantiate_function_application_inner( function_decl: TypedFunctionDeclaration, selector: Option, is_constant: IsConstant, + self_state_idx: Option, span: Span, ) -> CompileResult { let warnings = vec![]; @@ -131,6 +138,7 @@ fn instantiate_function_application_inner( contract_call_params, arguments, function_body: function_decl.body.clone(), + self_state_idx, selector, }, return_type: function_decl.return_type, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 843c58432a6..f0009f51a0a 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -3,6 +3,7 @@ use crate::constants; use crate::parse_tree::{MethodName, StructExpressionField}; use crate::semantic_analysis::namespace::Namespace; use crate::semantic_analysis::TCOpts; +use crate::Expression::StorageAccess; use std::collections::{HashMap, VecDeque}; #[allow(clippy::too_many_arguments)] @@ -20,10 +21,10 @@ pub(crate) fn type_check_method_application( let mut errors = vec![]; let mut args_buf = VecDeque::new(); let mut contract_call_params_map = HashMap::new(); - for arg in arguments { + for arg in &arguments { args_buf.push_back(check!( TypedExpression::type_check(TypeCheckArguments { - checkee: arg, + checkee: arg.clone(), namespace, return_type_annotation: insert_type(TypeInfo::Unknown), help_text: Default::default(), @@ -131,6 +132,39 @@ pub(crate) fn type_check_method_application( } } + // If this method was called with self being a `StorageAccess` (e.g. storage.map.insert(..)), + // then record the index of that storage variable and pass it on. + let mut self_state_idx = None; + if namespace.has_storage_declared() { + let storage_fields = check!( + namespace.get_storage_field_descriptors(), + return err(warnings, errors), + warnings, + errors + ); + + self_state_idx = match arguments.first() { + Some(StorageAccess { field_names, .. }) => { + let first_field = field_names[0].clone(); + let self_state_idx = match storage_fields + .iter() + .enumerate() + .find(|(_, TypedStorageField { name, .. })| name == &first_field) + { + Some((ix, _)) => StateIndex::new(ix), + None => { + errors.push(CompileError::StorageFieldDoesNotExist { + name: first_field.clone(), + }); + return err(warnings, errors); + } + }; + Some(self_state_idx) + } + _ => None, + } + }; + // type check all of the arguments against the parameters in the method declaration for (arg, param) in args_buf.iter().zip(method.parameters.iter()) { // if the return type cannot be cast into the annotation type then it is a type error @@ -196,6 +230,7 @@ pub(crate) fn type_check_method_application( method, selector, IsConstant::No, + self_state_idx, span, ), return err(warnings, errors), @@ -245,6 +280,7 @@ pub(crate) fn type_check_method_application( method, selector, IsConstant::No, + self_state_idx, span, ), return err(warnings, errors), diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs index ba3117a46b2..5d0b36e5dab 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs @@ -24,6 +24,7 @@ pub enum TypedExpressionVariant { function_body: TypedCodeBlock, /// If this is `Some(val)` then `val` is the metadata. If this is `None`, then /// there is no selector. + self_state_idx: Option, #[derivative(Eq(bound = ""))] selector: Option, }, @@ -102,7 +103,7 @@ pub enum TypedExpressionVariant { type_id: TypeId, span: Span, }, - GenerateUid { + GetStorageKey { span: Span, }, SizeOfValue { @@ -430,7 +431,7 @@ impl CopyTypes for TypedExpressionVariant { exp.copy_types(type_mapping); variant.copy_types(type_mapping); } - GenerateUid { .. } => (), + GetStorageKey { .. } => (), AbiName(_) => (), } } @@ -595,7 +596,7 @@ impl TypedExpressionVariant { TypedExpressionVariant::SizeOfValue { expr } => { format!("size_of_val({:?})", expr.pretty_print()) } - TypedExpressionVariant::GenerateUid { .. } => "generate_uid".to_string(), + TypedExpressionVariant::GetStorageKey { .. } => "get_storage_key".to_string(), TypedExpressionVariant::AbiName(n) => format!("ABI name {}", n), TypedExpressionVariant::EnumTag { exp } => { format!( diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 24ef30d2181..5d3d243f205 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -475,7 +475,7 @@ impl Dependencies { Expression::StorageAccess { .. } => self, Expression::SizeOfVal { exp, .. } => self.gather_from_expr(exp), Expression::BuiltinGetTypeProperty { .. } => self, - Expression::BuiltinGenerateUid { .. } => self, + Expression::BuiltinGetStorageKey { .. } => self, } } diff --git a/sway-core/src/type_engine/unresolved_type_check.rs b/sway-core/src/type_engine/unresolved_type_check.rs index 2dea17adef6..4a9f6eb6b0a 100644 --- a/sway-core/src/type_engine/unresolved_type_check.rs +++ b/sway-core/src/type_engine/unresolved_type_check.rs @@ -175,7 +175,7 @@ impl UnresolvedTypeCheck for TypedExpression { | Literal(_) | AbiName(_) | FunctionParameter - | GenerateUid { .. } => vec![], + | GetStorageKey { .. } => vec![], EnumTag { exp } => exp.check_for_unresolved_types(), UnsafeDowncast { exp, variant } => exp .check_for_unresolved_types() diff --git a/sway-core/tests/ir_to_asm/generate_uid.asm b/sway-core/tests/ir_to_asm/generate_uid.asm deleted file mode 100644 index a123cbf0d69..00000000000 --- a/sway-core/tests/ir_to_asm/generate_uid.asm +++ /dev/null @@ -1,26 +0,0 @@ -.program: -ji i4 -noop -DATA_SECTION_OFFSET[0..32] -DATA_SECTION_OFFSET[32..64] -lw $ds $is 1 -add $$ds $$ds $is -move $r2 $sp ; save locals base register -cfei i96 ; allocate 96 bytes for all locals -lw $r1 data_0 ; literal instantiation -addi $r0 $r2 i0 ; get offset reg for get_ptr -addi $r0 $r2 i0 ; get store offset -mcpi $r0 $r1 i32 ; store value -lw $r0 data_1 ; literal instantiation -addi $r1 $r2 i32 ; get offset reg for get_ptr -addi $r1 $r2 i32 ; get store offset -mcpi $r1 $r0 i32 ; store value -lw $r0 data_2 ; literal instantiation -addi $r1 $r2 i64 ; get offset reg for get_ptr -addi $r1 $r2 i64 ; get store offset -mcpi $r1 $r0 i32 ; store value -ret $zero ; returning unit as zero -.data: -data_0 .b256 0xa11bfeaaf375e5527e56b335059ce8ba90b767d7b6abe24ad4752c28be4dbceb -data_1 .b256 0xb3014a9722208a5ad14317a887fdac3f153f92968d905cea638cf54db8f133e0 -data_2 .b256 0x040d53c164d38731950be9278876db5fa5ab7409fdee8e3c87e2e6fbbeeebd48 diff --git a/sway-core/tests/ir_to_asm/generate_uid.ir b/sway-core/tests/ir_to_asm/generate_uid.ir deleted file mode 100644 index 47b4d0f73d1..00000000000 --- a/sway-core/tests/ir_to_asm/generate_uid.ir +++ /dev/null @@ -1,40 +0,0 @@ -script { - fn main() -> () { - local ptr b256 key1 - local ptr b256 key2 - local ptr b256 key3 - - entry: - v0 = generate_uid - v1 = get_ptr ptr b256 key1, ptr b256, 0 - store v0, ptr v1 - v2 = generate_uid - br block0 - - block0: - v3 = phi(entry: v2) - v4 = get_ptr ptr b256 key2, ptr b256, 0 - store v3, ptr v4 - v5 = generate_uid - br block1 - - block1: - v6 = phi(block0: v5) - v7 = get_ptr ptr b256 key3, ptr b256, 0 - store v6, ptr v7 - v8 = const unit () - ret () v8 - } - - fn anon_0() -> b256 { - entry: - v0 = generate_uid - ret b256 v0 - } - - fn anon_1() -> b256 { - entry: - v0 = generate_uid - ret b256 v0 - } -} diff --git a/sway-core/tests/ir_to_asm/get_storage_key.asm b/sway-core/tests/ir_to_asm/get_storage_key.asm new file mode 100644 index 00000000000..35b30957743 --- /dev/null +++ b/sway-core/tests/ir_to_asm/get_storage_key.asm @@ -0,0 +1,28 @@ +.program: +ji i4 +noop +DATA_SECTION_OFFSET[0..32] +DATA_SECTION_OFFSET[32..64] +lw $ds $is 1 +add $$ds $$ds $is +lw $r1 $fp i73 ; load input function selector +lw $r0 data_3 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnzi $r0 i14 ; jump to selected function +lw $r0 data_4 ; load fn selector for comparison +eq $r0 $r1 $r0 ; function selector comparison +jnzi $r0 i18 ; jump to selected function +rvrt $zero ; revert if no selectors matched +lw $r0 data_0 ; literal instantiation +lw $r1 data_1 ; loading size for RETD +retd $r0 $r1 +lw $r1 data_2 ; literal instantiation +lw $r0 data_1 ; loading size for RETD +retd $r1 $r0 +noop ; word-alignment of data section +.data: +data_0 .b256 0xf383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed +data_1 .u64 0x20 +data_2 .b256 0xde9090cb50e71c2588c773487d1da7066d0c719849a7e58dc8b6397a25c567c0 +data_3 .u32 0x2994c98e +data_4 .u32 0xf57bdec8 diff --git a/sway-core/tests/ir_to_asm/get_storage_key.ir b/sway-core/tests/ir_to_asm/get_storage_key.ir new file mode 100644 index 00000000000..06c82ab979f --- /dev/null +++ b/sway-core/tests/ir_to_asm/get_storage_key.ir @@ -0,0 +1,39 @@ +contract { + fn foo1<2994c98e>() -> b256 { + entry: + v0 = get_storage_key, !1, !2 + br block0 + + block0: + v1 = phi(entry: v0) + ret b256 v1 + } + + fn anon_0() -> b256 { + entry: + v0 = get_storage_key, !1 + ret b256 v0 + } + + fn foo2() -> b256 { + entry: + v0 = get_storage_key, !3, !4 + br block0 + + block0: + v1 = phi(entry: v0) + ret b256 v1 + } + + fn anon_1() -> b256 { + entry: + v0 = get_storage_key, !3 + ret b256 v0 + } +} + +!0 = filepath "/path/to/get_storage_key.sw" +!1 = span !0 72 91 +!2 = state_index 0 +!3 = span !0 72 91 +!4 = state_index 1 diff --git a/sway-core/tests/sway_to_ir/generate_uid.ir b/sway-core/tests/sway_to_ir/generate_uid.ir deleted file mode 100644 index 94c04fdef1f..00000000000 --- a/sway-core/tests/sway_to_ir/generate_uid.ir +++ /dev/null @@ -1,42 +0,0 @@ -script { - fn main() -> () { - local ptr b256 key1 - local ptr b256 key2 - local ptr b256 key3 - - entry: - v0 = generate_uid, !1 - v1 = get_ptr ptr b256 key1, ptr b256, 0, !2 - store v0, ptr v1, !2 - v2 = call anon_0(), !3 - v3 = get_ptr ptr b256 key2, ptr b256, 0, !4 - store v2, ptr v3, !4 - v4 = call anon_1(), !5 - v5 = get_ptr ptr b256 key3, ptr b256, 0, !6 - store v4, ptr v5, !6 - v6 = const unit () - ret () v6 - } - - fn anon_0() -> b256 { - entry: - v0 = generate_uid, !7 - ret b256 v0 - } - - fn anon_1() -> b256 { - entry: - v0 = generate_uid, !8 - ret b256 v0 - } -} - -!0 = filepath "/path/to/generate_uid.sw" -!1 = span !0 79 95 -!2 = span !0 68 96 -!3 = span !0 9 50 -!4 = span !0 101 118 -!5 = span !0 9 50 -!6 = span !0 123 140 -!7 = span !0 32 48 -!8 = span !0 32 48 diff --git a/sway-core/tests/sway_to_ir/generate_uid.sw b/sway-core/tests/sway_to_ir/generate_uid.sw deleted file mode 100644 index 07c5d9f41a3..00000000000 --- a/sway-core/tests/sway_to_ir/generate_uid.sw +++ /dev/null @@ -1,11 +0,0 @@ -script; - -fn foo() -> b256 { - __generate_uid() -} - -fn main() { - let key1 = __generate_uid(); - let key2 = foo(); - let key3 = foo(); -} diff --git a/sway-core/tests/sway_to_ir/get_storage_key.ir b/sway-core/tests/sway_to_ir/get_storage_key.ir new file mode 100644 index 00000000000..c4562827a45 --- /dev/null +++ b/sway-core/tests/sway_to_ir/get_storage_key.ir @@ -0,0 +1,33 @@ +contract { + fn foo1<2994c98e>() -> b256 { + entry: + v0 = call anon_0(), !1, !2 + ret b256 v0 + } + + fn anon_0() -> b256 { + entry: + v0 = get_storage_key, !3 + ret b256 v0 + } + + fn foo2() -> b256 { + entry: + v0 = call anon_1(), !4, !5 + ret b256 v0 + } + + fn anon_1() -> b256 { + entry: + v0 = get_storage_key, !6 + ret b256 v0 + } +} + +!0 = filepath "/path/to/get_storage_key.sw" +!1 = span !0 287 303 +!2 = state_index 0 +!3 = span !0 72 91 +!4 = span !0 342 358 +!5 = state_index 1 +!6 = span !0 72 91 diff --git a/sway-core/tests/sway_to_ir/get_storage_key.sw b/sway-core/tests/sway_to_ir/get_storage_key.sw new file mode 100644 index 00000000000..2de9f90cdcc --- /dev/null +++ b/sway-core/tests/sway_to_ir/get_storage_key.sw @@ -0,0 +1,28 @@ +contract; + +struct Empty {} + +impl Empty { + fn bar() -> b256 { + __get_storage_key() + } +} + +storage { + e1: Empty, + e2: Empty, +} + +abi GetStorageKeyTest { + fn foo1() -> b256; + fn foo2() -> b256; +} + +impl GetStorageKeyTest for Contract { + fn foo1() -> b256 { + storage.e1.bar() + } + fn foo2() -> b256 { + storage.e2.bar() + } +} diff --git a/sway-ir/src/block.rs b/sway-ir/src/block.rs index cf28a418fe9..b7dd20307ee 100644 --- a/sway-ir/src/block.rs +++ b/sway-ir/src/block.rs @@ -40,7 +40,7 @@ impl Block { /// is optional and is used only when printing the IR. pub fn new(context: &mut Context, function: Function, label: Option) -> Block { let label = function.get_unique_label(context, label); - let phi = Value::new_instruction(context, Instruction::Phi(Vec::new()), None); + let phi = Value::new_instruction(context, Instruction::Phi(Vec::new()), None, None); let content = BlockContent { label, function, diff --git a/sway-ir/src/instruction.rs b/sway-ir/src/instruction.rs index 7bac75454f8..c8114114e14 100644 --- a/sway-ir/src/instruction.rs +++ b/sway-ir/src/instruction.rs @@ -61,7 +61,7 @@ pub enum Instruction { indices: Vec, }, /// Generate a unique integer value - GenerateUid, + GetStorageKey, /// Return a pointer as a value. GetPointer { base_ptr: Pointer, @@ -160,7 +160,7 @@ impl Instruction { Instruction::ContractCall { return_type, .. } => Some(*return_type), Instruction::ExtractElement { ty, .. } => ty.get_elem_type(context), Instruction::ExtractValue { ty, indices, .. } => ty.get_field_type(context, indices), - Instruction::GenerateUid => Some(Type::B256), + Instruction::GetStorageKey => Some(Type::B256), Instruction::InsertElement { array, .. } => array.get_type(context), Instruction::InsertValue { aggregate, .. } => aggregate.get_type(context), Instruction::Load(ptr_val) => { @@ -284,7 +284,7 @@ impl Instruction { replace(index_val); } Instruction::ExtractValue { aggregate, .. } => replace(aggregate), - Instruction::GenerateUid => (), + Instruction::GetStorageKey => (), Instruction::Load(_) => (), Instruction::Nop => (), Instruction::Phi(pairs) => pairs.iter_mut().for_each(|(_, val)| replace(val)), @@ -390,15 +390,23 @@ impl<'a> InstructionInserter<'a> { args: Vec, span_md_idx: Option, ) -> Value { - let asm_val = - Value::new_instruction(self.context, Instruction::AsmBlock(asm, args), span_md_idx); + let asm_val = Value::new_instruction( + self.context, + Instruction::AsmBlock(asm, args), + span_md_idx, + None, + ); self.context.blocks[self.block.0].instructions.push(asm_val); asm_val } pub fn bitcast(self, value: Value, ty: Type, span_md_idx: Option) -> Value { - let bitcast_val = - Value::new_instruction(self.context, Instruction::BitCast(value, ty), span_md_idx); + let bitcast_val = Value::new_instruction( + self.context, + Instruction::BitCast(value, ty), + span_md_idx, + None, + ); self.context.blocks[self.block.0] .instructions .push(bitcast_val); @@ -411,8 +419,12 @@ impl<'a> InstructionInserter<'a> { phi_value: Option, span_md_idx: Option, ) -> Value { - let br_val = - Value::new_instruction(self.context, Instruction::Branch(to_block), span_md_idx); + let br_val = Value::new_instruction( + self.context, + Instruction::Branch(to_block), + span_md_idx, + None, + ); phi_value .into_iter() .for_each(|pv| to_block.add_phi(self.context, self.block, pv)); @@ -425,11 +437,13 @@ impl<'a> InstructionInserter<'a> { function: Function, args: &[Value], span_md_idx: Option, + state_idx_md_idx: Option, ) -> Value { let call_val = Value::new_instruction( self.context, Instruction::Call(function, args.to_vec()), span_md_idx, + state_idx_md_idx, ); self.context.blocks[self.block.0] .instructions @@ -448,6 +462,7 @@ impl<'a> InstructionInserter<'a> { self.context, Instruction::Cmp(pred, lhs_value, rhs_value), span_md_idx, + None, ); self.context.blocks[self.block.0].instructions.push(cmp_val); cmp_val @@ -469,6 +484,7 @@ impl<'a> InstructionInserter<'a> { false_block, }, span_md_idx, + None, ); phi_value.into_iter().for_each(|pv| { true_block.add_phi(self.context, self.block, pv); @@ -500,6 +516,7 @@ impl<'a> InstructionInserter<'a> { gas, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -522,6 +539,7 @@ impl<'a> InstructionInserter<'a> { index_val, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -544,6 +562,7 @@ impl<'a> InstructionInserter<'a> { indices, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -551,13 +570,21 @@ impl<'a> InstructionInserter<'a> { extract_value_val } - pub fn generate_uid(self, span_md_idx: Option) -> Value { - let generate_uid_val = - Value::new_instruction(self.context, Instruction::GenerateUid, span_md_idx); + pub fn get_storage_key( + self, + span_md_idx: Option, + state_index_md_idx: Option, + ) -> Value { + let get_storage_key_val = Value::new_instruction( + self.context, + Instruction::GetStorageKey, + span_md_idx, + state_index_md_idx, + ); self.context.blocks[self.block.0] .instructions - .push(generate_uid_val); - generate_uid_val + .push(get_storage_key_val); + get_storage_key_val } pub fn get_ptr( @@ -575,6 +602,7 @@ impl<'a> InstructionInserter<'a> { offset, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -599,6 +627,7 @@ impl<'a> InstructionInserter<'a> { index_val, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -623,6 +652,7 @@ impl<'a> InstructionInserter<'a> { indices, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -632,7 +662,7 @@ impl<'a> InstructionInserter<'a> { pub fn load(self, src_val: Value, span_md_idx: Option) -> Value { let load_val = - Value::new_instruction(self.context, Instruction::Load(src_val), span_md_idx); + Value::new_instruction(self.context, Instruction::Load(src_val), span_md_idx, None); self.context.blocks[self.block.0] .instructions .push(load_val); @@ -640,14 +670,18 @@ impl<'a> InstructionInserter<'a> { } pub fn nop(self) -> Value { - let nop_val = Value::new_instruction(self.context, Instruction::Nop, None); + let nop_val = Value::new_instruction(self.context, Instruction::Nop, None, None); self.context.blocks[self.block.0].instructions.push(nop_val); nop_val } pub fn read_register(self, reg: Register, span_md_idx: Option) -> Value { - let read_register_val = - Value::new_instruction(self.context, Instruction::ReadRegister(reg), span_md_idx); + let read_register_val = Value::new_instruction( + self.context, + Instruction::ReadRegister(reg), + span_md_idx, + None, + ); self.context.blocks[self.block.0] .instructions .push(read_register_val); @@ -656,7 +690,7 @@ impl<'a> InstructionInserter<'a> { pub fn ret(self, value: Value, ty: Type, span_md_idx: Option) -> Value { let ret_val = - Value::new_instruction(self.context, Instruction::Ret(value, ty), span_md_idx); + Value::new_instruction(self.context, Instruction::Ret(value, ty), span_md_idx, None); self.context.blocks[self.block.0].instructions.push(ret_val); ret_val } @@ -671,6 +705,7 @@ impl<'a> InstructionInserter<'a> { self.context, Instruction::StateLoadQuadWord { load_val, key }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -679,8 +714,12 @@ impl<'a> InstructionInserter<'a> { } pub fn state_load_word(self, key: Value, span_md_idx: Option) -> Value { - let state_load_val = - Value::new_instruction(self.context, Instruction::StateLoadWord(key), span_md_idx); + let state_load_val = Value::new_instruction( + self.context, + Instruction::StateLoadWord(key), + span_md_idx, + None, + ); self.context.blocks[self.block.0] .instructions .push(state_load_val); @@ -697,6 +736,7 @@ impl<'a> InstructionInserter<'a> { self.context, Instruction::StateStoreQuadWord { stored_val, key }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -714,6 +754,7 @@ impl<'a> InstructionInserter<'a> { self.context, Instruction::StateStoreWord { stored_val, key }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions @@ -734,6 +775,7 @@ impl<'a> InstructionInserter<'a> { stored_val, }, span_md_idx, + None, ); self.context.blocks[self.block.0] .instructions diff --git a/sway-ir/src/metadata.rs b/sway-ir/src/metadata.rs index 0c43216ae53..168e185ab6e 100644 --- a/sway-ir/src/metadata.rs +++ b/sway-ir/src/metadata.rs @@ -20,6 +20,7 @@ pub enum Metadatum { start: usize, end: usize, }, + StateIndex(usize), } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -69,4 +70,17 @@ impl MetadataIndex { _otherwise => Err(IrError::InvalidMetadatum), } } + + pub fn from_state_idx(context: &mut Context, state_idx: usize) -> Option { + Some(MetadataIndex( + context.metadata.insert(Metadatum::StateIndex(state_idx)), + )) + } + + pub fn to_state_idx(&self, context: &Context) -> Result { + match &context.metadata[self.0] { + Metadatum::StateIndex(ix) => Ok(*ix), + _otherwise => Err(IrError::InvalidMetadatum), + } + } } diff --git a/sway-ir/src/optimize/constants.rs b/sway-ir/src/optimize/constants.rs index 5d012b5e126..60e977c6763 100644 --- a/sway-ir/src/optimize/constants.rs +++ b/sway-ir/src/optimize/constants.rs @@ -93,6 +93,7 @@ fn combine_const_aggregate_field( ValueContent { value: ValueDatum::Constant(c), span_md_idx, + state_idx_md_idx: None, } => (c.clone(), *span_md_idx), _otherwise => { unreachable!("BUG! Invalid aggregate parameter to combine_const_insert_value()") diff --git a/sway-ir/src/optimize/inline.rs b/sway-ir/src/optimize/inline.rs index 5abbed89712..e3a1f5b7c4f 100644 --- a/sway-ir/src/optimize/inline.rs +++ b/sway-ir/src/optimize/inline.rs @@ -11,6 +11,7 @@ use crate::{ error::IrError, function::Function, instruction::Instruction, + metadata::MetadataIndex, pointer::Pointer, value::{Value, ValueContent, ValueDatum}, }; @@ -94,6 +95,10 @@ pub fn inline_function_call( } } + // Get the state index metadata attached to the function call. This needs to be propagated to + // the __get_storage_key intrinsic + let state_idx_md_idx = context.values[call_site.0].state_idx_md_idx; + // Now remove the call altogether. context.values.remove(call_site.0); @@ -141,6 +146,7 @@ pub fn inline_function_call( &block_map, &mut value_map, &ptr_map, + state_idx_md_idx, ); } } @@ -167,6 +173,7 @@ pub fn inline_function_call( Ok(()) } +#[allow(clippy::too_many_arguments)] fn inline_instruction( context: &mut Context, new_block: &Block, @@ -175,6 +182,7 @@ fn inline_instruction( block_map: &HashMap, value_map: &mut HashMap, ptr_map: &HashMap, + state_idx_md_idx: Option, ) { // Util to translate old blocks to new. If an old block isn't in the map then we panic, since // it should be guaranteed to be there...that's a bug otherwise. @@ -195,6 +203,7 @@ fn inline_instruction( if let ValueContent { value: ValueDatum::Instruction(old_ins), span_md_idx, + .. } = context.values[instruction.0].clone() { let new_ins = match old_ins { @@ -231,6 +240,7 @@ fn inline_instruction( .collect::>() .as_slice(), span_md_idx, + state_idx_md_idx, ), Instruction::Cmp(pred, lhs_value, rhs_value) => new_block.ins(context).cmp( pred, @@ -284,7 +294,9 @@ fn inline_instruction( .ins(context) .extract_value(map_value(aggregate), ty, indices, span_md_idx) } - Instruction::GenerateUid => new_block.ins(context).generate_uid(span_md_idx), + Instruction::GetStorageKey => new_block + .ins(context) + .get_storage_key(span_md_idx, state_idx_md_idx), Instruction::GetPointer { base_ptr, ptr_ty, diff --git a/sway-ir/src/parser.rs b/sway-ir/src/parser.rs index f05703c3db9..1edb288ad1e 100644 --- a/sway-ir/src/parser.rs +++ b/sway-ir/src/parser.rs @@ -98,11 +98,15 @@ mod ir_builder { } rule instr_decl() -> IrAstInstruction - = value_name:value_assign()? op:operation() meta_idx:comma_metadata_idx()? { + = value_name:value_assign()? op:operation() + meta_idx:comma_metadata_idx()? + state_idx_md_idx:comma_metadata_idx()? + { IrAstInstruction { value_name, op, meta_idx, + state_idx_md_idx, } } @@ -132,7 +136,7 @@ mod ir_builder { / op_contract_call() / op_extract_element() / op_extract_value() - / op_generate_uid() + / op_get_storage_key() / op_get_ptr() / op_insert_element() / op_insert_value() @@ -207,9 +211,9 @@ mod ir_builder { IrAstOperation::ExtractValue(name, ty, idcs) } - rule op_generate_uid() -> IrAstOperation - = "generate_uid" _ { - IrAstOperation::GenerateUid() + rule op_get_storage_key() -> IrAstOperation + = "get_storage_key" _ { + IrAstOperation::GetStorageKey() } rule op_get_ptr() -> IrAstOperation @@ -441,6 +445,9 @@ mod ir_builder { / "span" _ "!" li:decimal() s:decimal() e:decimal() { IrMetadatum::Span { loc_idx: li, start: s as usize, end: e as usize } } + / "state_index" _ idx:decimal() { + IrMetadatum::StateIndex { idx: idx as usize} + } rule id_char0() = quiet!{ ['A'..='Z' | 'a'..='z' | '_'] } @@ -527,6 +534,7 @@ mod ir_builder { value_name: Option, op: IrAstOperation, meta_idx: Option, + state_idx_md_idx: Option, } #[derive(Debug)] @@ -547,7 +555,7 @@ mod ir_builder { ContractCall(IrAstTy, String, String, String, String, String), ExtractElement(String, IrAstTy, String), ExtractValue(String, IrAstTy, Vec), - GenerateUid(), + GetStorageKey(), GetPtr(String, IrAstTy, u64), InsertElement(String, IrAstTy, String, String), InsertValue(String, IrAstTy, String, Vec), @@ -696,6 +704,9 @@ mod ir_builder { start: usize, end: usize, }, + StateIndex { + idx: usize, + }, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -720,7 +731,14 @@ mod ir_builder { module: Module, fn_decl: IrAstFnDecl, md_map: &HashMap, - unresolved_calls: &mut Vec<(Block, Value, String, Vec, Option)>, + unresolved_calls: &mut Vec<( + Block, + Value, + String, + Vec, + Option, + Option, + )>, ) -> Result<(), IrError> { let args: Vec<(String, Type, Option)> = fn_decl .args @@ -800,11 +818,22 @@ mod ir_builder { ptr_map: &HashMap, val_map: &mut HashMap, md_map: &HashMap, - unresolved_calls: &mut Vec<(Block, Value, String, Vec, Option)>, + unresolved_calls: &mut Vec<( + Block, + Value, + String, + Vec, + Option, + Option, + )>, ) { let block = named_blocks.get(&ir_block.label).unwrap(); for ins in ir_block.instructions { let opt_ins_md_idx = ins.meta_idx.map(|mdi| md_map.get(&mdi).unwrap()).copied(); + let opt_ins_state_idx_md_idx = ins + .state_idx_md_idx + .map(|mdi| md_map.get(&mdi).unwrap()) + .copied(); let ins_val = match ins.op { IrAstOperation::Asm(args, return_type, return_name, ops, meta_idx) => { let args = args @@ -868,6 +897,7 @@ mod ir_builder { .cloned() .collect::>(), opt_ins_md_idx, + opt_ins_state_idx_md_idx, )); nop } @@ -920,7 +950,9 @@ mod ir_builder { opt_ins_md_idx, ) } - IrAstOperation::GenerateUid() => block.ins(context).generate_uid(opt_ins_md_idx), + IrAstOperation::GetStorageKey() => block + .ins(context) + .get_storage_key(opt_ins_md_idx, opt_ins_state_idx_md_idx), IrAstOperation::GetPtr(base_ptr, ptr_ty, offset) => { let ptr_ir_ty = ptr_ty.to_ir_type(context); block.ins(context).get_ptr( @@ -1033,7 +1065,10 @@ mod ir_builder { _otherwise => None, }) .fold(HashMap::new(), |mut md_map, (idx_ref, path)| { - let path_content = Arc::from(std::fs::read_to_string(path).unwrap().as_str()); + let path_content = match std::fs::read_to_string(path) { + Ok(res) => Arc::from(res.as_str()), + Err(_) => Arc::from(""), + }; let md_idx = context.metadata.insert(Metadatum::FileLocation( Arc::new(path.clone()), path_content, @@ -1043,18 +1078,26 @@ mod ir_builder { }); for (idx_ref, md) in ir_metadata { - if let IrMetadatum::Span { - loc_idx, - start, - end, - } = md - { - let span_idx = context.metadata.insert(Metadatum::Span { - loc_idx: md_map.get(loc_idx).copied().unwrap(), - start: *start, - end: *end, - }); - md_map.insert(*idx_ref, MetadataIndex(span_idx)); + match md { + IrMetadatum::Span { + loc_idx, + start, + end, + } => { + let span_idx = context.metadata.insert(Metadatum::Span { + loc_idx: md_map.get(loc_idx).copied().unwrap(), + start: *start, + end: *end, + }); + md_map.insert(*idx_ref, MetadataIndex(span_idx)); + } + IrMetadatum::StateIndex { idx } => { + md_map.insert( + *idx_ref, + MetadataIndex(context.metadata.insert(Metadatum::StateIndex(*idx))), + ); + } + _ => {} } } md_map @@ -1063,13 +1106,21 @@ mod ir_builder { #[allow(clippy::type_complexity)] fn resolve_calls( context: &mut Context, - unresolved_calls: Vec<(Block, Value, String, Vec, Option)>, + unresolved_calls: Vec<( + Block, + Value, + String, + Vec, + Option, + Option, + )>, ) -> Result<(), IrError> { // All of the call instructions are currently NOPs which need to be replaced with actual // calls. We couldn't do it above until we'd gone and created all the functions first. // // Now we can loop and find the callee function for each call and replace the NOPs. - for (block, nop, callee, args, opt_ins_md_idx) in unresolved_calls { + for (block, nop, callee, args, opt_ins_md_idx, opt_ins_state_idx_md_idx) in unresolved_calls + { let function = context .functions .iter() @@ -1081,8 +1132,12 @@ mod ir_builder { } }) .unwrap(); - let call_val = - Value::new_instruction(context, Instruction::Call(function, args), opt_ins_md_idx); + let call_val = Value::new_instruction( + context, + Instruction::Call(function, args), + opt_ins_md_idx, + opt_ins_state_idx_md_idx, + ); block.replace_instruction(context, nop, call_val)?; } Ok(()) diff --git a/sway-ir/src/printer.rs b/sway-ir/src/printer.rs index 50a2d174e3d..19335ac2b89 100644 --- a/sway-ir/src/printer.rs +++ b/sway-ir/src/printer.rs @@ -153,6 +153,7 @@ fn function_to_doc<'a>( ValueContent { value: ValueDatum::Argument(ty), span_md_idx, + .. } => (ty, span_md_idx), _ => unreachable!("Unexpected non argument value for function arguments."), }; @@ -233,6 +234,7 @@ fn constant_to_doc( if let ValueContent { value: ValueDatum::Constant(constant), span_md_idx, + .. } = &context.values[const_val.0] { Doc::text_line(format!( @@ -291,6 +293,7 @@ fn instruction_to_doc<'a>( ValueContent { value: ValueDatum::Instruction(instruction), span_md_idx, + state_idx_md_idx, } => match instruction { Instruction::AsmBlock(asm, args) => { asm_block_to_doc(context, md_namer, namer, ins_value, asm, args, span_md_idx) @@ -332,6 +335,12 @@ fn instruction_to_doc<'a>( .append(match span_md_idx { None => Doc::Empty, Some(_) => Doc::text(md_namer.meta_as_string(context, span_md_idx, true)), + }) + .append(match state_idx_md_idx { + None => Doc::Empty, + Some(_) => { + Doc::text(md_namer.meta_as_string(context, state_idx_md_idx, true)) + } }), )), Instruction::Cmp(pred, lhs_value, rhs_value) => { @@ -421,10 +430,11 @@ fn instruction_to_doc<'a>( Some(_) => Doc::text(md_namer.meta_as_string(context, span_md_idx, true)), }), )), - Instruction::GenerateUid => Doc::text_line(format!( - "{} = generate_uid{}", + Instruction::GetStorageKey => Doc::text_line(format!( + "{} = get_storage_key{}{}", namer.name(context, ins_value), md_namer.meta_as_string(context, span_md_idx, true), + md_namer.meta_as_string(context, state_idx_md_idx, true), )), Instruction::GetPointer { base_ptr, @@ -685,6 +695,7 @@ fn metadata_to_doc(context: &Context, md_namer: &MetadataNamer) -> Doc { } => md_namer .get(loc_idx) .map(|loc_ref_idx| format!("!{ref_idx} = span !{loc_ref_idx} {start} {end}")), + Metadatum::StateIndex(idx) => Some(format!("!{ref_idx} = state_index {idx:?}")), } .map(&Doc::text_line) }) diff --git a/sway-ir/src/value.rs b/sway-ir/src/value.rs index 1704e5fff3e..09e01a1bb68 100644 --- a/sway-ir/src/value.rs +++ b/sway-ir/src/value.rs @@ -23,6 +23,7 @@ pub struct Value(pub generational_arena::Index); pub struct ValueContent { pub value: ValueDatum, pub span_md_idx: Option, + pub state_idx_md_idx: Option, } #[doc(hidden)] @@ -43,6 +44,7 @@ impl Value { let content = ValueContent { value: ValueDatum::Argument(ty), span_md_idx, + state_idx_md_idx: None, }; Value(context.values.insert(content)) } @@ -56,6 +58,7 @@ impl Value { let content = ValueContent { value: ValueDatum::Constant(constant), span_md_idx, + state_idx_md_idx: None, }; Value(context.values.insert(content)) } @@ -65,10 +68,12 @@ impl Value { context: &mut Context, instruction: Instruction, opt_span_md_idx: Option, + opt_state_idx_md_idx: Option, ) -> Value { let content = ValueContent { value: ValueDatum::Instruction(instruction), span_md_idx: opt_span_md_idx, + state_idx_md_idx: opt_state_idx_md_idx, }; Value(context.values.insert(content)) } @@ -84,6 +89,15 @@ impl Value { .expect("A valid span.") } + /// Return the content of the state index metadata + pub fn get_storage_key(&self, context: &Context) -> Option { + context.values[self.0] + .state_idx_md_idx + .map(|idx| idx.to_state_idx(context)) + .transpose() + .expect("A valid state index.") + } + /// Return whether this is a constant value. pub fn is_constant(&self, context: &Context) -> bool { matches!(context.values[self.0].value, ValueDatum::Constant(_)) diff --git a/sway-ir/src/verify.rs b/sway-ir/src/verify.rs index 78c50f701b8..4512ff5250c 100644 --- a/sway-ir/src/verify.rs +++ b/sway-ir/src/verify.rs @@ -123,7 +123,7 @@ impl<'a> InstructionVerifier<'a> { ty, indices, } => self.verify_extract_value(aggregate, ty, indices)?, - Instruction::GenerateUid => (), + Instruction::GetStorageKey => (), Instruction::GetPointer { base_ptr, ptr_ty, diff --git a/sway-ir/tests/inline/get_storage_key.ir b/sway-ir/tests/inline/get_storage_key.ir new file mode 100644 index 00000000000..60114aa47c8 --- /dev/null +++ b/sway-ir/tests/inline/get_storage_key.ir @@ -0,0 +1,30 @@ +// regex: VAR=v\d+ +// regex: MD=!\d+ +// regex: LABEL=[[:alpha:]0-9]+: + +script { + fn anon_0() -> b256 { + entry: + v0 = get_storage_key, !2 + ret b256 v0 + } + +// check: fn main + fn main() -> b256 { + entry: + v0 = call anon_0(), !1, !3 +// check: $(arg0=$VAR) = get_storage_key, !1, $(md0=$MD) + +// check: $(arg1=$VAR) = phi($LABEL $arg0) +// check: ret b256 $arg1 + ret b256 v0 + } +} + +// check: $(md0) = state_index 42 + +!0 = filepath "proj/src/main.sw" +!1 = span !0 381 425 +!2 = span !0 404 423 +!3 = state_index 42 + diff --git a/sway-lib-std/src/storage.sw b/sway-lib-std/src/storage.sw index cf535201c9c..0de36a0fc52 100644 --- a/sway-lib-std/src/storage.sw +++ b/sway-lib-std/src/storage.sw @@ -92,22 +92,16 @@ pub fn get(key: b256) -> T { } } -pub struct StorageMap { - seed: b256, -} +pub struct StorageMap { } impl StorageMap { - fn new() -> StorageMap { - StorageMap { seed: __generate_uid() } - } - fn insert(self, key: K, value: V) { - let key = sha256((key, self.seed)); + let key = sha256((key, __get_storage_key())); store::(key, value); } fn get(self, key: K) -> V { - let key = sha256((key, self.seed)); + let key = sha256((key, __get_storage_key())); get::(key) } } diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index d31a78ea5c5..16144a4cdcd 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -447,7 +447,7 @@ fn handle_expression(exp: Expression, tokens: &mut Vec) { Expression::BuiltinGetTypeProperty { .. } => { //TODO handle built in get type property? } - Expression::BuiltinGenerateUid { .. } => { + Expression::BuiltinGetStorageKey { .. } => { //TODO handle built in generate uid? } } diff --git a/sway-lsp/src/core/traverse_typed_tree.rs b/sway-lsp/src/core/traverse_typed_tree.rs index a8f404244d6..15ff19fd3fb 100644 --- a/sway-lsp/src/core/traverse_typed_tree.rs +++ b/sway-lsp/src/core/traverse_typed_tree.rs @@ -309,7 +309,7 @@ fn handle_expression(expression: &TypedExpression, tokens: &mut TokenMap) { } } TypedExpressionVariant::TypeProperty { .. } => {} - TypedExpressionVariant::GenerateUid { .. } => {} + TypedExpressionVariant::GetStorageKey { .. } => {} TypedExpressionVariant::SizeOfValue { expr } => { handle_expression(expr, tokens); } diff --git a/sway-parse/src/intrinsics.rs b/sway-parse/src/intrinsics.rs index 2c3cb2ad1ff..7271d8adcc1 100644 --- a/sway-parse/src/intrinsics.rs +++ b/sway-parse/src/intrinsics.rs @@ -1,6 +1,6 @@ #[derive(Eq, PartialEq)] pub enum Intrinsic { - GenerateUid, + GetStorageKey, IsReferenceType, SizeOf, SizeOfVal, @@ -10,7 +10,7 @@ impl Intrinsic { pub fn try_from_str(raw: &str) -> Option { use Intrinsic::*; Some(match raw { - "__generate_uid" => GenerateUid, + "__get_storage_key" => GetStorageKey, "__is_reference_type" => IsReferenceType, "__size_of" => SizeOf, "__size_of_val" => SizeOfVal, diff --git a/test/src/e2e_vm_tests/mod.rs b/test/src/e2e_vm_tests/mod.rs index 57148e1eacd..593722f476e 100644 --- a/test/src/e2e_vm_tests/mod.rs +++ b/test/src/e2e_vm_tests/mod.rs @@ -380,14 +380,6 @@ pub fn run(filter_regex: Option) { "should_pass/language/match_expressions_mismatched", ProgramState::Return(5), ), - ( - "should_pass/language/generate_uid", - ProgramState::ReturnData(Bytes32::from([ - 0x17, 0x6e, 0x57, 0xc7, 0x2a, 0x93, 0x91, 0x74, 0x4a, 0x01, 0x44, 0x98, 0xb6, 0xda, - 0xee, 0x2f, 0xb5, 0x30, 0x0a, 0x6f, 0x57, 0xd3, 0xf9, 0x24, 0x06, 0x39, 0xcf, 0x3b, - 0xfb, 0xc7, 0x88, 0x4e, - ])), - ), ( "should_pass/language/match_expressions_inside_generic_functions", ProgramState::Return(1), @@ -467,6 +459,10 @@ pub fn run(filter_regex: Option) { "should_pass/test_contracts/abi_with_tuples_contract", ProgramState::Revert(0), ), + ( + "should_pass/test_contracts/get_storage_key_contract", + ProgramState::Revert(0), + ), ]; number_of_tests_run += positive_project_names_with_abi @@ -613,8 +609,8 @@ pub fn run(filter_regex: Option) { ), ( ( - "should_pass/test_contracts/nested_struct_args_contract", - "should_pass/require_contract_deployment/nested_struct_args_caller", + "should_pass/test_contracts/get_storage_key_contract", + "should_pass/require_contract_deployment/get_storage_key_caller", ), 1, ), diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.lock deleted file mode 100644 index f0989837c5f..00000000000 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.lock +++ /dev/null @@ -1,11 +0,0 @@ -[[package]] -name = 'core' -dependencies = [] - -[[package]] -name = 'generate_uid' -dependencies = ['std'] - -[[package]] -name = 'std' -dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/src/main.sw deleted file mode 100644 index d907b648189..00000000000 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/src/main.sw +++ /dev/null @@ -1,41 +0,0 @@ -script; - -use std::assert::assert; - -fn bar() -> (b256, b256) { - (foo(), foo()) -} - -fn foo() -> b256 { - __generate_uid() -} - -fn main() -> b256 { - let key1 = __generate_uid(); - let key2 = __generate_uid(); - let key3 = foo(); - let key4 = foo(); - let (key5, key6) = bar(); - - assert(key1 != key2); - assert(key1 != key3); - assert(key1 != key4); - assert(key1 != key5); - assert(key1 != key6); - - assert(key2 != key3); - assert(key2 != key4); - assert(key2 != key5); - assert(key2 != key6); - - assert(key3 != key4); - assert(key3 != key5); - assert(key3 != key6); - - assert(key4 != key5); - assert(key4 != key6); - - assert(key5 != key6); - - key1 -} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.lock new file mode 100644 index 00000000000..c1643b4f90d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.lock @@ -0,0 +1,18 @@ +[[package]] +name = 'core' +dependencies = [] + +[[package]] +name = 'get_storage_key_abi' +dependencies = [] + +[[package]] +name = 'get_storage_key_caller' +dependencies = [ + 'get_storage_key_abi', + 'std', +] + +[[package]] +name = 'std' +dependencies = ['core'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.toml similarity index 61% rename from test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.toml rename to test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.toml index eededf9a418..f902d59c081 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generate_uid/Forc.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/Forc.toml @@ -2,7 +2,8 @@ authors = ["Fuel Labs "] entry = "main.sw" license = "Apache-2.0" -name = "generate_uid" +name = "get_storage_key_caller" [dependencies] +get_storage_key_abi = { path = "../../test_abis/get_storage_key_abi" } std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/src/main.sw new file mode 100644 index 00000000000..cc91dea8b52 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/get_storage_key_caller/src/main.sw @@ -0,0 +1,30 @@ +script; +use get_storage_key_abi::TestContract; +use std::assert::assert; + +fn main() -> u64 { + let caller = abi(TestContract, 0x2ecaf8fd525af004f5c9e1368b4cd0a5b30fa7f93ddfdb140695b4ce4eece8da); + + let f1 = caller.from_f1(); + assert(f1 == caller.from_f1()); + + let f2 = caller.from_f2(); + assert(f2 == caller.from_f2()); + + let f3 = caller.from_f3(); + assert(f3 == caller.from_f3()); + + let f4 = caller.from_f4(); + assert(f4 == caller.from_f4()); + + assert(f1 != f2); + assert(f1 != f3); + assert(f1 != f4); + + assert(f2 != f3); + assert(f2 != f4); + + assert(f3 != f4); + + 1 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.lock new file mode 100644 index 00000000000..d3f9658bdd1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.lock @@ -0,0 +1,3 @@ +[[package]] +name = 'array_of_structs_abi' +dependencies = [] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.toml new file mode 100644 index 00000000000..f67ca7cf2c1 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +implicit-std = false +license = "Apache-2.0" +name = "get_storage_key_abi" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/src/main.sw new file mode 100644 index 00000000000..4a3cd045176 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_abis/get_storage_key_abi/src/main.sw @@ -0,0 +1,8 @@ +library get_storage_key_abi; + +abi TestContract { + fn from_f1() -> b256; + fn from_f2() -> b256; + fn from_f3() -> b256; + fn from_f4() -> b256; +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.lock new file mode 100644 index 00000000000..cf8f6ecdda7 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.lock @@ -0,0 +1,7 @@ +[[package]] +name = 'get_storage_key_abi' +dependencies = [] + +[[package]] +name = 'get_storage_key_contract' +dependencies = ['get_storage_key_abi'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.toml new file mode 100644 index 00000000000..6d99dc99420 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +implicit-std = false +license = "Apache-2.0" +name = "get_storage_key_contract" + +[dependencies] +get_storage_key_abi = { path = "../../test_abis/get_storage_key_abi" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_abi_oracle.json new file mode 100644 index 00000000000..49d1cb26207 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/json_abi_oracle.json @@ -0,0 +1,50 @@ +[ + { + "inputs": [], + "name": "from_f1", + "outputs": [ + { + "components": null, + "name": "", + "type": "b256" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "from_f2", + "outputs": [ + { + "components": null, + "name": "", + "type": "b256" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "from_f3", + "outputs": [ + { + "components": null, + "name": "", + "type": "b256" + } + ], + "type": "function" + }, + { + "inputs": [], + "name": "from_f4", + "outputs": [ + { + "components": null, + "name": "", + "type": "b256" + } + ], + "type": "function" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/src/main.sw new file mode 100644 index 00000000000..30baf7a86fa --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/get_storage_key_contract/src/main.sw @@ -0,0 +1,36 @@ +contract; + +use get_storage_key_abi::TestContract; + +struct Foo { +} + +impl Foo { + fn foo() -> b256 { + __get_storage_key() + } +} + +storage { + x: u64, + f1: Foo, + f2: Foo, + y: u64, + f3: Foo, + f4: Foo, +} + +impl TestContract for Contract { + fn from_f1() -> b256 { + storage.f1.foo() + } + fn from_f2() -> b256 { + storage.f2.foo() + } + fn from_f3() -> b256 { + storage.f3.foo() + } + fn from_f4() -> b256 { + storage.f4.foo() + } +} diff --git a/test/src/sdk-harness/test_projects/storage_map/mod.rs b/test/src/sdk-harness/test_projects/storage_map/mod.rs index fd706b26b7a..fe72514eda2 100644 --- a/test/src/sdk-harness/test_projects/storage_map/mod.rs +++ b/test/src/sdk-harness/test_projects/storage_map/mod.rs @@ -27,8 +27,6 @@ mod u64_to { async fn bool_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (1, 2, 3); let (val1, val2, val3) = (true, false, true); @@ -83,8 +81,6 @@ mod u64_to { async fn u8_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (1, 2, 3); let (val1, val2, val3) = (8, 66, 99); @@ -137,8 +133,6 @@ mod u64_to { async fn u16_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (6, 9, 1); let (val1, val2, val3) = (9, 42, 100); @@ -191,8 +185,6 @@ mod u64_to { async fn u32_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (5, 99, 10); let (val1, val2, val3) = (90, 2, 100); @@ -245,8 +237,6 @@ mod u64_to { async fn u64_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (50, 99, 1); let (val1, val2, val3) = (90, 20, 10); @@ -299,8 +289,6 @@ mod u64_to { async fn tuple_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (50, 99, 10); let (val1, val2, val3) = ( ([1; 32], 42, true), @@ -357,8 +345,6 @@ mod u64_to { async fn struct_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (5, 9, 1); let (val1, val2, val3) = ( Struct { @@ -427,8 +413,6 @@ mod u64_to { async fn enum_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (44, 17, 1000); let (val1, val2, val3) = (Enum::V1([66; 32]), Enum::V2(42), Enum::V3([42; 32])); @@ -481,8 +465,6 @@ mod u64_to { async fn string_map() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (9001, 1980, 1000); let (val1, val2, val3) = ( "fastest_modular_execution_layer_A", @@ -544,8 +526,6 @@ mod to_u64_map { async fn from_bool() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2) = (true, false); let (val1, val2) = (1, 2); @@ -584,8 +564,6 @@ mod to_u64_map { async fn from_u8() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (8, 66, 99); let (val1, val2, val3) = (1, 2, 3); @@ -638,8 +616,6 @@ mod to_u64_map { async fn from_u16() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (9, 42, 100); let (val1, val2, val3) = (6, 9, 1); @@ -692,8 +668,6 @@ mod to_u64_map { async fn from_u32() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (90, 2, 100); let (val1, val2, val3) = (5, 99, 10); @@ -746,8 +720,6 @@ mod to_u64_map { async fn from_tuple() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = ( ([1; 32], 42, true), ([2; 32], 24, true), @@ -804,8 +776,6 @@ mod to_u64_map { async fn from_struct() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = ( Struct { x: 42, @@ -875,8 +845,6 @@ mod to_u64_map { async fn from_enum() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (Enum::V1([66; 32]), Enum::V2(42), Enum::V3([42; 32])); let (val1, val2, val3) = (44, 17, 1000); @@ -925,8 +893,6 @@ mod to_u64_map { async fn from_string() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = ( "fastest_modular_execution_layer_A", "fastest_modular_execution_layer_B", @@ -984,8 +950,6 @@ mod to_u64_map { async fn test_multiple_maps() { let instance = test_storage_map_instance().await; - instance.init().call().await.unwrap(); - let (key1, key2, key3) = (1, 2, 3); let (val1_1, val2_1, val3_1) = (8, 66, 99); let (val1_2, val2_2, val3_2) = (9, 42, 100); diff --git a/test/src/sdk-harness/test_projects/storage_map/src/main.sw b/test/src/sdk-harness/test_projects/storage_map/src/main.sw index a49aa9c6b94..3e49897304c 100644 --- a/test/src/sdk-harness/test_projects/storage_map/src/main.sw +++ b/test/src/sdk-harness/test_projects/storage_map/src/main.sw @@ -40,8 +40,6 @@ storage { } abi StorageMapTest { - fn init(); - fn insert_into_u64_to_bool_map(key: u64, value: bool); fn get_from_u64_to_bool_map(key: u64) -> bool; @@ -105,31 +103,6 @@ abi StorageMapTest { } impl StorageMapTest for Contract { - fn init() { - storage.map1 = ~StorageMap::new::(); - storage.map2 = ~StorageMap::new::(); - storage.map3 = ~StorageMap::new::(); - storage.map4 = ~StorageMap::new::(); - storage.map5 = ~StorageMap::new::(); - storage.map6 = ~StorageMap::new::(); - storage.map7 = ~StorageMap::new::(); - storage.map8 = ~StorageMap::new::(); - storage.map9 = ~StorageMap::new::(); - storage.map10 = ~StorageMap::new::(); - - storage.map11 = ~StorageMap::new::(); - storage.map12 = ~StorageMap::new::(); - storage.map13 = ~StorageMap::new::(); - storage.map14 = ~StorageMap::new::(); - storage.map15 = ~StorageMap::new::<(b256, u8, bool), u64 >(); - storage.map16 = ~StorageMap::new::(); - storage.map17 = ~StorageMap::new::(); - storage.map18 = ~StorageMap::new::(); - storage.map19 = ~StorageMap::new::<[b256; - 3], u64>(); - } - fn insert_into_u64_to_bool_map(key: u64, value: bool) { storage.map1.insert(key, value); }