Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Nov 28, 2022
1 parent 06951f4 commit 7a5f2be
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 43 deletions.
12 changes: 12 additions & 0 deletions a.fe
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pub struct Field {
row: u8
column: u8
value: u8
}

pub struct Board {
state: Array<Array<Field, 4>, 4>
}

pub contract Foo {
}
4 changes: 2 additions & 2 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1691,13 +1691,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
39 changes: 27 additions & 12 deletions crates/codegen/src/db/queries/cgu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use fe_mir::ir::{
body_cursor::{BodyCursor, CursorLocation},
function::BodyDataStore,
inst::InstKind,
types::TypeParamDef,
FunctionBody, FunctionParam, FunctionSigId, FunctionSignature, InstId, TypeId, TypeKind,
ValueId,
};
Expand Down Expand Up @@ -139,15 +140,15 @@ impl<'db> CguFunctionBuilder<'db> {
store: &BodyDataStore,
inst: InstId,
) -> (FunctionSigId, FunctionBody) {
let InstKind::Call {func: callee, args, ..} = &store.inst_data(inst).kind else {
let InstKind::Call {func: callee, args, generic_type, ..} = &store.inst_data(inst).kind else {
panic!("expected a call instruction");
};
debug_assert!(callee.is_generic(self.db.upcast()));

let callee = *callee;
let subst = self.get_subst(store, callee, args);

let mono_sig = self.monomorphize_sig(callee, &subst);
let mono_sig = self.monomorphize_sig(callee, &subst, generic_type);
let mono_body = self.monomorphize_body(callee, &subst);

(self.db.mir_intern_function(mono_sig.into()), mono_body)
Expand All @@ -157,6 +158,7 @@ impl<'db> CguFunctionBuilder<'db> {
&self,
sig: FunctionSigId,
subst: &FxHashMap<SmolStr, TypeId>,
generic_type: &Option<TypeParamDef>,
) -> FunctionSignature {
let params = sig
.data(self.db.upcast())
Expand All @@ -176,10 +178,11 @@ impl<'db> CguFunctionBuilder<'db> {
})
.collect();

let return_type = sig.return_type(self.db.upcast()).clone();
let return_type = sig.return_type(self.db.upcast());
let module_id = sig.module(self.db.upcast());
let linkage = sig.linkage(self.db.upcast());
let analyzer_id = self.resolve_function(sig.analyzer_sig(self.db.upcast()), subst);
let analyzer_id =
self.resolve_function(sig.analyzer_sig(self.db.upcast()), subst, generic_type);

FunctionSignature {
name: self.mono_func_name(analyzer_id, subst),
Expand All @@ -204,12 +207,9 @@ impl<'db> CguFunctionBuilder<'db> {

let mut body = (*self.db.mir_lowered_func_body(func_id)).clone();
for value in body.store.values_mut() {
match &value.ty().data(self.db.upcast()).kind {
TypeKind::TypeParam(def) => {
let subst_ty = subst[&def.name];
*value.ty_mut() = subst_ty;
}
_ => {}
if let TypeKind::TypeParam(def) = &value.ty().data(self.db.upcast()).kind {
let subst_ty = subst[&def.name];
*value.ty_mut() = subst_ty;
}
}

Expand All @@ -222,21 +222,36 @@ impl<'db> CguFunctionBuilder<'db> {
&self,
callee: AnalyzerFuncSigId,
subst: &FxHashMap<SmolStr, TypeId>,
generic_type: &Option<TypeParamDef>,
) -> AnalyzerFuncSigId {
let trait_id = match callee.parent(self.db.upcast()) {
Item::Trait(id) => id,
_ => return callee,
};

todo!()
let concrete_type = subst[&generic_type.as_ref().unwrap().name];
let impl_ = concrete_type
.analyzer_ty(self.db.upcast())
.unwrap()
.get_impl_for(self.db.upcast(), trait_id)
.unwrap();

let resolved = impl_
.function(self.db.upcast(), &callee.name(self.db.upcast()))
.expect("missing function");
resolved.sig(self.db.upcast())
}

fn mono_func_name(
&self,
callee: AnalyzerFuncSigId,
subst: &FxHashMap<SmolStr, TypeId>,
) -> SmolStr {
todo!()
let mut func_name = callee.name(self.db.upcast()).to_string();
for ty in subst.values() {
func_name.push_str(&format!("_{}", ty.as_string(self.db.upcast())))
}
func_name.into()
}

fn get_subst(
Expand Down
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
44 changes: 23 additions & 21 deletions crates/codegen/src/yul/isel/contract.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand All @@ -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! {}
};
Expand Down Expand Up @@ -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
}
Expand All @@ -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]())
}
Expand Down Expand Up @@ -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::<Vec<_>>();

if arms.is_empty() {
Expand All @@ -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| {
Expand All @@ -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::<Vec<_>>())...])};
if let Some(mut return_type) = func_sig.return_type {
Expand Down Expand Up @@ -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] {
Expand All @@ -211,13 +213,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
1 change: 1 addition & 0 deletions crates/codegen/src/yul/isel/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ impl<'db, 'a> FuncLowerHelper<'db, 'a> {
func,
args,
call_type,
..
} => {
let args: Vec<_> = args.iter().map(|arg| self.value_expr(*arg)).collect();
let result = match call_type {
Expand Down
2 changes: 1 addition & 1 deletion crates/mir/src/lower/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn lower_func_signature(db: &dyn MirDb, func: analyzer_items::FunctionSigId)
};

let sig = FunctionSignature {
name: func.name(db.upcast()).clone(),
name: func.name(db.upcast()),
params,
return_type: Some(return_type),
module_id: func.module(db.upcast()),
Expand Down
6 changes: 3 additions & 3 deletions crates/mir/src/lower/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ pub fn lower_type(db: &dyn MirDb, analyzer_ty: analyzer_types::TypeId) -> TypeId
analyzer_types::Type::SelfContract(contract) => lower_contract(db, contract),
analyzer_types::Type::Struct(struct_) => lower_struct(db, struct_),
analyzer_types::Type::Enum(enum_) => lower_enum(db, enum_),
analyzer_types::Type::Generic(generic) => TypeKind::TypeParam(TypeParamDef {
name: generic.name.clone(),
}),
analyzer_types::Type::Generic(generic) => {
TypeKind::TypeParam(TypeParamDef { name: generic.name })
}
};

intern_type(db, ty_kind, Some(analyzer_ty.deref(db.upcast())))
Expand Down

0 comments on commit 7a5f2be

Please sign in to comment.