fe_codegen/yul/isel/
context.rs

1use indexmap::IndexSet;
2
3use fe_analyzer::namespace::items::ContractId;
4use fe_mir::ir::FunctionId;
5use fxhash::FxHashSet;
6use yultsur::yul;
7
8use crate::{
9    db::CodegenDb,
10    yul::runtime::{DefaultRuntimeProvider, RuntimeProvider},
11};
12
13use super::{lower_contract_deployable, lower_function};
14
15pub struct Context {
16    pub runtime: Box<dyn RuntimeProvider>,
17    pub(super) contract_dependency: IndexSet<ContractId>,
18    pub(super) function_dependency: IndexSet<FunctionId>,
19    pub(super) string_constants: IndexSet<String>,
20    pub(super) lowered_functions: FxHashSet<FunctionId>,
21}
22
23// Currently, `clippy::derivable_impls` causes false positive result,
24// see https://github.com/rust-lang/rust-clippy/issues/10158 for more details.
25#[allow(clippy::derivable_impls)]
26impl Default for Context {
27    fn default() -> Self {
28        Self {
29            runtime: Box::<DefaultRuntimeProvider>::default(),
30            contract_dependency: IndexSet::default(),
31            function_dependency: IndexSet::default(),
32            string_constants: IndexSet::default(),
33            lowered_functions: FxHashSet::default(),
34        }
35    }
36}
37
38impl Context {
39    pub(super) fn resolve_function_dependency(
40        &mut self,
41        db: &dyn CodegenDb,
42    ) -> Vec<yul::FunctionDefinition> {
43        let mut funcs = vec![];
44        loop {
45            let dependencies = std::mem::take(&mut self.function_dependency);
46            if dependencies.is_empty() {
47                break;
48            }
49            for dependency in dependencies {
50                if self.lowered_functions.contains(&dependency) {
51                    // Ignore dependency if it's already lowered.
52                    continue;
53                } else {
54                    funcs.push(lower_function(db, self, dependency))
55                }
56            }
57        }
58
59        funcs
60    }
61
62    pub(super) fn resolve_constant_dependency(&self, db: &dyn CodegenDb) -> Vec<yul::Data> {
63        self.string_constants
64            .iter()
65            .map(|s| {
66                let symbol = db.codegen_constant_string_symbol_name(s.to_string());
67                yul::Data {
68                    name: symbol.as_ref().clone(),
69                    value: s.to_string(),
70                }
71            })
72            .collect()
73    }
74
75    pub(super) fn resolve_contract_dependency(&self, db: &dyn CodegenDb) -> Vec<yul::Object> {
76        self.contract_dependency
77            .iter()
78            .map(|cid| lower_contract_deployable(db, *cid))
79            .collect()
80    }
81}