define pointer size

Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
xermicus
2023-12-08 19:11:00 +01:00
parent 80e14f182d
commit c04ae9a5c3
4 changed files with 128 additions and 86 deletions
+1 -1
View File
@@ -6,5 +6,5 @@ fn main() {
let bytecode = hex::decode(hexcode.trim()).unwrap();
let instructions = bytecode.disassemble();
Program::new(instructions).dot(BasicBlockFormatOption::Ir);
Program::new(instructions).dot(BasicBlockFormatOption::ByteCode);
}
+46 -8
View File
@@ -2,7 +2,10 @@ use evmil::bytecode::Instruction as EvmInstruction;
use primitive_types::U256;
use std::fmt::Write;
use crate::symbol::{Global, Symbol, SymbolTable, Type};
use crate::{
symbol::{Global, Symbol, SymbolTable, Type},
POINTER_SIZE,
};
#[derive(PartialEq, Debug)]
pub enum Instruction {
@@ -162,7 +165,7 @@ fn decrement_stack_height(symbol_table: &mut SymbolTable) -> Instruction {
x: symbol_table.global(Global::StackHeight),
y: symbol_table.global(Global::StackHeight),
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),
y: symbol_table.global(Global::StackHeight),
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}"),
_ => Vec::new(),
}
@@ -333,12 +371,12 @@ mod tests {
Instruction::IndexedAssign {
x: Symbol {
address: Address::Label(Global::Stack),
type_hint: Type::Word,
type_hint: Global::Stack.typ(),
kind: Global::Stack.kind(),
},
index: Symbol {
address: Address::Label(Global::StackHeight),
type_hint: Type::Int(4),
type_hint: Global::StackHeight.typ(),
kind: Global::StackHeight.kind(),
},
y: Symbol {
@@ -350,18 +388,18 @@ mod tests {
Instruction::BinaryAssign {
x: Symbol {
address: Address::Label(Global::StackHeight),
type_hint: Type::Int(4),
type_hint: Global::StackHeight.typ(),
kind: Global::StackHeight.kind(),
},
y: Symbol {
address: Address::Label(Global::StackHeight),
type_hint: Type::Int(4),
type_hint: Global::StackHeight.typ(),
kind: Global::StackHeight.kind(),
},
operator: Operator::Add,
z: Symbol {
address: Address::Constant(U256::one()),
type_hint: Type::Int(4),
type_hint: Global::StackHeight.typ(),
kind: Kind::Value,
},
},
+2
View File
@@ -2,6 +2,8 @@ pub mod cfg;
pub mod instruction;
pub mod symbol;
pub static POINTER_SIZE: usize = 32;
#[cfg(test)]
mod tests {
+79 -77
View File
@@ -1,26 +1,53 @@
use indexmap::IndexSet;
use primitive_types::U256;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Address {
Constant(U256),
Temporary(usize),
Label(Global),
use crate::POINTER_SIZE;
#[derive(Debug, Default)]
pub struct SymbolTable {
symbols: IndexSet<Symbol>,
nonce: usize,
}
impl std::fmt::Display for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Constant(value) => write!(f, "{value:02x}"),
Self::Temporary(n) => write!(f, "tmp_{n}"),
Self::Label(label) => write!(f, "{label:?}"),
}
impl SymbolTable {
fn next(&mut self) -> usize {
let current = self.nonce;
self.nonce += 1;
current
}
}
impl Address {
pub fn from_be_bytes(bytes: &[u8]) -> Self {
Self::Constant(U256::from_big_endian(bytes))
pub fn temporary(&mut self, type_hint: Option<Type>) -> Symbol {
let id = self.next();
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 {
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 {
fn global(symbol: Global) -> Self {
let type_hint = match symbol {
Global::StackHeight => Type::Int(4),
_ => Default::default(),
};
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Address {
Constant(U256),
Temporary(usize),
Label(Global),
}
Self::new(Address::Label(symbol), type_hint, symbol.kind())
}
fn new(address: Address, type_hint: Type, kind: Kind) -> Self {
Self {
address,
type_hint,
kind,
impl std::fmt::Display for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Constant(value) => write!(f, "0x{value:02x}"),
Self::Temporary(n) => write!(f, "tmp_{n}"),
Self::Label(label) => write!(f, "{label:?}"),
}
}
}
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)]
pub enum Type {
#[default]
Word,
UInt(usize),
Int(usize),
Bytes(usize),
Bool,
@@ -69,7 +106,8 @@ impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
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::Bool => write!(f, "bool"),
}
@@ -78,7 +116,7 @@ impl std::fmt::Display for Type {
impl Type {
pub fn pointer() -> Self {
Self::Int(4)
Self::UInt(POINTER_SIZE)
}
}
@@ -140,6 +178,14 @@ pub enum 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 {
match self {
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
}
}