Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
sbillig committed Aug 31, 2022
1 parent 7cc8015 commit 2532bbf
Show file tree
Hide file tree
Showing 167 changed files with 1,584 additions and 320 deletions.
244 changes: 132 additions & 112 deletions crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap

Large diffs are not rendered by default.

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 @@ -196,11 +196,11 @@ pub fn abi_type(db: &dyn CodegenDb, ty: TypeId) -> AbiType {

AbiType::Tuple(fields)
}
ir::TypeKind::MPtr(inner) => db.codegen_abi_type(*inner),

ir::TypeKind::Event(_)
| ir::TypeKind::Contract(_)
| ir::TypeKind::Map(_)
| ir::TypeKind::MPtr(_)
| ir::TypeKind::SPtr(_) => unreachable!(),
}
}
Expand Down
6 changes: 5 additions & 1 deletion crates/codegen/src/yul/legalize/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,10 @@ fn make_zst_ptr(db: &dyn CodegenDb, ty: TypeId) -> Value {

/// Returns `true` if a value has a zero sized type.
fn is_value_zst(db: &dyn CodegenDb, body: &FunctionBody, value: ValueId) -> bool {
body.store.value_ty(value).is_zero_sized(db.upcast())
body.store
.value_ty(value)
.deref(db.upcast())
.is_zero_sized(db.upcast()) // XXX deref?
}

fn is_value_contract(db: &dyn CodegenDb, body: &FunctionBody, value: ValueId) -> bool {
Expand All @@ -198,5 +201,6 @@ fn is_value_contract(db: &dyn CodegenDb, body: &FunctionBody, value: ValueId) ->
fn is_lvalue_zst(db: &dyn CodegenDb, body: &FunctionBody, lvalue: &AssignableValue) -> bool {
lvalue
.ty(db.upcast(), &body.store)
.deref(db.upcast())
.is_zero_sized(db.upcast())
}
10 changes: 6 additions & 4 deletions crates/codegen/src/yul/legalize/signature.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use fe_mir::ir::FunctionSignature;
use fe_mir::ir::{FunctionSignature, TypeKind};

use crate::db::CodegenDb;

pub fn legalize_func_signature(db: &dyn CodegenDb, sig: &mut FunctionSignature) {
// Remove param if the type is contract or zero-sized.
let params = &mut sig.params;
params
.retain(|param| !param.ty.is_contract(db.upcast()) && !param.ty.is_zero_sized(db.upcast()));
params.retain(|param| match param.ty.data(db.upcast()).kind {
TypeKind::Contract(_) => false,
_ => !param.ty.deref(db.upcast()).is_zero_sized(db.upcast()),
});

// Legalize param types.
for param in params.iter_mut() {
Expand All @@ -15,7 +17,7 @@ pub fn legalize_func_signature(db: &dyn CodegenDb, sig: &mut FunctionSignature)

if let Some(ret_ty) = sig.return_type {
// Remove return type if the type is contract or zero-sized.
if ret_ty.is_contract(db.upcast()) || ret_ty.is_zero_sized(db.upcast()) {
if ret_ty.is_contract(db.upcast()) || ret_ty.deref(db.upcast()).is_zero_sized(db.upcast()) {
sig.return_type = None;
} else {
// Legalize param types.
Expand Down
6 changes: 3 additions & 3 deletions crates/mir/src/db/queries/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ impl TypeId {
}

pub fn deref(self, db: &dyn MirDb) -> TypeId {
match &self.data(db).kind {
TypeKind::SPtr(inner) => *inner,
TypeKind::MPtr(inner) => *inner,
match self.data(db).kind {
TypeKind::SPtr(inner) => inner,
TypeKind::MPtr(inner) => inner.deref(db),
_ => self,
}
}
Expand Down
23 changes: 18 additions & 5 deletions crates/mir/src/lower/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,18 +731,31 @@ impl<'db, 'a> BodyLowerHelper<'db, 'a> {

for into_ty in &self.analyzer_body.expressions[&expr.id].type_coercion_chain {
let into_ty = self.lower_analyzer_type(*into_ty);
if expr_ty == into_ty {
// meaningless mut unwrap

// XXX typeid equality is broken by differing analyzer types
if expr_ty.data(self.db).kind == into_ty.data(self.db).kind {
// `Mut` type unwrapping that was already handled in `lower_type`
continue;
}

eprintln!(
"{}: {} -> {}",
expr.kind,
expr_ty.as_string(self.db),
into_ty.as_string(self.db)
);

// XXX blah
let tmp = self.map_to_tmp(inst, expr_ty);
if expr_ty.is_ptr(self.db) && !into_ty.is_ptr(self.db) {
inst = self.builder.load(tmp, expr.into());
} else if expr_ty.is_string(self.db) {
if into_ty.is_primitive(self.db) {
inst = self.builder.load(tmp, expr.into());
} else {
inst = self.builder.mem_copy(tmp, expr.into());
}
} else if expr_ty.deref(self.db).is_string(self.db) {
// XXX handle string size difference
} else {
dbg!(expr_ty.as_string(self.db), into_ty.as_string(self.db));
inst = self.builder.cast(tmp, into_ty, expr.into());
}
expr_ty = into_ty;
Expand Down
12 changes: 8 additions & 4 deletions crates/mir/src/lower/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ use fe_analyzer::namespace::{items as analyzer_items, types as analyzer_types};
pub fn lower_type(db: &dyn MirDb, analyzer_ty: analyzer_types::TypeId) -> TypeId {
let ty_kind = match analyzer_ty.typ(db.upcast()) {
analyzer_types::Type::SPtr(inner) => TypeKind::SPtr(lower_type(db, inner)),
analyzer_types::Type::Mut(inner) => {
// XXX lower to MPtr
return lower_type(db, inner);
}
// XXX this results in unexpected MIR TypeId inequalities
// (when different analyzer types map to the same MIR type)
analyzer_types::Type::Mut(inner) => match inner.typ(db.upcast()) {
analyzer_types::Type::SPtr(t) => TypeKind::SPtr(lower_type(db, t)),
analyzer_types::Type::Base(t) => lower_base(t),
analyzer_types::Type::Contract(_) => TypeKind::Address,
_ => TypeKind::MPtr(lower_type(db, inner)),
},
analyzer_types::Type::Base(base) => lower_base(base),
analyzer_types::Type::Array(arr) => lower_array(db, &arr),
analyzer_types::Type::Map(map) => lower_map(db, &map),
Expand Down
122 changes: 122 additions & 0 deletions crates/parser/tests/cases/snapshots/cases__print_ast__erc20.snap.new
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
source: crates/parser/tests/cases/print_ast.rs
expression: "parse_and_print(\"demos/erc20_token.fe\", src)"

---
contract ERC20 {
_balances: Map<address, u256>
_allowances: Map<address, Map<address, u256>>
_total_supply: u256
_name: String<100>
_symbol: String<100>
_decimals: u8

event Approval {
idx owner: address
idx spender: address
value: u256
}

event Transfer {
idx from: address
idx to: address
value: u256
}

pub fn __init__(mut self, mut ctx: Context, name: String<100>, symbol: String<100>) {
self._name = name
self._symbol = symbol
self._decimals = u8(18)
self._mint(ctx, account: ctx.msg_sender(), value: 1000_000_000_000_000_000_000_000)
}

pub fn name(self) -> String<100> {
return self._name.to_mem()
}

pub fn symbol(self) -> String<100> {
return self._symbol.to_mem()
}

pub fn decimals(self) -> u8 {
return self._decimals
}

pub fn totalSupply(self) -> u256 {
return self._total_supply
}

pub fn balanceOf(self, _ account: address) -> u256 {
return self._balances[account]
}

pub fn transfer(mut self, mut ctx: Context, recipient: address, value: u256) -> bool {
self._transfer(ctx, sender: ctx.msg_sender(), recipient, value)
return true
}

pub fn allowance(self, owner: address, spender: address) -> u256 {
return self._allowances[owner][spender]
}

pub fn approve(mut self, mut ctx: Context, spender: address, value: u256) -> bool {
self._approve(ctx, owner: ctx.msg_sender(), spender, value)
return true
}

pub fn transferFrom(mut self, mut ctx: Context, sender: address, recipient: address, value: u256) -> bool {
assert self._allowances[sender][ctx.msg_sender()] >= value
self._transfer(ctx, sender, recipient, value)
self._approve(ctx, owner: sender, spender: ctx.msg_sender(), value: self._allowances[sender][ctx.msg_sender()] - value)
return true
}

pub fn increaseAllowance(mut self, mut ctx: Context, spender: address, addedValue: u256) -> bool {
self._approve(ctx, owner: ctx.msg_sender(), spender, value: self._allowances[ctx.msg_sender()][spender] + addedValue)
return true
}

pub fn decreaseAllowance(mut self, mut ctx: Context, spender: address, subtractedValue: u256) -> bool {
self._approve(ctx, owner: ctx.msg_sender(), spender, value: self._allowances[ctx.msg_sender()][spender] - subtractedValue)
return true
}

fn _transfer(mut self, mut ctx: Context, sender: address, recipient: address, value: u256) {
assert sender != address(0)
assert recipient != address(0)
_before_token_transfer(from: sender, to: recipient, value)
self._balances[sender] = self._balances[sender] - value
self._balances[recipient] = self._balances[recipient] + value
emit Transfer(ctx, from: sender, to: recipient, value)
}

fn _mint(mut self, mut ctx: Context, account: address, value: u256) {
assert account != address(0)
_before_token_transfer(from: address(0), to: account, value)
self._total_supply = self._total_supply + value
self._balances[account] = self._balances[account] + value
emit Transfer(ctx, from: address(0), to: account, value)
}

fn _burn(mut self, mut ctx: Context, account: address, value: u256) {
assert account != address(0)
_before_token_transfer(from: account, to: address(0), value)
self._balances[account] = self._balances[account] - value
self._total_supply = self._total_supply - value
emit Transfer(ctx, from: account, to: address(0), value)
}

fn _approve(mut self, mut ctx: Context, owner: address, spender: address, value: u256) {
assert owner != address(0)
assert spender != address(0)
self._allowances[owner][spender] = value
emit Approval(ctx, owner, spender, value)
}

fn _setup_decimals(mut self, _ decimals_: u8) {
self._decimals = decimals_
}

fn _before_token_transfer(from: address, to: address, _ value: u256) {}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: crates/parser/tests/cases/print_ast.rs
expression: "parse_and_print(\"demos/guest_book.fe\", src)"

---
contract GuestBook {
messages: Map<address, String<100>>

event Signed {
book_msg: String<100>
}

pub fn sign(mut self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
emit Signed(ctx, book_msg)
}

pub fn get_msg(self, addr: address) -> String<100> {
return self.messages[addr].to_mem()
}
}

11 changes: 6 additions & 5 deletions crates/test-files/fixtures/stress/data_copying_stress.fe
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ contract Foo {
self.my_u256 = self.my_other_u256
}

// XXX change this
pub fn multiple_references_shared_memory(mut my_array: Array<u256, 10>) {
let my_2nd_array: Array<u256, 10> = my_array
let mut my_3rd_array: Array<u256, 10> = my_2nd_array

assert my_array[3] != 5
my_array[3] = 5
assert my_array[3] == 5
assert my_2nd_array[3] == 5
assert my_3rd_array[3] == 5
assert my_2nd_array[3] != 5
assert my_3rd_array[3] != 5
my_3rd_array[3] = 50
assert my_array[3] == 50
assert my_2nd_array[3] == 50
assert my_array[3] == 5
assert my_2nd_array[3] == 5
assert my_3rd_array[3] == 50
}

Expand All @@ -51,6 +51,7 @@ contract Foo {
pub fn clone_mutate_and_return(my_array: Array<u256, 10>) -> Array<u256, 10> {
let mut a: Array<u256, 10> = my_array
a[3] = 5
assert my_array[3] != 5
return my_array
}

Expand Down
Loading

0 comments on commit 2532bbf

Please sign in to comment.