mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 03:01:04 +00:00
@@ -6,5 +6,5 @@ fn main() {
|
|||||||
let bytecode = hex::decode(hexcode.trim()).unwrap();
|
let bytecode = hex::decode(hexcode.trim()).unwrap();
|
||||||
let instructions = bytecode.disassemble();
|
let instructions = bytecode.disassemble();
|
||||||
|
|
||||||
Program::new(instructions).dot(BasicBlockFormatOption::Ir);
|
Program::new(instructions).dot(BasicBlockFormatOption::ByteCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ use evmil::bytecode::Instruction as EvmInstruction;
|
|||||||
use primitive_types::U256;
|
use primitive_types::U256;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::symbol::{Global, Symbol, SymbolTable, Type};
|
use crate::{
|
||||||
|
symbol::{Global, Symbol, SymbolTable, Type},
|
||||||
|
POINTER_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
@@ -162,7 +165,7 @@ fn decrement_stack_height(symbol_table: &mut SymbolTable) -> Instruction {
|
|||||||
x: symbol_table.global(Global::StackHeight),
|
x: symbol_table.global(Global::StackHeight),
|
||||||
y: symbol_table.global(Global::StackHeight),
|
y: symbol_table.global(Global::StackHeight),
|
||||||
operator: Operator::Sub,
|
operator: Operator::Sub,
|
||||||
z: symbol_table.constant(U256::one(), Some(Type::Int(4))),
|
z: symbol_table.constant(U256::one(), Some(Global::StackHeight.typ())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +194,7 @@ fn increment_stack_height(symbol_table: &mut SymbolTable) -> Instruction {
|
|||||||
x: symbol_table.global(Global::StackHeight),
|
x: symbol_table.global(Global::StackHeight),
|
||||||
y: symbol_table.global(Global::StackHeight),
|
y: symbol_table.global(Global::StackHeight),
|
||||||
operator: Operator::Add,
|
operator: Operator::Add,
|
||||||
z: symbol_table.constant(U256::one(), Some(Type::Int(4))),
|
z: symbol_table.constant(U256::one(), Some(Global::StackHeight.typ())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,6 +308,41 @@ pub fn translate(opcode: &EvmInstruction, symbol_table: &mut SymbolTable) -> Vec
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STOP => {
|
||||||
|
vec![Instruction::Procedure {
|
||||||
|
symbol: Global::Stop,
|
||||||
|
parameters: Default::default(),
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
INVALID => {
|
||||||
|
let offset = symbol_table.constant(U256::zero(), Some(Type::Int(POINTER_SIZE)));
|
||||||
|
let size = symbol_table.constant(U256::zero(), Some(Type::Int(POINTER_SIZE)));
|
||||||
|
|
||||||
|
vec![Instruction::Procedure {
|
||||||
|
symbol: Global::Revert,
|
||||||
|
parameters: vec![offset, size],
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
REVERT => {
|
||||||
|
let offset = stack_pop(symbol_table);
|
||||||
|
let size = stack_pop(symbol_table);
|
||||||
|
|
||||||
|
let procedure = Instruction::Procedure {
|
||||||
|
symbol: Global::Revert,
|
||||||
|
parameters: vec![offset.load.target_address(), size.load.target_address()],
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![
|
||||||
|
offset.decrement,
|
||||||
|
offset.load,
|
||||||
|
size.decrement,
|
||||||
|
size.load,
|
||||||
|
procedure,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
//_ => todo!("{opcode}"),
|
//_ => todo!("{opcode}"),
|
||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
}
|
}
|
||||||
@@ -333,12 +371,12 @@ mod tests {
|
|||||||
Instruction::IndexedAssign {
|
Instruction::IndexedAssign {
|
||||||
x: Symbol {
|
x: Symbol {
|
||||||
address: Address::Label(Global::Stack),
|
address: Address::Label(Global::Stack),
|
||||||
type_hint: Type::Word,
|
type_hint: Global::Stack.typ(),
|
||||||
kind: Global::Stack.kind(),
|
kind: Global::Stack.kind(),
|
||||||
},
|
},
|
||||||
index: Symbol {
|
index: Symbol {
|
||||||
address: Address::Label(Global::StackHeight),
|
address: Address::Label(Global::StackHeight),
|
||||||
type_hint: Type::Int(4),
|
type_hint: Global::StackHeight.typ(),
|
||||||
kind: Global::StackHeight.kind(),
|
kind: Global::StackHeight.kind(),
|
||||||
},
|
},
|
||||||
y: Symbol {
|
y: Symbol {
|
||||||
@@ -350,18 +388,18 @@ mod tests {
|
|||||||
Instruction::BinaryAssign {
|
Instruction::BinaryAssign {
|
||||||
x: Symbol {
|
x: Symbol {
|
||||||
address: Address::Label(Global::StackHeight),
|
address: Address::Label(Global::StackHeight),
|
||||||
type_hint: Type::Int(4),
|
type_hint: Global::StackHeight.typ(),
|
||||||
kind: Global::StackHeight.kind(),
|
kind: Global::StackHeight.kind(),
|
||||||
},
|
},
|
||||||
y: Symbol {
|
y: Symbol {
|
||||||
address: Address::Label(Global::StackHeight),
|
address: Address::Label(Global::StackHeight),
|
||||||
type_hint: Type::Int(4),
|
type_hint: Global::StackHeight.typ(),
|
||||||
kind: Global::StackHeight.kind(),
|
kind: Global::StackHeight.kind(),
|
||||||
},
|
},
|
||||||
operator: Operator::Add,
|
operator: Operator::Add,
|
||||||
z: Symbol {
|
z: Symbol {
|
||||||
address: Address::Constant(U256::one()),
|
address: Address::Constant(U256::one()),
|
||||||
type_hint: Type::Int(4),
|
type_hint: Global::StackHeight.typ(),
|
||||||
kind: Kind::Value,
|
kind: Kind::Value,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ pub mod cfg;
|
|||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
|
|
||||||
|
pub static POINTER_SIZE: usize = 32;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|||||||
+79
-77
@@ -1,26 +1,53 @@
|
|||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use primitive_types::U256;
|
use primitive_types::U256;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
use crate::POINTER_SIZE;
|
||||||
pub enum Address {
|
|
||||||
Constant(U256),
|
#[derive(Debug, Default)]
|
||||||
Temporary(usize),
|
pub struct SymbolTable {
|
||||||
Label(Global),
|
symbols: IndexSet<Symbol>,
|
||||||
|
nonce: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Address {
|
impl SymbolTable {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn next(&mut self) -> usize {
|
||||||
match self {
|
let current = self.nonce;
|
||||||
Self::Constant(value) => write!(f, "{value:02x}"),
|
self.nonce += 1;
|
||||||
Self::Temporary(n) => write!(f, "tmp_{n}"),
|
current
|
||||||
Self::Label(label) => write!(f, "{label:?}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Address {
|
pub fn temporary(&mut self, type_hint: Option<Type>) -> Symbol {
|
||||||
pub fn from_be_bytes(bytes: &[u8]) -> Self {
|
let id = self.next();
|
||||||
Self::Constant(U256::from_big_endian(bytes))
|
let symbol = Symbol {
|
||||||
|
address: Address::Temporary(id),
|
||||||
|
type_hint: type_hint.unwrap_or_default(),
|
||||||
|
kind: Kind::Value,
|
||||||
|
};
|
||||||
|
assert!(self.symbols.insert(symbol));
|
||||||
|
|
||||||
|
symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn constant(&mut self, value: U256, type_hint: Option<Type>) -> Symbol {
|
||||||
|
let symbol = Symbol {
|
||||||
|
address: Address::Constant(value),
|
||||||
|
type_hint: type_hint.unwrap_or_default(),
|
||||||
|
kind: Kind::Value,
|
||||||
|
};
|
||||||
|
self.symbols.insert(symbol);
|
||||||
|
|
||||||
|
symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global(&mut self, label: Global) -> Symbol {
|
||||||
|
let symbol = Symbol {
|
||||||
|
address: Address::Label(label),
|
||||||
|
type_hint: label.typ(),
|
||||||
|
kind: label.kind(),
|
||||||
|
};
|
||||||
|
self.symbols.insert(symbol);
|
||||||
|
|
||||||
|
symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,33 +60,43 @@ pub struct Symbol {
|
|||||||
|
|
||||||
impl std::fmt::Display for Symbol {
|
impl std::fmt::Display for Symbol {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "({}) {}", self.type_hint, self.address)
|
write!(f, "({} {})", self.type_hint, self.address)?;
|
||||||
|
|
||||||
|
match self.kind {
|
||||||
|
Kind::Pointer => write!(f, "*"),
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol {
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
fn global(symbol: Global) -> Self {
|
pub enum Address {
|
||||||
let type_hint = match symbol {
|
Constant(U256),
|
||||||
Global::StackHeight => Type::Int(4),
|
Temporary(usize),
|
||||||
_ => Default::default(),
|
Label(Global),
|
||||||
};
|
}
|
||||||
|
|
||||||
Self::new(Address::Label(symbol), type_hint, symbol.kind())
|
impl std::fmt::Display for Address {
|
||||||
}
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
fn new(address: Address, type_hint: Type, kind: Kind) -> Self {
|
Self::Constant(value) => write!(f, "0x{value:02x}"),
|
||||||
Self {
|
Self::Temporary(n) => write!(f, "tmp_{n}"),
|
||||||
address,
|
Self::Label(label) => write!(f, "{label:?}"),
|
||||||
type_hint,
|
|
||||||
kind,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Address {
|
||||||
|
pub fn from_be_bytes(bytes: &[u8]) -> Self {
|
||||||
|
Self::Constant(U256::from_big_endian(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone, Copy)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
#[default]
|
#[default]
|
||||||
Word,
|
Word,
|
||||||
|
UInt(usize),
|
||||||
Int(usize),
|
Int(usize),
|
||||||
Bytes(usize),
|
Bytes(usize),
|
||||||
Bool,
|
Bool,
|
||||||
@@ -69,7 +106,8 @@ impl std::fmt::Display for Type {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Word => write!(f, "word"),
|
Self::Word => write!(f, "word"),
|
||||||
Self::Int(size) => write!(f, "int{}", size * 8),
|
Self::UInt(size) => write!(f, "u{}", size),
|
||||||
|
Self::Int(size) => write!(f, "i{}", size),
|
||||||
Self::Bytes(size) => write!(f, "bytes{size}"),
|
Self::Bytes(size) => write!(f, "bytes{size}"),
|
||||||
Self::Bool => write!(f, "bool"),
|
Self::Bool => write!(f, "bool"),
|
||||||
}
|
}
|
||||||
@@ -78,7 +116,7 @@ impl std::fmt::Display for Type {
|
|||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
pub fn pointer() -> Self {
|
pub fn pointer() -> Self {
|
||||||
Self::Int(4)
|
Self::UInt(POINTER_SIZE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +178,14 @@ pub enum Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
|
pub fn typ(&self) -> Type {
|
||||||
|
match self {
|
||||||
|
Self::Stack | Self::CallData | Self::Memory | Self::ReturnData => Type::pointer(),
|
||||||
|
Self::StackHeight => Type::UInt(POINTER_SIZE),
|
||||||
|
_ => Type::Word,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> Kind {
|
pub fn kind(&self) -> Kind {
|
||||||
match self {
|
match self {
|
||||||
Self::Stack | Self::CallData | Self::Memory | Self::ReturnData => Kind::Pointer,
|
Self::Stack | Self::CallData | Self::Memory | Self::ReturnData => Kind::Pointer,
|
||||||
@@ -148,47 +194,3 @@ impl Global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct SymbolTable {
|
|
||||||
symbols: IndexSet<Symbol>,
|
|
||||||
nonce: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolTable {
|
|
||||||
fn next(&mut self) -> usize {
|
|
||||||
let current = self.nonce;
|
|
||||||
self.nonce += 1;
|
|
||||||
current
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn temporary(&mut self, type_hint: Option<Type>) -> Symbol {
|
|
||||||
let id = self.next();
|
|
||||||
let symbol = Symbol::new(
|
|
||||||
Address::Temporary(id),
|
|
||||||
type_hint.unwrap_or_default(),
|
|
||||||
Kind::Value,
|
|
||||||
);
|
|
||||||
assert!(self.symbols.insert(symbol));
|
|
||||||
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn constant(&mut self, value: U256, type_hint: Option<Type>) -> Symbol {
|
|
||||||
let symbol = Symbol::new(
|
|
||||||
Address::Constant(value),
|
|
||||||
type_hint.unwrap_or_default(),
|
|
||||||
Kind::Value,
|
|
||||||
);
|
|
||||||
self.symbols.insert(symbol);
|
|
||||||
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global(&mut self, label: Global) -> Symbol {
|
|
||||||
let symbol = Symbol::global(label);
|
|
||||||
self.symbols.insert(symbol);
|
|
||||||
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user