Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Dec 10, 2022
1 parent a239f2a commit 5ff56a1
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 69 deletions.
4 changes: 2 additions & 2 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1698,13 +1698,13 @@ fn expr_call_method(
vec!["Hint: rename one of the methods to disambiguate".into()],
);
let return_type = first.signature(context.db()).return_type.clone()?;
return Ok((
Ok((
ExpressionAttributes::new(return_type),
CallType::ValueMethod {
typ: obj_type,
sig: *first,
},
));
))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/codegen/src/db/queries/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn abi_function(db: &dyn CodegenDb, function: FunctionSigId) -> AbiFunction

// The "stateMutability" field is derived from the presence & mutability of
// `self` and `ctx` params in the analyzer fn sig.
let analyzer_sig = sig.analyzer_func_id.signature(db.upcast());
let analyzer_sig = sig.analyzer_id.signature(db.upcast());
let self_param = match analyzer_sig.self_decl {
None => SelfParam::None,
Some(SelfDecl { mut_: None, .. }) => SelfParam::Imm,
Expand Down
10 changes: 2 additions & 8 deletions crates/codegen/src/db/queries/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use std::rc::Rc;
use fe_analyzer::{
display::Displayable,
namespace::{
items::{FunctionId, Item},
items::Item,
types::{Type, TypeId},
},
};
use fe_mir::ir::{FunctionBody, FunctionSigId, FunctionSignature};
use fe_mir::ir::{FunctionSigId, FunctionSignature};
use salsa::InternKey;
use smol_str::SmolStr;

Expand All @@ -19,12 +19,6 @@ pub fn legalized_signature(db: &dyn CodegenDb, function: FunctionSigId) -> Rc<Fu
sig.into()
}

pub fn legalized_body(db: &dyn CodegenDb, func: FunctionId) -> Rc<FunctionBody> {
let mut body = (*db.mir_lowered_func_body(func)).clone();
legalize::legalize_func_body(db, &mut body);
body.into()
}

pub fn symbol_name(db: &dyn CodegenDb, function: FunctionSigId) -> Rc<String> {
let module = function.data(db.upcast()).module_id;
let module_name = module.name(db.upcast());
Expand Down
1 change: 1 addition & 0 deletions crates/codegen/src/yul/isel/call_graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

38 changes: 12 additions & 26 deletions crates/codegen/src/yul/isel/cgu.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use fe_mir::ir::FunctionSigId;
use indexmap::IndexMap;
use indexmap::{IndexMap, IndexSet};
use yultsur::yul;

use crate::{
cgu::CodegenUnit,
db::CodegenDb,
yul::runtime::{DefaultRuntimeProvider, RuntimeProvider},
yul::runtime::{DefaultRuntimeProvider, RuntimeFuncDepGraph, RuntimeProvider},
};

use super::lower_function;

pub(super) fn compile_cgu(db: &dyn CodegenDb, cgu: CodegenUnit) -> CompiledCgu {
let mut ctx = CguContext::default();
let mut ctx = CguLowerContext::default();
let mut functions = IndexMap::with_capacity(cgu.functions.len());
for func in cgu.functions {
let sig = func.sig;
Expand All @@ -20,50 +20,36 @@ pub(super) fn compile_cgu(db: &dyn CodegenDb, cgu: CodegenUnit) -> CompiledCgu {
}

let mut runtime_functions = IndexMap::default();

for func in ctx.runtime.collect_definitions() {
runtime_functions.insert(func.name.identifier.clone(), func);
}

CompiledCgu {
functions,
constants: ctx.string_constants,
runtime_functions,
runtime_funcs: runtime_functions,
}
}

pub(super) struct CompiledCgu {
functions: IndexMap<FunctionSigId, yul::FunctionDefinition>,
constants: IndexMap<String, yul::Data>,
runtime_functions: IndexMap<String, yul::FunctionDefinition>,
constants: IndexSet<yul::Data>,
runtime_funcs: IndexMap<String, yul::FunctionDefinition>,
runtime_func_dependencies: IndexMap<FunctionSigId, RuntimeFuncDepGraph>,
}

pub struct CguContext {
pub(super) struct CguLowerContext {
pub(super) runtime: Box<dyn RuntimeProvider>,
pub(super) string_constants: IndexMap<String, yul::Data>,
pub(super) string_constants: IndexSet<yul::Data>,
}

impl CguContext {
pub fn add_string_constant(&mut self, db: &dyn CodegenDb, s: &str) {
impl CguLowerContext {
pub(super) fn add_string_constant(&mut self, db: &dyn CodegenDb, s: &str) {
let symbol_name = db.codegen_constant_string_symbol_name(s.into());
if self.string_constants.contains_key(symbol_name.as_ref()) {
return;
}

let data = yul::Data {
name: symbol_name.as_ref().clone(),
value: s.to_string(),
};
self.string_constants
.insert(symbol_name.as_ref().clone(), data);
}
}

impl Default for CguContext {
fn default() -> Self {
Self {
runtime: Box::new(DefaultRuntimeProvider::default()),
string_constants: IndexMap::default(),
}
self.string_constants.insert(data);
}
}
16 changes: 12 additions & 4 deletions crates/codegen/src/yul/isel/context.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -15,9 +15,9 @@ use super::{lower_contract_deployable, lower_function};
pub struct Context {
pub runtime: Box<dyn RuntimeProvider>,
pub(super) contract_dependency: IndexSet<ContractId>,
pub(super) function_dependency: IndexSet<FunctionId>,
pub(super) string_constants: IndexSet<String>,
pub(super) lowered_functions: FxHashSet<FunctionId>,
pub(super) function_dependency: IndexSet<FunctionSigId>,
lowered_functions: FxHashSet<FunctionSigId>,
}

impl Default for Context {
Expand Down Expand Up @@ -48,7 +48,15 @@ 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())
.unwrap_or_else(|| {
panic!("`{}` is not defined", dependency.name(db.upcast()))
});
funcs.push(lower_function(db, self, dependency, func))
}
}
}
Expand Down
55 changes: 31 additions & 24 deletions crates/codegen/src/yul/isel/contract.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
use fe_analyzer::namespace::items::ContractId;
use fe_mir::ir::{function::Linkage, FunctionId};
use fe_analyzer::namespace::items::{ContractId, ModuleId};
use fe_mir::ir::{function::Linkage, FunctionSigId};
use fxhash::FxHashMap;
use yultsur::{yul, *};

use crate::{
db::CodegenDb,
yul::{runtime::AbiSrcLocation, YulVariable},
};

use super::context::Context;
use super::{cgu::CompiledCgu, context::Context};

pub fn lower_contract_deployable(db: &dyn CodegenDb, contract: ContractId) -> yul::Object {
pub fn lower_contract_deployable(
db: &dyn CodegenDb,
contract: ContractId,
cgus: &FxHashMap<ModuleId, CompiledCgu>,
) -> 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! {}
};
Expand Down Expand Up @@ -65,9 +71,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
}
Expand All @@ -76,9 +82,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]())
}
Expand Down Expand Up @@ -122,11 +129,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::<Vec<_>>();

if arms.is_empty() {
Expand All @@ -143,9 +150,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| {
Expand All @@ -165,7 +172,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::<Vec<_>>())...])};
if let Some(mut return_type) = func_sig.return_type {
Expand Down Expand Up @@ -197,7 +204,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] {
Expand All @@ -211,13 +218,13 @@ fn make_init(
db: &dyn CodegenDb,
context: &mut Context,
contract: ContractId,
init: FunctionId,
init_sig: FunctionSigId,
) -> Vec<yul::Statement> {
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");
Expand Down
8 changes: 4 additions & 4 deletions crates/codegen/src/yul/isel/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(unused)]
use std::thread::Scope;

use super::cgu::CguContext;
use super::cgu::CguLowerContext;
use super::{context::Context, inst_order::InstSerializer};
use fe_analyzer::namespace::items::FunctionId;
use fe_common::numeric::to_hex_str;
Expand Down Expand Up @@ -40,7 +40,7 @@ use crate::{

pub fn lower_function(
db: &dyn CodegenDb,
ctx: &mut CguContext,
ctx: &mut CguLowerContext,
func: CguFunction,
) -> yul::FunctionDefinition {
let sig_data = &db.codegen_legalized_signature(func.sig);
Expand All @@ -51,7 +51,7 @@ pub fn lower_function(

struct FuncLowerHelper<'db, 'a> {
db: &'db dyn CodegenDb,
ctx: &'a mut CguContext,
ctx: &'a mut CguLowerContext,
value_map: ScopedValueMap,
sig_id: FunctionSigId,
sig: &'a FunctionSignature,
Expand All @@ -63,7 +63,7 @@ struct FuncLowerHelper<'db, 'a> {
impl<'db, 'a> FuncLowerHelper<'db, 'a> {
fn new(
db: &'db dyn CodegenDb,
ctx: &'a mut CguContext,
ctx: &'a mut CguLowerContext,
sig_id: FunctionSigId,
sig: &'a FunctionSignature,
body: &'a FunctionBody,
Expand Down
1 change: 1 addition & 0 deletions crates/codegen/src/yul/isel/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod context;

mod call_graph;
mod cgu;
mod contract;
mod function;
Expand Down

0 comments on commit 5ff56a1

Please sign in to comment.