Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions etk-asm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
mod error {
use crate::ops::Expression;
use crate::ParseError;
use etk_ops::cancun::Op;
use etk_ops::prague::Op;
use num_bigint::BigInt;
use snafu::{Backtrace, Snafu};

Expand Down Expand Up @@ -132,7 +132,7 @@ mod error {
pub use self::error::Error;
use crate::ops::expression::{self, Terminal};
use crate::ops::{self, AbstractOp, Assemble, Expression, Imm, MacroDefinition};
use etk_ops::cancun::Op;
use etk_ops::prague::Op;
use rand::Rng;
use snafu::OptionExt;
use std::collections::{hash_map, HashMap, HashSet, VecDeque};
Expand Down Expand Up @@ -185,7 +185,7 @@ impl From<Vec<u8>> for RawOp {
/// ```rust
/// use etk_asm::asm::Assembler;
/// use etk_asm::ops::AbstractOp;
/// use etk_ops::cancun::{Op, GetPc};
/// use etk_ops::prague::{Op, GetPc};
/// # use etk_asm::asm::Error;
/// #
/// # use hex_literal::hex;
Expand Down Expand Up @@ -711,7 +711,7 @@ mod tests {
InstructionMacroDefinition, InstructionMacroInvocation, Terminal,
};
use assert_matches::assert_matches;
use etk_ops::cancun::*;
use etk_ops::prague::*;
use hex_literal::hex;
use num_bigint::{BigInt, Sign};

Expand Down
2 changes: 1 addition & 1 deletion etk-asm/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::ops::{Abstract, AbstractOp, ExpressionMacroDefinition, InstructionMacroDefinition};
use etk_ops::cancun::Op;
use etk_ops::prague::Op;
use std::path::PathBuf;

#[derive(Debug, Clone, PartialEq)]
Expand Down
6 changes: 3 additions & 3 deletions etk-asm/src/disasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod error {
}
}

use etk_ops::cancun::Op;
use etk_ops::prague::Op;

pub use self::error::Error;

Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'a> Iterator for Iter<'a> {
///
/// ## Example
/// ```rust
/// use etk_ops::cancun::{Op, GetPc, Stop};
/// use etk_ops::prague::{Op, GetPc, Stop};
/// use etk_asm::disasm::Disassembler;
/// # use etk_asm::disasm::Offset;
///
Expand Down Expand Up @@ -158,7 +158,7 @@ impl Disassembler {

#[cfg(test)]
mod tests {
use etk_ops::cancun::*;
use etk_ops::prague::*;

use hex_literal::hex;

Expand Down
4 changes: 2 additions & 2 deletions etk-asm/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

mod error {
use super::expression;
use etk_ops::cancun::Op;
use etk_ops::prague::Op;
use num_bigint::BigInt;
use snafu::{Backtrace, Snafu};

Expand Down Expand Up @@ -43,7 +43,7 @@ mod types;

pub(crate) use self::error::Error;

use etk_ops::cancun::{Op, Operation, Push32};
use etk_ops::prague::{Op, Operation, Push32};

pub use self::error::UnknownSpecifierError;
pub use self::expression::{Context, Expression, Terminal};
Expand Down
9 changes: 7 additions & 2 deletions etk-asm/src/parse/asm.pest
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
///////////////////////
program = _{ SOI ~ inner ~ EOI }
inner = _{ NEWLINE* ~ (stmt ~ (NEWLINE+|";"))* ~ stmt? }
stmt = _{ label_definition | builtin | local_macro | push | op }
stmt = _{ label_definition | builtin | local_macro | push | op | relative_jump }

//////////////////////
// opcode mnemonics //
Expand All @@ -21,13 +21,18 @@ op = @{
"jumpi" | "jump" | "pc" | "msize" | "gas" | swap | dup | log |
"create2" | "callcode" | "call" | "return" | "delegatecall" | "create" |
"staticcall" | "revert" | "selfdestruct" | "byte" | "chainid" | "selfbalance" |
"basefee" | "invalid" | "push0" | "mcopy"
"basefee" | "invalid" | "push0" | "mcopy"
}
push = ${ "push" ~ word_size ~ WHITESPACE ~ expression }
swap = @{ "swap" ~ half_word_size }
dup = @{ "dup" ~ half_word_size }
log = @{ "log" ~ '0'..'4' }

relative_jump = { rjump | rjumpi | rjumpv }
rjump = ${ "rjump" ~ WHITESPACE ~ expression }
rjumpi = ${ "rjumpi" ~ WHITESPACE ~ expression }
rjumpv = ${ "rjumpv" ~ WHITESPACE ~ expression }

word_size = @{ ('1'..'2' ~ '0'..'9') | ("3" ~ '0'..'2') | '1'..'9' }
half_word_size = @{ ("1" ~ '0'..'6') | '1'..'9' }

Expand Down
38 changes: 36 additions & 2 deletions etk-asm/src/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use self::{
};
use crate::ast::Node;
use crate::ops::AbstractOp;
use etk_ops::cancun::Op;
use etk_ops::prague::{Op, RJump, RJumpI, RJumpV};
use num_bigint::BigInt;
use pest::{iterators::Pair, Parser};

Expand All @@ -48,6 +48,7 @@ fn parse_abstract_op(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
AbstractOp::Label(pair.into_inner().next().unwrap().as_str().to_string())
}
Rule::push => parse_push(pair)?,
Rule::relative_jump => parse_relative_jump(pair)?,
Rule::op => {
let spec: Op<()> = pair.as_str().parse().unwrap();
let op = Op::new(spec).unwrap();
Expand Down Expand Up @@ -78,6 +79,23 @@ fn parse_push(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
Ok(AbstractOp::Op(spec.with(expr).unwrap()))
}

fn parse_relative_jump(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
let pair = pair.into_inner().next().unwrap();

let mut inner_pair = pair.clone().into_inner();
let operand = inner_pair.next().unwrap();
let expr = expression::parse(operand)?;

let spec = match pair.as_rule() {
Rule::rjump => Op::RJump(RJump(expr.try_into().unwrap())),
Rule::rjumpi => Op::RJumpI(RJumpI(expr.try_into().unwrap())),
Rule::rjumpv => Op::RJumpV(RJumpV(expr.try_into().unwrap())),
_ => unreachable!(),
};

Ok(AbstractOp::Op(spec))
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -86,7 +104,7 @@ mod tests {
InstructionMacroDefinition, InstructionMacroInvocation, Terminal,
};
use assert_matches::assert_matches;
use etk_ops::cancun::*;
use etk_ops::prague::*;
use hex_literal::hex;
use num_bigint::Sign;
use std::path::PathBuf;
Expand Down Expand Up @@ -596,4 +614,20 @@ mod tests {
];
assert_eq!(parse_asm(&asm).unwrap(), expected);
}

#[test]
fn parse_relative_jumps() {
let asm = r#"
rjump 1
rjumpi 2
rjumpv 3
"#;

let expected = nodes![
Op::from(RJump(Imm::from(1u8))),
Op::from(RJumpI(Imm::from(2u8))),
Op::from(RJumpV(Imm::from(3u8))),
];
assert_matches!(parse_asm(asm), Ok(e) if e == expected);
}
}
4 changes: 4 additions & 0 deletions etk-asm/tests/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ fn every_op() -> Result<(), Error> {
a3
a4

e0 aabbccddeeff00112233445566778899
e1 aabbccddeeff00112233445566778899
e2 aabbccddeeff00112233445566778899

f0
f1
f2
Expand Down
4 changes: 4 additions & 0 deletions etk-asm/tests/asm/every-op/main.etk
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ log2
log3
log4

rjump 0xAABBCCDDEEFF00112233445566778899
rjumpi 0xAABBCCDDEEFF00112233445566778899
rjumpv 0xAABBCCDDEEFF00112233445566778899

create
call
callcode
Expand Down
4 changes: 2 additions & 2 deletions etk-dasm/src/bin/disease/selectors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use etk_4byte::reverse_selector;

use etk_ops::cancun::{Op, Operation};
use etk_ops::prague::{Op, Operation};

use std::fmt;

Expand Down Expand Up @@ -69,7 +69,7 @@ impl fmt::Display for DisplayOp {

#[cfg(test)]
mod tests {
use etk_ops::cancun::*;
use etk_ops::prague::*;

use hex_literal::hex;

Expand Down
41 changes: 37 additions & 4 deletions etk-dasm/src/blocks/annotated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! (ie. stack/memory/storage).
use crate::sym::{Expr, Var};

use etk_ops::cancun::*;
use etk_ops::prague::*;

use std::collections::VecDeque;

Expand Down Expand Up @@ -659,6 +659,42 @@ impl<'a> Annotator<'a> {
let _topic3 = stack.pop();
}

Op::RJump(RJump(imm)) => {
let dest = Expr::pc(pc as u16).add(&Expr::constant(imm));
return Some(Exit::Unconditional(dest));
}

Op::RJumpI(RJumpI(imm)) => {
let when_false = pc + 1;
let when_true = Expr::pc(pc as u16).add(&Expr::constant(imm));
let condition = stack.pop();
return Some(Exit::Branch {
when_false,
when_true,
condition,
});
}

Op::RJumpV(RJumpV(imm)) => {
let max_index = &Expr::constant(&imm[0..8]);
let relative_offset = &Expr::constant(&imm[8..16]);

let case = stack.pop();

let when_false = pc + 1;

let table_position = case.mul(&Expr::constant([32])); // case as postition in table
let relative_jump = table_position.add(relative_offset); // relative_offset[case]
let when_true = relative_jump.add(&Expr::pc(pc as u16)); // pc + relative_offset[case]

let condition = Expr::gt(&case, max_index);
return Some(Exit::Branch {
when_false,
when_true,
condition,
});
}

Op::Swap1(_) => stack.swap(1),
Op::Swap2(_) => stack.swap(2),
Op::Swap3(_) => stack.swap(3),
Expand Down Expand Up @@ -880,9 +916,6 @@ impl<'a> Annotator<'a> {
| Op::InvalidDd(_)
| Op::InvalidDe(_)
| Op::InvalidDf(_)
| Op::InvalidE0(_)
| Op::InvalidE1(_)
| Op::InvalidE2(_)
| Op::InvalidE3(_)
| Op::InvalidE4(_)
| Op::InvalidE5(_)
Expand Down
4 changes: 2 additions & 2 deletions etk-dasm/src/blocks/basic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! A list of EVM instructions with a single point of entry and a single exit.
use etk_asm::disasm::Offset;

use etk_ops::cancun::{Op, Operation};
use etk_ops::prague::{Op, Operation};

/// A list of EVM instructions with a single point of entry and a single exit.
#[derive(Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -107,7 +107,7 @@ impl Separator {

#[cfg(test)]
mod tests {
use etk_ops::cancun::*;
use etk_ops::prague::*;

use super::*;

Expand Down
44 changes: 10 additions & 34 deletions etk-ops/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ fn generate_fork(fork_name: &str) -> Result<(), Error> {
let mut immediate_mut_matches = quote! {};
let mut into_immediate_matches = quote! {};
let names: Vec<_> = ops.iter().map(|(n, _)| format_ident!("{}", n)).collect();
let immediate_ops: Vec<_> = ops
.iter()
.filter(|(_, op)| op.extra_len > 0)
.map(|(n, _)| format_ident!("{}", n))
.collect();

for (name, op) in &ops {
let name = format_ident!("{}", name);
Expand Down Expand Up @@ -680,41 +685,11 @@ fn generate_fork(fork_name: &str) -> Result<(), Error> {
T: ?Sized + super::Immediates,
#(I: TryInto<T::#bounds, Error = E>,)*
{
// TODO: Automate generating these?
let result = match self {
Self::Push1(_) => Op::Push1(Push1(immediate.try_into()?)),
Self::Push2(_) => Op::Push2(Push2(immediate.try_into()?)),
Self::Push3(_) => Op::Push3(Push3(immediate.try_into()?)),
Self::Push4(_) => Op::Push4(Push4(immediate.try_into()?)),
Self::Push5(_) => Op::Push5(Push5(immediate.try_into()?)),
Self::Push6(_) => Op::Push6(Push6(immediate.try_into()?)),
Self::Push7(_) => Op::Push7(Push7(immediate.try_into()?)),
Self::Push8(_) => Op::Push8(Push8(immediate.try_into()?)),
Self::Push9(_) => Op::Push9(Push9(immediate.try_into()?)),
Self::Push10(_) => Op::Push10(Push10(immediate.try_into()?)),
Self::Push11(_) => Op::Push11(Push11(immediate.try_into()?)),
Self::Push12(_) => Op::Push12(Push12(immediate.try_into()?)),
Self::Push13(_) => Op::Push13(Push13(immediate.try_into()?)),
Self::Push14(_) => Op::Push14(Push14(immediate.try_into()?)),
Self::Push15(_) => Op::Push15(Push15(immediate.try_into()?)),
Self::Push16(_) => Op::Push16(Push16(immediate.try_into()?)),
Self::Push17(_) => Op::Push17(Push17(immediate.try_into()?)),
Self::Push18(_) => Op::Push18(Push18(immediate.try_into()?)),
Self::Push19(_) => Op::Push19(Push19(immediate.try_into()?)),
Self::Push20(_) => Op::Push20(Push20(immediate.try_into()?)),
Self::Push21(_) => Op::Push21(Push21(immediate.try_into()?)),
Self::Push22(_) => Op::Push22(Push22(immediate.try_into()?)),
Self::Push23(_) => Op::Push23(Push23(immediate.try_into()?)),
Self::Push24(_) => Op::Push24(Push24(immediate.try_into()?)),
Self::Push25(_) => Op::Push25(Push25(immediate.try_into()?)),
Self::Push26(_) => Op::Push26(Push26(immediate.try_into()?)),
Self::Push27(_) => Op::Push27(Push27(immediate.try_into()?)),
Self::Push28(_) => Op::Push28(Push28(immediate.try_into()?)),
Self::Push29(_) => Op::Push29(Push29(immediate.try_into()?)),
Self::Push30(_) => Op::Push30(Push30(immediate.try_into()?)),
Self::Push31(_) => Op::Push31(Push31(immediate.try_into()?)),
Self::Push32(_) => Op::Push32(Push32(immediate.try_into()?)),
_ => panic!("only push operations can be combined"),
#(
Self::#immediate_ops(_) => Op::#immediate_ops(#immediate_ops(immediate.try_into()?)),
)*
_ => panic!("only relative jumps/push operations can be combined"),
};

Ok(result)
Expand Down Expand Up @@ -852,4 +827,5 @@ fn main() {
generate_fork("london").unwrap();
generate_fork("shanghai").unwrap();
generate_fork("cancun").unwrap();
generate_fork("prague").unwrap();
}
5 changes: 5 additions & 0 deletions etk-ops/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ pub mod cancun {
include!(concat!(env!("OUT_DIR"), "/cancun.rs"));
}

pub mod prague {
//! Instructions available in the Cancun hard fork.
include!(concat!(env!("OUT_DIR"), "/prague.rs"));
}

/// Error that can occur when parsing an operation from a string.
#[derive(Debug, Snafu)]
pub struct FromStrError {
Expand Down
Loading