Skip to content

Commit

Permalink
Eliminating the need for new() to use StorageMap (FuelLabs#1776)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammadfawaz authored Jun 1, 2022
1 parent 133ec9b commit 443f42c
Show file tree
Hide file tree
Showing 52 changed files with 680 additions and 354 deletions.
1 change: 1 addition & 0 deletions sway-core/src/asm_generation/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
58 changes: 46 additions & 12 deletions sway-core/src/asm_generation/from_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<CompileWarning> = Vec::new();
let mut errors: Vec<CompileError> = 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);

Expand All @@ -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(
Expand Down
2 changes: 0 additions & 2 deletions sway-core/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
12 changes: 6 additions & 6 deletions sway-core/src/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
}
Expand Down Expand Up @@ -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(),
}
}
Expand Down Expand Up @@ -1399,17 +1399,17 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result<Expression, E
} else if call_path.prefixes.is_empty()
&& !call_path.is_absolute
&& Intrinsic::try_from_str(call_path.suffix.as_str())
== Some(Intrinsic::GenerateUid)
== Some(Intrinsic::GetStorageKey)
{
if !arguments.is_empty() {
let error = ConvertParseTreeError::GenerateUidTooManyArgs { span };
let error = ConvertParseTreeError::GetStorageKeyTooManyArgs { span };
return Err(ec.error(error));
}
if generics_opt.is_some() {
let error = ConvertParseTreeError::GenericsNotSupportedHere { span };
return Err(ec.error(error));
}
Expression::BuiltinGenerateUid { span }
Expression::BuiltinGetStorageKey { span }
} else if call_path.prefixes.is_empty()
&& !call_path.is_absolute
&& Intrinsic::try_from_str(call_path.suffix.as_str())
Expand Down
34 changes: 24 additions & 10 deletions sway-core/src/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ impl FnCompiler {
contract_call_params,
arguments,
function_body,
self_state_idx,
selector,
} => {
if let Some(metadata) = selector {
Expand All @@ -619,6 +620,7 @@ impl FnCompiler {
name.suffix.as_str(),
arguments,
Some(function_body),
self_state_idx,
span_md_idx,
)
}
Expand Down Expand Up @@ -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<MetadataIndex>,
) -> Result<Value, CompileError> {
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(
Expand Down Expand Up @@ -1042,6 +1047,7 @@ impl FnCompiler {
_ast_name: &str,
ast_args: Vec<(Ident, TypedExpression)>,
callee_body: Option<TypedCodeBlock>,
self_state_idx: Option<StateIndex>,
span_md_idx: Option<MetadataIndex>,
) -> Result<Value, CompileError> {
// XXX OK, now, the old compiler inlines everything very lazily. Function calls include
Expand Down Expand Up @@ -1104,10 +1110,18 @@ impl FnCompiler {
.into_iter()
.map(|(_, expr)| self.compile_expression(context, expr))
.collect::<Result<Vec<Value>, 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,
))
}
}

Expand Down Expand Up @@ -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());
}
}
Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/parse_tree/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ pub enum Expression {
type_span: Span,
span: Span,
},
BuiltinGenerateUid {
BuiltinGetStorageKey {
span: Span,
},
}
Expand Down Expand Up @@ -225,7 +225,7 @@ impl Expression {
StorageAccess { span, .. } => span,
SizeOfVal { span, .. } => span,
BuiltinGetTypeProperty { span, .. } => span,
BuiltinGenerateUid { span, .. } => span,
BuiltinGetStorageKey { span, .. } => span,
})
.clone()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl TypedExpression {
method,
None,
IsConstant::No,
None,
span,
)
}
Expand Down Expand Up @@ -141,7 +142,7 @@ impl TypedExpression {
| Literal(_)
| StorageAccess { .. }
| TypeProperty { .. }
| GenerateUid { .. }
| GetStorageKey { .. }
| VariableExpression { .. }
| FunctionParameter
| TupleElemAccess { .. } => false,
Expand Down Expand Up @@ -230,7 +231,7 @@ impl TypedExpression {
| TypedExpressionVariant::FunctionApplication { .. }
| TypedExpressionVariant::EnumTag { .. }
| TypedExpressionVariant::UnsafeDowncast { .. }
| TypedExpressionVariant::GenerateUid { .. } => vec![],
| TypedExpressionVariant::GetStorageKey { .. } => vec![],
}
}

Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -76,6 +77,7 @@ pub(crate) fn instantiate_function_application(
function_decl,
None,
IsConstant::No,
None,
span,
),
return err(warnings, errors),
Expand All @@ -85,13 +87,15 @@ 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<String, TypedExpression, RandomState>,
arguments: VecDeque<TypedExpression>,
function_decl: TypedFunctionDeclaration,
selector: Option<ContractCallMetadata>,
is_constant: IsConstant,
self_state_idx: Option<StateIndex>,
span: Span,
) -> CompileResult<TypedExpression> {
let args_and_names = function_decl
Expand All @@ -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,
Expand All @@ -119,6 +125,7 @@ fn instantiate_function_application_inner(
function_decl: TypedFunctionDeclaration,
selector: Option<ContractCallMetadata>,
is_constant: IsConstant,
self_state_idx: Option<StateIndex>,
span: Span,
) -> CompileResult<TypedExpression> {
let warnings = vec![];
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 443f42c

Please sign in to comment.