From 839cea92dd251899dedf7d28f31d67009561a835 Mon Sep 17 00:00:00 2001 From: Yoshitomo Nakanishi Date: Mon, 28 Nov 2022 03:00:59 +0100 Subject: [PATCH] wip --- crates/codegen/src/yul/isel/context.rs | 17 +++++++--- crates/codegen/src/yul/isel/contract.rs | 44 +++++++++++++------------ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/crates/codegen/src/yul/isel/context.rs b/crates/codegen/src/yul/isel/context.rs index fea327aa18..cca00ba8cd 100644 --- a/crates/codegen/src/yul/isel/context.rs +++ b/crates/codegen/src/yul/isel/context.rs @@ -1,7 +1,7 @@ +use fe_mir::ir::FunctionSigId; use indexmap::IndexSet; use fe_analyzer::namespace::items::ContractId; -use fe_mir::ir::FunctionId; use fxhash::FxHashSet; use yultsur::yul; @@ -15,9 +15,9 @@ use super::{lower_contract_deployable, lower_function}; pub struct Context { pub runtime: Box, pub(super) contract_dependency: IndexSet, - pub(super) function_dependency: IndexSet, pub(super) string_constants: IndexSet, - pub(super) lowered_functions: FxHashSet, + pub(super) function_dependency: IndexSet, + lowered_functions: FxHashSet, } impl Default for Context { @@ -48,7 +48,16 @@ impl Context { // Ignore dependency if it's already lowered. continue; } else { - funcs.push(lower_function(db, self, dependency)) + // Intrinsic functions are already inlined in the legalization phase. + // TODO: Add linker to allow linking to external functions. + let func = dependency + .analyzer_sig(db.upcast()) + .function(db.upcast()) + .expect(&format!( + "`{}` is not defined", + dependency.name(db.upcast()) + )); + funcs.push(lower_function(db, self, dependency, func)) } } } diff --git a/crates/codegen/src/yul/isel/contract.rs b/crates/codegen/src/yul/isel/contract.rs index 3703381d8e..3b8516dc9d 100644 --- a/crates/codegen/src/yul/isel/contract.rs +++ b/crates/codegen/src/yul/isel/contract.rs @@ -1,5 +1,5 @@ use fe_analyzer::namespace::items::ContractId; -use fe_mir::ir::{function::Linkage, FunctionId}; +use fe_mir::ir::{function::Linkage, FunctionSigId}; use yultsur::{yul, *}; use crate::{ @@ -12,9 +12,10 @@ use super::context::Context; pub fn lower_contract_deployable(db: &dyn CodegenDb, contract: ContractId) -> yul::Object { let mut context = Context::default(); - let constructor = if let Some(init) = contract.init_function(db.upcast()) { - let init = db.mir_lowered_func_signature(init); - make_init(db, &mut context, contract, init) + let constructor = if let Some(init_func) = contract.init_function(db.upcast()) { + let init_sig = init_func.sig(db.upcast()); + let init_sig = db.mir_lowered_func_signature(init_sig); + make_init(db, &mut context, contract, init_sig) } else { statements! {} }; @@ -65,9 +66,9 @@ pub fn lower_contract(db: &dyn CodegenDb, contract: ContractId) -> yul::Object { let exported_funcs: Vec<_> = db .mir_lower_contract_all_functions(contract) .iter() - .filter_map(|fid| { - if fid.signature(db.upcast()).linkage == Linkage::Export { - Some(*fid) + .filter_map(|(sig, _)| { + if sig.linkage(db.upcast()) == Linkage::Export { + Some(*sig) } else { None } @@ -76,9 +77,10 @@ pub fn lower_contract(db: &dyn CodegenDb, contract: ContractId) -> yul::Object { let mut context = Context::default(); let dispatcher = if let Some(call_fn) = contract.call_function(db.upcast()) { - let call_fn = db.mir_lowered_func_signature(call_fn); - context.function_dependency.insert(call_fn); - let call_symbol = identifier! { (db.codegen_function_symbol_name(call_fn)) }; + let call_fn_sig = call_fn.sig(db.upcast()); + let call_fn_sig = db.mir_lowered_func_signature(call_fn_sig); + context.function_dependency.insert(call_fn_sig); + let call_symbol = identifier! { (db.codegen_function_symbol_name(call_fn_sig)) }; statement! { ([call_symbol]()) } @@ -122,11 +124,11 @@ pub fn lower_contract(db: &dyn CodegenDb, contract: ContractId) -> yul::Object { fn make_dispatcher( db: &dyn CodegenDb, context: &mut Context, - funcs: &[FunctionId], + funcs: &[FunctionSigId], ) -> yul::Statement { let arms = funcs .iter() - .map(|func| dispatch_arm(db, context, *func)) + .map(|sig| dispatch_arm(db, context, *sig)) .collect::>(); if arms.is_empty() { @@ -143,9 +145,9 @@ fn make_dispatcher( } } -fn dispatch_arm(db: &dyn CodegenDb, context: &mut Context, func: FunctionId) -> yul::Case { - context.function_dependency.insert(func); - let func_sig = db.codegen_legalized_signature(func); +fn dispatch_arm(db: &dyn CodegenDb, context: &mut Context, sig: FunctionSigId) -> yul::Case { + context.function_dependency.insert(sig); + let func_sig = db.codegen_legalized_signature(sig); let mut param_vars = Vec::with_capacity(func_sig.params.len()); let mut param_tys = Vec::with_capacity(func_sig.params.len()); func_sig.params.iter().for_each(|param| { @@ -165,7 +167,7 @@ fn dispatch_arm(db: &dyn CodegenDb, context: &mut Context, func: FunctionId) -> }; let call_and_encode_return = { - let name = identifier! { (db.codegen_function_symbol_name(func)) }; + let name = identifier! { (db.codegen_function_symbol_name(sig)) }; // we pass in a `0` for the expected `Context` argument let call = expression! {[name]([(param_vars.iter().map(YulVariable::expr).collect::>())...])}; if let Some(mut return_type) = func_sig.return_type { @@ -197,7 +199,7 @@ fn dispatch_arm(db: &dyn CodegenDb, context: &mut Context, func: FunctionId) -> } }; - let abi_sig = db.codegen_abi_function(func); + let abi_sig = db.codegen_abi_function(sig); let selector = literal! { (format!("0x{}", abi_sig.selector().hex())) }; case! { case [selector] { @@ -211,13 +213,13 @@ fn make_init( db: &dyn CodegenDb, context: &mut Context, contract: ContractId, - init: FunctionId, + init_sig: FunctionSigId, ) -> Vec { - context.function_dependency.insert(init); - let init_func_name = identifier! { (db.codegen_function_symbol_name(init)) }; + context.function_dependency.insert(init_sig); + let init_func_name = identifier! { (db.codegen_function_symbol_name(init_sig)) }; let contract_name = identifier_expression! { (format!{r#""{}""#, db.codegen_contract_deployer_symbol_name(contract)}) }; - let func_sig = db.codegen_legalized_signature(init); + let func_sig = db.codegen_legalized_signature(init_sig); let mut param_vars = Vec::with_capacity(func_sig.params.len()); let mut param_tys = Vec::with_capacity(func_sig.params.len()); let program_size = YulVariable::new("$program_size");