use normal style for comments

Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
xermicus
2024-05-01 16:12:32 +02:00
parent 72515254fe
commit 426f673b0a
184 changed files with 3 additions and 1789 deletions
-2
View File
@@ -1,6 +1,4 @@
//!
//! The number base constants. //! The number base constants.
//!
/// The binary number base. /// The binary number base.
pub const BASE_BINARY: u32 = 2; pub const BASE_BINARY: u32 = 2;
-2
View File
@@ -1,6 +1,4 @@
//!
//! The common sizes in bits. //! The common sizes in bits.
//!
/// The `bool` type bit-length. /// The `bool` type bit-length.
pub const BIT_LENGTH_BOOLEAN: usize = 1; pub const BIT_LENGTH_BOOLEAN: usize = 1;
-2
View File
@@ -1,6 +1,4 @@
//!
//! The common sizes in bytes. //! The common sizes in bytes.
//!
/// The byte-length. /// The byte-length.
pub const BYTE_LENGTH_BYTE: usize = 1; pub const BYTE_LENGTH_BYTE: usize = 1;
-2
View File
@@ -1,6 +1,4 @@
//!
//! The EraVM address constants. //! The EraVM address constants.
//!
/// The corresponding simulation predefined address. /// The corresponding simulation predefined address.
pub const ERAVM_ADDRESS_TO_L1: u16 = 0xFFFF; pub const ERAVM_ADDRESS_TO_L1: u16 = 0xFFFF;
-4
View File
@@ -1,13 +1,9 @@
//!
//! The EVM version. //! The EVM version.
//!
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
///
/// The EVM version. /// The EVM version.
///
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum EVMVersion { pub enum EVMVersion {
-2
View File
@@ -1,6 +1,4 @@
//!
//! The file extensions. //! The file extensions.
//!
/// The manifest file extension. /// The manifest file extension.
pub static EXTENSION_MANIFEST: &str = "toml"; pub static EXTENSION_MANIFEST: &str = "toml";
-2
View File
@@ -1,6 +1,4 @@
//!
//! The compiler common library. //! The compiler common library.
//!
pub(crate) mod base; pub(crate) mod base;
pub(crate) mod bit_length; pub(crate) mod bit_length;
-8
View File
@@ -1,12 +1,7 @@
//!
//! The compiler common utils. //! The compiler common utils.
//!
///
/// Deserializes a `serde_json` object from slice with the recursion limit disabled. /// Deserializes a `serde_json` object from slice with the recursion limit disabled.
///
/// Must be used for all JSON I/O to avoid crashes due to the aforementioned limit. /// Must be used for all JSON I/O to avoid crashes due to the aforementioned limit.
///
pub fn deserialize_from_slice<O>(input: &[u8]) -> anyhow::Result<O> pub fn deserialize_from_slice<O>(input: &[u8]) -> anyhow::Result<O>
where where
O: serde::de::DeserializeOwned, O: serde::de::DeserializeOwned,
@@ -18,11 +13,8 @@ where
Ok(result) Ok(result)
} }
///
/// Deserializes a `serde_json` object from string with the recursion limit disabled. /// Deserializes a `serde_json` object from string with the recursion limit disabled.
///
/// Must be used for all JSON I/O to avoid crashes due to the aforementioned limit. /// Must be used for all JSON I/O to avoid crashes due to the aforementioned limit.
///
pub fn deserialize_from_str<O>(input: &str) -> anyhow::Result<O> pub fn deserialize_from_str<O>(input: &str) -> anyhow::Result<O>
where where
O: serde::de::DeserializeOwned, O: serde::de::DeserializeOwned,
-1
View File
@@ -9,7 +9,6 @@ include!(concat!(env!("OUT_DIR"), "/bswap.rs"));
/// - Takes a `i256` value argument /// - Takes a `i256` value argument
/// - Byte swaps it using `rev8` from the `zbb` extension /// - Byte swaps it using `rev8` from the `zbb` extension
/// - Returns the `i256` value /// - Returns the `i256` value
///
/// Returns `Error` if the module fails to validate, which should never happen. /// Returns `Error` if the module fails to validate, which should never happen.
pub fn module<'context>( pub fn module<'context>(
context: &'context Context, context: &'context Context,
+3 -3
View File
@@ -1,7 +1,7 @@
{ {
"ERC20": 53186, "Computation": 7380,
"Baseline": 3912, "Baseline": 3912,
"Flipper": 4354, "Flipper": 4354,
"Computation": 7380, "Fibonacci": 5971,
"Fibonacci": 5971 "ERC20": 53186
} }
@@ -1,10 +1,6 @@
//!
//! The debug IR type. //! The debug IR type.
//!
///
/// The debug IR type. /// The debug IR type.
///
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -24,9 +20,7 @@ pub enum IRType {
} }
impl IRType { impl IRType {
///
/// Returns the file extension for the specified IR. /// Returns the file extension for the specified IR.
///
pub fn file_extension(&self) -> &'static str { pub fn file_extension(&self) -> &'static str {
match self { match self {
Self::Yul => revive_common::EXTENSION_YUL, Self::Yul => revive_common::EXTENSION_YUL,
@@ -1,6 +1,4 @@
//!
//! The debug configuration. //! The debug configuration.
//!
pub mod ir_type; pub mod ir_type;
@@ -11,9 +9,7 @@ use serde::Serialize;
use self::ir_type::IRType; use self::ir_type::IRType;
///
/// The debug configuration. /// The debug configuration.
///
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct DebugConfig { pub struct DebugConfig {
/// The directory to dump the IRs to. /// The directory to dump the IRs to.
@@ -21,16 +17,12 @@ pub struct DebugConfig {
} }
impl DebugConfig { impl DebugConfig {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(output_directory: PathBuf) -> Self { pub fn new(output_directory: PathBuf) -> Self {
Self { output_directory } Self { output_directory }
} }
///
/// Dumps the Yul IR. /// Dumps the Yul IR.
///
pub fn dump_yul(&self, contract_path: &str, code: &str) -> anyhow::Result<()> { pub fn dump_yul(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned(); let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul); let full_file_name = Self::full_file_name(contract_path, None, IRType::Yul);
@@ -40,9 +32,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the EVM legacy assembly IR. /// Dumps the EVM legacy assembly IR.
///
pub fn dump_evmla(&self, contract_path: &str, code: &str) -> anyhow::Result<()> { pub fn dump_evmla(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned(); let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::EVMLA); let full_file_name = Self::full_file_name(contract_path, None, IRType::EVMLA);
@@ -52,9 +42,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the Ethereal IR. /// Dumps the Ethereal IR.
///
pub fn dump_ethir(&self, contract_path: &str, code: &str) -> anyhow::Result<()> { pub fn dump_ethir(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned(); let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::EthIR); let full_file_name = Self::full_file_name(contract_path, None, IRType::EthIR);
@@ -64,9 +52,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the LLL IR. /// Dumps the LLL IR.
///
pub fn dump_lll(&self, contract_path: &str, code: &str) -> anyhow::Result<()> { pub fn dump_lll(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned(); let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::LLL); let full_file_name = Self::full_file_name(contract_path, None, IRType::LLL);
@@ -76,9 +62,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the unoptimized LLVM IR. /// Dumps the unoptimized LLVM IR.
///
pub fn dump_llvm_ir_unoptimized( pub fn dump_llvm_ir_unoptimized(
&self, &self,
contract_path: &str, contract_path: &str,
@@ -94,9 +78,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the optimized LLVM IR. /// Dumps the optimized LLVM IR.
///
pub fn dump_llvm_ir_optimized( pub fn dump_llvm_ir_optimized(
&self, &self,
contract_path: &str, contract_path: &str,
@@ -112,9 +94,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Dumps the assembly. /// Dumps the assembly.
///
pub fn dump_assembly(&self, contract_path: &str, code: &str) -> anyhow::Result<()> { pub fn dump_assembly(&self, contract_path: &str, code: &str) -> anyhow::Result<()> {
let mut file_path = self.output_directory.to_owned(); let mut file_path = self.output_directory.to_owned();
let full_file_name = Self::full_file_name(contract_path, None, IRType::Assembly); let full_file_name = Self::full_file_name(contract_path, None, IRType::Assembly);
@@ -124,9 +104,7 @@ impl DebugConfig {
Ok(()) Ok(())
} }
///
/// Creates a full file name, given the contract full path, suffix, and extension. /// Creates a full file name, given the contract full path, suffix, and extension.
///
fn full_file_name(contract_path: &str, suffix: Option<&str>, ir_type: IRType) -> String { fn full_file_name(contract_path: &str, suffix: Option<&str>, ir_type: IRType) -> String {
let mut full_file_name = contract_path.replace('/', "_").replace(':', "."); let mut full_file_name = contract_path.replace('/', "_").replace(':', ".");
if let Some(suffix) = suffix { if let Some(suffix) = suffix {
-4
View File
@@ -1,6 +1,4 @@
//!
//! The LLVM context constants. //! The LLVM context constants.
//!
/// The LLVM framework version. /// The LLVM framework version.
pub const LLVM_VERSION: semver::Version = semver::Version::new(18, 1, 4); pub const LLVM_VERSION: semver::Version = semver::Version::new(18, 1, 4);
@@ -63,13 +61,11 @@ pub const NO_SYSTEM_CALL_BIT: bool = false;
/// The system call bit. /// The system call bit.
pub const SYSTEM_CALL_BIT: bool = true; pub const SYSTEM_CALL_BIT: bool = true;
///
/// The deployer call header size that consists of: /// The deployer call header size that consists of:
/// - selector (4 bytes) /// - selector (4 bytes)
/// - salt (32 bytes) /// - salt (32 bytes)
/// - bytecode hash (32 bytes) /// - bytecode hash (32 bytes)
/// - constructor arguments offset (32 bytes) /// - constructor arguments offset (32 bytes)
/// - constructor arguments length (32 bytes) /// - constructor arguments length (32 bytes)
///
pub const DEPLOYER_CALL_HEADER_SIZE: usize = pub const DEPLOYER_CALL_HEADER_SIZE: usize =
revive_common::BYTE_LENGTH_X32 + (revive_common::BYTE_LENGTH_FIELD * 4); revive_common::BYTE_LENGTH_X32 + (revive_common::BYTE_LENGTH_FIELD * 4);
@@ -1,10 +1,6 @@
//!
//! The address space aliases. //! The address space aliases.
//!
///
/// The address space aliases. /// The address space aliases.
///
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AddressSpace { pub enum AddressSpace {
/// The stack memory. /// The stack memory.
@@ -1,10 +1,6 @@
//!
//! The LLVM argument with metadata. //! The LLVM argument with metadata.
//!
///
/// The LLVM argument with metadata. /// The LLVM argument with metadata.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Argument<'ctx> { pub struct Argument<'ctx> {
/// The actual LLVM operand. /// The actual LLVM operand.
@@ -22,9 +18,7 @@ impl<'ctx> Argument<'ctx> {
/// The calldata length argument index. /// The calldata length argument index.
pub const ARGUMENT_INDEX_CALLDATA_LENGTH: usize = 1; pub const ARGUMENT_INDEX_CALLDATA_LENGTH: usize = 1;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(value: inkwell::values::BasicValueEnum<'ctx>) -> Self { pub fn new(value: inkwell::values::BasicValueEnum<'ctx>) -> Self {
Self { Self {
value, value,
@@ -33,9 +27,7 @@ impl<'ctx> Argument<'ctx> {
} }
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new_with_original( pub fn new_with_original(
value: inkwell::values::BasicValueEnum<'ctx>, value: inkwell::values::BasicValueEnum<'ctx>,
original: String, original: String,
@@ -47,9 +39,7 @@ impl<'ctx> Argument<'ctx> {
} }
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new_with_constant( pub fn new_with_constant(
value: inkwell::values::BasicValueEnum<'ctx>, value: inkwell::values::BasicValueEnum<'ctx>,
constant: num::BigUint, constant: num::BigUint,
@@ -61,9 +51,7 @@ impl<'ctx> Argument<'ctx> {
} }
} }
///
/// Returns the inner LLVM value. /// Returns the inner LLVM value.
///
pub fn to_llvm(&self) -> inkwell::values::BasicValueEnum<'ctx> { pub fn to_llvm(&self) -> inkwell::values::BasicValueEnum<'ctx> {
self.value self.value
} }
@@ -4,10 +4,8 @@ use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
/// The LLVM attribute. /// The LLVM attribute.
///
/// In order to check the real order in a new major version of LLVM, find the `Attributes.inc` file /// In order to check the real order in a new major version of LLVM, find the `Attributes.inc` file
/// inside of the LLVM build directory. This order is actually generated during the building. /// inside of the LLVM build directory. This order is actually generated during the building.
///
/// FIXME: Generate this in build.rs? /// FIXME: Generate this in build.rs?
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Attribute { pub enum Attribute {
@@ -1,15 +1,11 @@
//!
//! The LLVM module build. //! The LLVM module build.
//!
use std::collections::BTreeMap; use std::collections::BTreeMap;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
///
/// The LLVM module build. /// The LLVM module build.
///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Build { pub struct Build {
/// The EraVM text assembly. /// The EraVM text assembly.
@@ -25,9 +21,7 @@ pub struct Build {
} }
impl Build { impl Build {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
assembly_text: String, assembly_text: String,
metadata_hash: Option<[u8; revive_common::BYTE_LENGTH_FIELD]>, metadata_hash: Option<[u8; revive_common::BYTE_LENGTH_FIELD]>,
@@ -1,13 +1,8 @@
//!
//! The contract code types. //! The contract code types.
//!
///
/// The contract code types (deploy and runtime). /// The contract code types (deploy and runtime).
///
/// They do not represent any entities in the final bytecode, but this separation is always present /// They do not represent any entities in the final bytecode, but this separation is always present
/// in the IRs used for translation to the EVM bytecode. /// in the IRs used for translation to the EVM bytecode.
///
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CodeType { pub enum CodeType {
/// The deploy code. /// The deploy code.
@@ -1,13 +1,9 @@
//!
//! The LLVM debug information. //! The LLVM debug information.
//!
use inkwell::debug_info::AsDIScope; use inkwell::debug_info::AsDIScope;
use num::Zero; use num::Zero;
///
/// The LLVM debug information. /// The LLVM debug information.
///
pub struct DebugInfo<'ctx> { pub struct DebugInfo<'ctx> {
/// The compile unit. /// The compile unit.
compile_unit: inkwell::debug_info::DICompileUnit<'ctx>, compile_unit: inkwell::debug_info::DICompileUnit<'ctx>,
@@ -16,9 +12,7 @@ pub struct DebugInfo<'ctx> {
} }
impl<'ctx> DebugInfo<'ctx> { impl<'ctx> DebugInfo<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(module: &inkwell::module::Module<'ctx>) -> Self { pub fn new(module: &inkwell::module::Module<'ctx>) -> Self {
let (builder, compile_unit) = module.create_debug_info_builder( let (builder, compile_unit) = module.create_debug_info_builder(
true, true,
@@ -44,9 +38,7 @@ impl<'ctx> DebugInfo<'ctx> {
} }
} }
///
/// Creates a function info. /// Creates a function info.
///
pub fn create_function( pub fn create_function(
&self, &self,
name: &str, name: &str,
@@ -82,9 +74,7 @@ impl<'ctx> DebugInfo<'ctx> {
Ok(function) Ok(function)
} }
///
/// Creates a primitive type info. /// Creates a primitive type info.
///
pub fn create_type( pub fn create_type(
&self, &self,
bit_length: usize, bit_length: usize,
@@ -100,9 +90,7 @@ impl<'ctx> DebugInfo<'ctx> {
.map_err(|error| anyhow::anyhow!("Debug info error: {}", error)) .map_err(|error| anyhow::anyhow!("Debug info error: {}", error))
} }
///
/// Finalizes the builder. /// Finalizes the builder.
///
pub fn finalize(&self) { pub fn finalize(&self) {
self.builder.finalize(); self.builder.finalize();
} }
@@ -1,14 +1,9 @@
//!
//! The LLVM IR generator EVM legacy assembly data. //! The LLVM IR generator EVM legacy assembly data.
//!
use crate::eravm::context::argument::Argument; use crate::eravm::context::argument::Argument;
///
/// The LLVM IR generator EVM legacy assembly data. /// The LLVM IR generator EVM legacy assembly data.
///
/// Describes some data that is only relevant to the EVM legacy assembly. /// Describes some data that is only relevant to the EVM legacy assembly.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EVMLAData<'ctx> { pub struct EVMLAData<'ctx> {
/// The Solidity compiler version. /// The Solidity compiler version.
@@ -22,9 +17,7 @@ impl<'ctx> EVMLAData<'ctx> {
/// The default stack size. /// The default stack size.
pub const DEFAULT_STACK_SIZE: usize = 64; pub const DEFAULT_STACK_SIZE: usize = 64;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(version: semver::Version) -> Self { pub fn new(version: semver::Version) -> Self {
Self { Self {
version, version,
@@ -1,14 +1,9 @@
//!
//! The LLVM IR generator function block key. //! The LLVM IR generator function block key.
//!
use crate::eravm::context::code_type::CodeType; use crate::eravm::context::code_type::CodeType;
///
/// The LLVM IR generator function block key. /// The LLVM IR generator function block key.
///
/// Is only relevant to the EVM legacy assembly. /// Is only relevant to the EVM legacy assembly.
///
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Key { pub struct Key {
/// The block code type. /// The block code type.
@@ -18,9 +13,7 @@ pub struct Key {
} }
impl Key { impl Key {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(code_type: CodeType, tag: num::BigUint) -> Self { pub fn new(code_type: CodeType, tag: num::BigUint) -> Self {
Self { code_type, tag } Self { code_type, tag }
} }
@@ -1,14 +1,9 @@
//!
//! The LLVM function block EVM legacy assembly data. //! The LLVM function block EVM legacy assembly data.
//!
pub mod key; pub mod key;
///
/// The LLVM function block EVM legacy assembly data. /// The LLVM function block EVM legacy assembly data.
///
/// Describes some data that is only relevant to the EVM legacy assembly. /// Describes some data that is only relevant to the EVM legacy assembly.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EVMLAData { pub struct EVMLAData {
/// The initial hashes of the allowed stack states. /// The initial hashes of the allowed stack states.
@@ -16,9 +11,7 @@ pub struct EVMLAData {
} }
impl EVMLAData { impl EVMLAData {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(stack_hashes: Vec<md5::Digest>) -> Self { pub fn new(stack_hashes: Vec<md5::Digest>) -> Self {
Self { stack_hashes } Self { stack_hashes }
} }
@@ -1,14 +1,10 @@
//!
//! The LLVM IR generator function block. //! The LLVM IR generator function block.
//!
pub mod evmla_data; pub mod evmla_data;
use self::evmla_data::EVMLAData; use self::evmla_data::EVMLAData;
///
/// The LLVM IR generator function block. /// The LLVM IR generator function block.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Block<'ctx> { pub struct Block<'ctx> {
/// The inner block. /// The inner block.
@@ -18,9 +14,7 @@ pub struct Block<'ctx> {
} }
impl<'ctx> Block<'ctx> { impl<'ctx> Block<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(inner: inkwell::basic_block::BasicBlock<'ctx>) -> Self { pub fn new(inner: inkwell::basic_block::BasicBlock<'ctx>) -> Self {
Self { Self {
inner, inner,
@@ -28,38 +22,28 @@ impl<'ctx> Block<'ctx> {
} }
} }
///
/// Sets the EVM legacy assembly data. /// Sets the EVM legacy assembly data.
///
pub fn set_evmla_data(&mut self, data: EVMLAData) { pub fn set_evmla_data(&mut self, data: EVMLAData) {
self.evmla_data = Some(data); self.evmla_data = Some(data);
} }
///
/// The LLVM object reference. /// The LLVM object reference.
///
pub fn inner(&self) -> inkwell::basic_block::BasicBlock<'ctx> { pub fn inner(&self) -> inkwell::basic_block::BasicBlock<'ctx> {
self.inner self.inner
} }
///
/// Returns the EVM data reference. /// Returns the EVM data reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evm(&self) -> &EVMLAData { pub fn evm(&self) -> &EVMLAData {
self.evmla_data self.evmla_data
.as_ref() .as_ref()
.expect("The EVM data must have been initialized") .expect("The EVM data must have been initialized")
} }
///
/// Returns the EVM data mutable reference. /// Returns the EVM data mutable reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evm_mut(&mut self) -> &mut EVMLAData { pub fn evm_mut(&mut self) -> &mut EVMLAData {
self.evmla_data self.evmla_data
.as_mut() .as_mut()
@@ -1,10 +1,6 @@
//!
//! The LLVM function declaration. //! The LLVM function declaration.
//!
///
/// The LLVM function declaration. /// The LLVM function declaration.
///
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Declaration<'ctx> { pub struct Declaration<'ctx> {
/// The function type. /// The function type.
@@ -14,9 +10,7 @@ pub struct Declaration<'ctx> {
} }
impl<'ctx> Declaration<'ctx> { impl<'ctx> Declaration<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
r#type: inkwell::types::FunctionType<'ctx>, r#type: inkwell::types::FunctionType<'ctx>,
value: inkwell::values::FunctionValue<'ctx>, value: inkwell::values::FunctionValue<'ctx>,
@@ -1,17 +1,12 @@
//!
//! The LLVM function EVM legacy assembly data. //! The LLVM function EVM legacy assembly data.
//!
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::eravm::context::function::block::evmla_data::key::Key as BlockKey; use crate::eravm::context::function::block::evmla_data::key::Key as BlockKey;
use crate::eravm::context::function::block::Block; use crate::eravm::context::function::block::Block;
///
/// The LLVM function EVM legacy assembly data. /// The LLVM function EVM legacy assembly data.
///
/// Describes some data that is only relevant to the EVM legacy assembly. /// Describes some data that is only relevant to the EVM legacy assembly.
///
#[derive(Debug)] #[derive(Debug)]
pub struct EVMLAData<'ctx> { pub struct EVMLAData<'ctx> {
/// The ordinary blocks with numeric tags. /// The ordinary blocks with numeric tags.
@@ -22,9 +17,7 @@ pub struct EVMLAData<'ctx> {
} }
impl<'ctx> EVMLAData<'ctx> { impl<'ctx> EVMLAData<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(stack_size: usize) -> Self { pub fn new(stack_size: usize) -> Self {
Self { Self {
blocks: BTreeMap::new(), blocks: BTreeMap::new(),
@@ -32,9 +25,7 @@ impl<'ctx> EVMLAData<'ctx> {
} }
} }
///
/// Inserts a function block. /// Inserts a function block.
///
pub fn insert_block(&mut self, key: BlockKey, block: Block<'ctx>) { pub fn insert_block(&mut self, key: BlockKey, block: Block<'ctx>) {
if let Some(blocks) = self.blocks.get_mut(&key) { if let Some(blocks) = self.blocks.get_mut(&key) {
blocks.push(block); blocks.push(block);
@@ -43,11 +34,8 @@ impl<'ctx> EVMLAData<'ctx> {
} }
} }
///
/// Returns the block with the specified tag and initial stack pattern. /// Returns the block with the specified tag and initial stack pattern.
///
/// If there is only one block, it is returned unconditionally. /// If there is only one block, it is returned unconditionally.
///
pub fn find_block( pub fn find_block(
&self, &self,
key: &BlockKey, key: &BlockKey,
@@ -1,17 +1,12 @@
//!
//! The LLVM intrinsic functions. //! The LLVM intrinsic functions.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::function::declaration::Declaration as FunctionDeclaration; use crate::eravm::context::function::declaration::Declaration as FunctionDeclaration;
///
/// The LLVM intrinsic functions, implemented in the LLVM back-end. /// The LLVM intrinsic functions, implemented in the LLVM back-end.
///
/// Most of them are translated directly into bytecode instructions. /// Most of them are translated directly into bytecode instructions.
///
#[derive(Debug)] #[derive(Debug)]
pub struct Intrinsics<'ctx> { pub struct Intrinsics<'ctx> {
/// The trap. /// The trap.
@@ -37,9 +32,7 @@ impl<'ctx> Intrinsics<'ctx> {
/// The corresponding intrinsic function name. /// The corresponding intrinsic function name.
pub const FUNCTION_BYTE_SWAP: &'static str = "llvm.bswap.i256"; pub const FUNCTION_BYTE_SWAP: &'static str = "llvm.bswap.i256";
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
module: &inkwell::module::Module<'ctx>, module: &inkwell::module::Module<'ctx>,
@@ -100,9 +93,7 @@ impl<'ctx> Intrinsics<'ctx> {
} }
} }
///
/// Finds the specified LLVM intrinsic function in the target and returns its declaration. /// Finds the specified LLVM intrinsic function in the target and returns its declaration.
///
pub fn declare( pub fn declare(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
module: &inkwell::module::Module<'ctx>, module: &inkwell::module::Module<'ctx>,
@@ -118,9 +109,7 @@ impl<'ctx> Intrinsics<'ctx> {
FunctionDeclaration::new(r#type, value) FunctionDeclaration::new(r#type, value)
} }
///
/// Returns the LLVM types for selecting via the signature. /// Returns the LLVM types for selecting via the signature.
///
pub fn argument_types( pub fn argument_types(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
name: &str, name: &str,
@@ -1,6 +1,4 @@
//!
//! The LLVM runtime functions. //! The LLVM runtime functions.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
@@ -9,11 +7,8 @@ use crate::eravm::context::function::declaration::Declaration as FunctionDeclara
use crate::eravm::context::function::Function; use crate::eravm::context::function::Function;
use crate::optimizer::Optimizer; use crate::optimizer::Optimizer;
///
/// The runtime functions, implemented on the LLVM side. /// The runtime functions, implemented on the LLVM side.
///
/// The functions are automatically linked to the LLVM implementations if the signatures match. /// The functions are automatically linked to the LLVM implementations if the signatures match.
///
#[derive(Debug)] #[derive(Debug)]
pub struct LLVMRuntime<'ctx> { pub struct LLVMRuntime<'ctx> {
/// The LLVM personality function, used for exception handling. /// The LLVM personality function, used for exception handling.
@@ -159,9 +154,7 @@ impl<'ctx> LLVMRuntime<'ctx> {
/// The corresponding runtime function name. /// The corresponding runtime function name.
pub const FUNCTION_REVERT: &'static str = "__revert"; pub const FUNCTION_REVERT: &'static str = "__revert";
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
module: &inkwell::module::Module<'ctx>, module: &inkwell::module::Module<'ctx>,
@@ -602,9 +595,7 @@ impl<'ctx> LLVMRuntime<'ctx> {
} }
} }
///
/// Declares an LLVM runtime function in the `module`, /// Declares an LLVM runtime function in the `module`,
///
pub fn declare( pub fn declare(
module: &inkwell::module::Module<'ctx>, module: &inkwell::module::Module<'ctx>,
name: &str, name: &str,
@@ -625,9 +616,7 @@ impl<'ctx> LLVMRuntime<'ctx> {
FunctionDeclaration::new(value.get_type(), value).into() FunctionDeclaration::new(value.get_type(), value).into()
} }
///
/// Modifies the external call function with `is_byref` and `is_system` modifiers. /// Modifies the external call function with `is_byref` and `is_system` modifiers.
///
pub fn modify( pub fn modify(
&self, &self,
function: FunctionDeclaration<'ctx>, function: FunctionDeclaration<'ctx>,
@@ -1,6 +1,4 @@
//!
//! The LLVM IR generator function. //! The LLVM IR generator function.
//!
pub mod block; pub mod block;
pub mod declaration; pub mod declaration;
@@ -26,9 +24,7 @@ use self::runtime::Runtime;
use self::vyper_data::VyperData; use self::vyper_data::VyperData;
use self::yul_data::YulData; use self::yul_data::YulData;
///
/// The LLVM IR generator function. /// The LLVM IR generator function.
///
#[derive(Debug)] #[derive(Debug)]
pub struct Function<'ctx> { pub struct Function<'ctx> {
/// The high-level source code name. /// The high-level source code name.
@@ -66,9 +62,7 @@ impl<'ctx> Function<'ctx> {
/// The stack hashmap default capacity. /// The stack hashmap default capacity.
const STACK_HASHMAP_INITIAL_CAPACITY: usize = 64; const STACK_HASHMAP_INITIAL_CAPACITY: usize = 64;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
name: String, name: String,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -92,16 +86,12 @@ impl<'ctx> Function<'ctx> {
} }
} }
///
/// Returns the function name reference. /// Returns the function name reference.
///
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
self.name.as_str() self.name.as_str()
} }
///
/// Checks whether the function is defined outside of the front-end. /// Checks whether the function is defined outside of the front-end.
///
pub fn is_name_external(name: &str) -> bool { pub fn is_name_external(name: &str) -> bool {
name.starts_with("llvm.") name.starts_with("llvm.")
|| (name.starts_with("__") || (name.starts_with("__")
@@ -110,24 +100,18 @@ impl<'ctx> Function<'ctx> {
&& name != Runtime::FUNCTION_RUNTIME_CODE) && name != Runtime::FUNCTION_RUNTIME_CODE)
} }
///
/// Checks whether the function is related to the near call ABI. /// Checks whether the function is related to the near call ABI.
///
pub fn is_near_call_abi(name: &str) -> bool { pub fn is_near_call_abi(name: &str) -> bool {
name.starts_with(Self::ZKSYNC_NEAR_CALL_ABI_PREFIX) name.starts_with(Self::ZKSYNC_NEAR_CALL_ABI_PREFIX)
|| name == Self::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER || name == Self::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER
} }
///
/// Returns the LLVM function declaration. /// Returns the LLVM function declaration.
///
pub fn declaration(&self) -> Declaration<'ctx> { pub fn declaration(&self) -> Declaration<'ctx> {
self.declaration self.declaration
} }
///
/// Returns the N-th parameter of the function. /// Returns the N-th parameter of the function.
///
pub fn get_nth_param(&self, index: usize) -> inkwell::values::BasicValueEnum<'ctx> { pub fn get_nth_param(&self, index: usize) -> inkwell::values::BasicValueEnum<'ctx> {
self.declaration() self.declaration()
.value .value
@@ -135,9 +119,7 @@ impl<'ctx> Function<'ctx> {
.expect("Always exists") .expect("Always exists")
} }
///
/// Sets the memory writer function attributes. /// Sets the memory writer function attributes.
///
pub fn set_attributes( pub fn set_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -201,11 +183,8 @@ impl<'ctx> Function<'ctx> {
} }
} }
///
/// Sets the default attributes. /// Sets the default attributes.
///
/// The attributes only affect the LLVM optimizations. /// The attributes only affect the LLVM optimizations.
///
pub fn set_default_attributes( pub fn set_default_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -234,9 +213,7 @@ impl<'ctx> Function<'ctx> {
Self::set_attributes(llvm, declaration, vec![Attribute::NoFree], false); Self::set_attributes(llvm, declaration, vec![Attribute::NoFree], false);
} }
///
/// Sets the front-end runtime attributes. /// Sets the front-end runtime attributes.
///
pub fn set_frontend_runtime_attributes( pub fn set_frontend_runtime_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -247,9 +224,7 @@ impl<'ctx> Function<'ctx> {
} }
} }
///
/// Sets the exception handler attributes. /// Sets the exception handler attributes.
///
pub fn set_exception_handler_attributes( pub fn set_exception_handler_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -257,9 +232,7 @@ impl<'ctx> Function<'ctx> {
Self::set_attributes(llvm, declaration, vec![Attribute::NoInline], false); Self::set_attributes(llvm, declaration, vec![Attribute::NoInline], false);
} }
///
/// Sets the CXA-throw attributes. /// Sets the CXA-throw attributes.
///
pub fn set_cxa_throw_attributes( pub fn set_cxa_throw_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -267,9 +240,7 @@ impl<'ctx> Function<'ctx> {
Self::set_attributes(llvm, declaration, vec![Attribute::NoProfile], false); Self::set_attributes(llvm, declaration, vec![Attribute::NoProfile], false);
} }
///
/// Sets the pure function attributes. /// Sets the pure function attributes.
///
pub fn set_pure_function_attributes( pub fn set_pure_function_attributes(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
declaration: Declaration<'ctx>, declaration: Declaration<'ctx>,
@@ -288,10 +259,8 @@ impl<'ctx> Function<'ctx> {
); );
} }
///
/// Saves the pointer to a stack variable, returning the pointer to the shadowed variable, /// Saves the pointer to a stack variable, returning the pointer to the shadowed variable,
/// if it exists. /// if it exists.
///
pub fn insert_stack_pointer( pub fn insert_stack_pointer(
&mut self, &mut self,
name: String, name: String,
@@ -300,148 +269,108 @@ impl<'ctx> Function<'ctx> {
self.stack.insert(name, pointer) self.stack.insert(name, pointer)
} }
///
/// Gets the pointer to a stack variable. /// Gets the pointer to a stack variable.
///
pub fn get_stack_pointer(&self, name: &str) -> Option<Pointer<'ctx>> { pub fn get_stack_pointer(&self, name: &str) -> Option<Pointer<'ctx>> {
self.stack.get(name).copied() self.stack.get(name).copied()
} }
///
/// Removes the pointer to a stack variable. /// Removes the pointer to a stack variable.
///
pub fn remove_stack_pointer(&mut self, name: &str) { pub fn remove_stack_pointer(&mut self, name: &str) {
self.stack.remove(name); self.stack.remove(name);
} }
///
/// Returns the return entity representation. /// Returns the return entity representation.
///
pub fn r#return(&self) -> Return<'ctx> { pub fn r#return(&self) -> Return<'ctx> {
self.r#return self.r#return
} }
///
/// Returns the pointer to the function return value. /// Returns the pointer to the function return value.
///
/// # Panics /// # Panics
/// If the pointer has not been set yet. /// If the pointer has not been set yet.
///
pub fn return_pointer(&self) -> Option<Pointer<'ctx>> { pub fn return_pointer(&self) -> Option<Pointer<'ctx>> {
self.r#return.return_pointer() self.r#return.return_pointer()
} }
///
/// Returns the return data size in bytes, based on the default stack alignment. /// Returns the return data size in bytes, based on the default stack alignment.
///
/// # Panics /// # Panics
/// If the pointer has not been set yet. /// If the pointer has not been set yet.
///
pub fn return_data_size(&self) -> usize { pub fn return_data_size(&self) -> usize {
self.r#return.return_data_size() self.r#return.return_data_size()
} }
///
/// Returns the function entry block. /// Returns the function entry block.
///
pub fn entry_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> { pub fn entry_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> {
self.entry_block self.entry_block
} }
///
/// Returns the function return block. /// Returns the function return block.
///
pub fn return_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> { pub fn return_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> {
self.return_block self.return_block
} }
///
/// Sets the EVM legacy assembly data. /// Sets the EVM legacy assembly data.
///
pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) { pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) {
self.evmla_data = Some(data); self.evmla_data = Some(data);
} }
///
/// Returns the EVM legacy assembly data reference. /// Returns the EVM legacy assembly data reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evmla(&self) -> &EVMLAData<'ctx> { pub fn evmla(&self) -> &EVMLAData<'ctx> {
self.evmla_data self.evmla_data
.as_ref() .as_ref()
.expect("The EVM data must have been initialized") .expect("The EVM data must have been initialized")
} }
///
/// Returns the EVM legacy assembly data mutable reference. /// Returns the EVM legacy assembly data mutable reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> { pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> {
self.evmla_data self.evmla_data
.as_mut() .as_mut()
.expect("The EVM data must have been initialized") .expect("The EVM data must have been initialized")
} }
///
/// Sets the Vyper data. /// Sets the Vyper data.
///
pub fn set_vyper_data(&mut self, data: VyperData) { pub fn set_vyper_data(&mut self, data: VyperData) {
self.vyper_data = Some(data); self.vyper_data = Some(data);
} }
///
/// Returns the Vyper data reference. /// Returns the Vyper data reference.
///
/// # Panics /// # Panics
/// If the Vyper data has not been initialized. /// If the Vyper data has not been initialized.
///
pub fn vyper(&self) -> &VyperData { pub fn vyper(&self) -> &VyperData {
self.vyper_data self.vyper_data
.as_ref() .as_ref()
.expect("The Vyper data must have been initialized") .expect("The Vyper data must have been initialized")
} }
///
/// Returns the Vyper data mutable reference. /// Returns the Vyper data mutable reference.
///
/// # Panics /// # Panics
/// If the Vyper data has not been initialized. /// If the Vyper data has not been initialized.
///
pub fn vyper_mut(&mut self) -> &mut VyperData { pub fn vyper_mut(&mut self) -> &mut VyperData {
self.vyper_data self.vyper_data
.as_mut() .as_mut()
.expect("The Vyper data must have been initialized") .expect("The Vyper data must have been initialized")
} }
///
/// Sets the Yul data. /// Sets the Yul data.
///
pub fn set_yul_data(&mut self, data: YulData) { pub fn set_yul_data(&mut self, data: YulData) {
self.yul_data = Some(data); self.yul_data = Some(data);
} }
///
/// Returns the Yul data reference. /// Returns the Yul data reference.
///
/// # Panics /// # Panics
/// If the Yul data has not been initialized. /// If the Yul data has not been initialized.
///
pub fn yul(&self) -> &YulData { pub fn yul(&self) -> &YulData {
self.yul_data self.yul_data
.as_ref() .as_ref()
.expect("The Yul data must have been initialized") .expect("The Yul data must have been initialized")
} }
///
/// Returns the Yul data mutable reference. /// Returns the Yul data mutable reference.
///
/// # Panics /// # Panics
/// If the Yul data has not been initialized. /// If the Yul data has not been initialized.
///
pub fn yul_mut(&mut self) -> &mut YulData { pub fn yul_mut(&mut self) -> &mut YulData {
self.yul_data self.yul_data
.as_mut() .as_mut()
@@ -1,12 +1,8 @@
//!
//! The LLVM IR generator function return entity. //! The LLVM IR generator function return entity.
//!
use crate::eravm::context::pointer::Pointer; use crate::eravm::context::pointer::Pointer;
///
/// The LLVM IR generator function return entity. /// The LLVM IR generator function return entity.
///
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Return<'ctx> { pub enum Return<'ctx> {
/// The function does not return a value. /// The function does not return a value.
@@ -27,30 +23,22 @@ pub enum Return<'ctx> {
} }
impl<'ctx> Return<'ctx> { impl<'ctx> Return<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn none() -> Self { pub fn none() -> Self {
Self::None Self::None
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn primitive(pointer: Pointer<'ctx>) -> Self { pub fn primitive(pointer: Pointer<'ctx>) -> Self {
Self::Primitive { pointer } Self::Primitive { pointer }
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn compound(pointer: Pointer<'ctx>, size: usize) -> Self { pub fn compound(pointer: Pointer<'ctx>, size: usize) -> Self {
Self::Compound { pointer, size } Self::Compound { pointer, size }
} }
///
/// Returns the pointer to the function return value. /// Returns the pointer to the function return value.
///
pub fn return_pointer(&self) -> Option<Pointer<'ctx>> { pub fn return_pointer(&self) -> Option<Pointer<'ctx>> {
match self { match self {
Return::None => None, Return::None => None,
@@ -59,9 +47,7 @@ impl<'ctx> Return<'ctx> {
} }
} }
///
/// Returns the return data size in bytes, based on the default stack alignment. /// Returns the return data size in bytes, based on the default stack alignment.
///
pub fn return_data_size(&self) -> usize { pub fn return_data_size(&self) -> usize {
revive_common::BYTE_LENGTH_FIELD revive_common::BYTE_LENGTH_FIELD
* match self { * match self {
@@ -1,6 +1,4 @@
//!
//! The `default_call` function. //! The `default_call` function.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
@@ -11,11 +9,8 @@ use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
use crate::eravm::WriteLLVM; use crate::eravm::WriteLLVM;
///
/// The `default_call` function. /// The `default_call` function.
///
/// Generates a default contract call, if the `msg.value` is zero. /// Generates a default contract call, if the `msg.value` is zero.
///
#[derive(Debug)] #[derive(Debug)]
pub struct DefaultCall { pub struct DefaultCall {
/// The name of the inner function used for the low-level call. /// The name of the inner function used for the low-level call.
@@ -44,9 +39,7 @@ impl DefaultCall {
/// The output length argument index. /// The output length argument index.
pub const ARGUMENT_INDEX_OUTPUT_LENGTH: usize = 5; pub const ARGUMENT_INDEX_OUTPUT_LENGTH: usize = 5;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(call_function: FunctionDeclaration) -> Self { pub fn new(call_function: FunctionDeclaration) -> Self {
let inner_name = call_function.value.get_name().to_string_lossy().to_string(); let inner_name = call_function.value.get_name().to_string_lossy().to_string();
let name = Self::name(call_function); let name = Self::name(call_function);
@@ -54,9 +47,7 @@ impl DefaultCall {
Self { inner_name, name } Self { inner_name, name }
} }
///
/// Returns the function name. /// Returns the function name.
///
pub fn name(call_function: FunctionDeclaration) -> String { pub fn name(call_function: FunctionDeclaration) -> String {
let suffix = match call_function.value.get_name().to_string_lossy() { let suffix = match call_function.value.get_name().to_string_lossy() {
name if name == LLVMRuntime::FUNCTION_FARCALL => "far", name if name == LLVMRuntime::FUNCTION_FARCALL => "far",
@@ -67,9 +58,7 @@ impl DefaultCall {
format!("__default_{suffix}_call") format!("__default_{suffix}_call")
} }
///
/// Returns the low-level call function. /// Returns the low-level call function.
///
fn inner_function<'ctx, D>(&self, context: &Context<'ctx, D>) -> FunctionDeclaration<'ctx> fn inner_function<'ctx, D>(&self, context: &Context<'ctx, D>) -> FunctionDeclaration<'ctx>
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -1,6 +1,4 @@
//!
//! The deploy code function. //! The deploy code function.
//!
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -12,11 +10,8 @@ use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
use crate::eravm::WriteLLVM; use crate::eravm::WriteLLVM;
///
/// The deploy code function. /// The deploy code function.
///
/// Is a special function that is only used by the front-end generated code. /// Is a special function that is only used by the front-end generated code.
///
#[derive(Debug)] #[derive(Debug)]
pub struct DeployCode<B, D> pub struct DeployCode<B, D>
where where
@@ -34,9 +29,7 @@ where
B: WriteLLVM<D>, B: WriteLLVM<D>,
D: Dependency + Clone, D: Dependency + Clone,
{ {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(inner: B) -> Self { pub fn new(inner: B) -> Self {
Self { Self {
inner, inner,
@@ -1,6 +1,4 @@
//!
//! The `deployer_call` function. //! The `deployer_call` function.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
@@ -11,14 +9,10 @@ use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
use crate::eravm::WriteLLVM; use crate::eravm::WriteLLVM;
///
/// The `deployer_call` function. /// The `deployer_call` function.
///
/// Calls the deployer system contract, which returns the newly deployed contract address or 0. /// Calls the deployer system contract, which returns the newly deployed contract address or 0.
///
/// The address is returned in the first 32-byte word of the return data. If it is 0, the 0 is /// The address is returned in the first 32-byte word of the return data. If it is 0, the 0 is
/// returned. If the entire call has failed, there is also a 0 returned. /// returned. If the entire call has failed, there is also a 0 returned.
///
#[derive(Debug)] #[derive(Debug)]
pub struct DeployerCall { pub struct DeployerCall {
/// The address space where the calldata is allocated. /// The address space where the calldata is allocated.
@@ -45,9 +39,7 @@ impl DeployerCall {
/// The salt argument index. /// The salt argument index.
pub const ARGUMENT_INDEX_SALT: usize = 4; pub const ARGUMENT_INDEX_SALT: usize = 4;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(address_space: AddressSpace) -> Self { pub fn new(address_space: AddressSpace) -> Self {
Self { address_space } Self { address_space }
} }
@@ -1,6 +1,4 @@
//!
//! The entry function. //! The entry function.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
@@ -11,13 +9,9 @@ use crate::eravm::Dependency;
use crate::eravm::WriteLLVM; use crate::eravm::WriteLLVM;
use crate::EraVMPointer as Pointer; use crate::EraVMPointer as Pointer;
///
/// The entry function. /// The entry function.
///
/// The function is a wrapper managing the runtime and deploy code calling logic. /// The function is a wrapper managing the runtime and deploy code calling logic.
///
/// Is a special runtime function that is only used by the front-end generated code. /// Is a special runtime function that is only used by the front-end generated code.
///
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Entry {} pub struct Entry {}
@@ -1,6 +1,4 @@
//!
//! The front-end runtime functions. //! The front-end runtime functions.
//!
pub mod default_call; pub mod default_call;
pub mod deploy_code; pub mod deploy_code;
@@ -17,9 +15,7 @@ use crate::eravm::WriteLLVM;
use self::default_call::DefaultCall; use self::default_call::DefaultCall;
use self::deployer_call::DeployerCall; use self::deployer_call::DeployerCall;
///
/// The front-end runtime functions. /// The front-end runtime functions.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Runtime { pub struct Runtime {
/// The address space where the calldata is allocated. /// The address space where the calldata is allocated.
@@ -37,16 +33,12 @@ impl Runtime {
/// The runtime code function name. /// The runtime code function name.
pub const FUNCTION_RUNTIME_CODE: &'static str = "__runtime"; pub const FUNCTION_RUNTIME_CODE: &'static str = "__runtime";
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(address_space: AddressSpace) -> Self { pub fn new(address_space: AddressSpace) -> Self {
Self { address_space } Self { address_space }
} }
///
/// Returns the corresponding runtime function. /// Returns the corresponding runtime function.
///
pub fn default_call<'ctx, D>( pub fn default_call<'ctx, D>(
context: &Context<'ctx, D>, context: &Context<'ctx, D>,
call_function: FunctionDeclaration<'ctx>, call_function: FunctionDeclaration<'ctx>,
@@ -61,9 +53,7 @@ impl Runtime {
.declaration() .declaration()
} }
///
/// Returns the corresponding runtime function. /// Returns the corresponding runtime function.
///
pub fn deployer_call<'ctx, D>(context: &Context<'ctx, D>) -> FunctionDeclaration<'ctx> pub fn deployer_call<'ctx, D>(context: &Context<'ctx, D>) -> FunctionDeclaration<'ctx>
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -1,6 +1,4 @@
//!
//! The runtime code function. //! The runtime code function.
//!
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -10,11 +8,8 @@ use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
use crate::eravm::WriteLLVM; use crate::eravm::WriteLLVM;
///
/// The runtime code function. /// The runtime code function.
///
/// Is a special function that is only used by the front-end generated code. /// Is a special function that is only used by the front-end generated code.
///
#[derive(Debug)] #[derive(Debug)]
pub struct RuntimeCode<B, D> pub struct RuntimeCode<B, D>
where where
@@ -32,9 +27,7 @@ where
B: WriteLLVM<D>, B: WriteLLVM<D>,
D: Dependency + Clone, D: Dependency + Clone,
{ {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(inner: B) -> Self { pub fn new(inner: B) -> Self {
Self { Self {
inner, inner,
@@ -1,14 +1,9 @@
//!
//! The LLVM function Vyper data. //! The LLVM function Vyper data.
//!
use std::collections::HashMap; use std::collections::HashMap;
///
/// The LLVM function Vyper data. /// The LLVM function Vyper data.
///
/// Describes some data that is only relevant to Vyper. /// Describes some data that is only relevant to Vyper.
///
#[derive(Debug)] #[derive(Debug)]
pub struct VyperData { pub struct VyperData {
/// The block-local variables. They are still allocated at the beginning of the function, /// The block-local variables. They are still allocated at the beginning of the function,
@@ -29,23 +24,17 @@ impl VyperData {
/// The label arguments hashmap default capacity. /// The label arguments hashmap default capacity.
const LABEL_ARGUMENTS_HASHMAP_INITIAL_CAPACITY: usize = 16; const LABEL_ARGUMENTS_HASHMAP_INITIAL_CAPACITY: usize = 16;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
///
/// Returns the list of a Vyper label arguments. /// Returns the list of a Vyper label arguments.
///
pub fn label_arguments(&self, label_name: &str) -> Option<Vec<String>> { pub fn label_arguments(&self, label_name: &str) -> Option<Vec<String>> {
self.label_arguments.get(label_name).cloned() self.label_arguments.get(label_name).cloned()
} }
///
/// Inserts arguments for the specified label. /// Inserts arguments for the specified label.
///
pub fn insert_label_arguments(&mut self, label_name: String, arguments: Vec<String>) { pub fn insert_label_arguments(&mut self, label_name: String, arguments: Vec<String>) {
self.label_arguments.insert(label_name, arguments); self.label_arguments.insert(label_name, arguments);
} }
@@ -1,16 +1,11 @@
//!
//! The LLVM function Yul data. //! The LLVM function Yul data.
//!
use std::collections::HashMap; use std::collections::HashMap;
use num::BigUint; use num::BigUint;
///
/// The LLVM function Yul data. /// The LLVM function Yul data.
///
/// Describes some data that is only relevant to Yul. /// Describes some data that is only relevant to Yul.
///
#[derive(Debug)] #[derive(Debug)]
pub struct YulData { pub struct YulData {
/// The constants saved to variables. Used for peculiar cases like call simulation. /// The constants saved to variables. Used for peculiar cases like call simulation.
@@ -30,23 +25,17 @@ impl YulData {
/// The constants hashmap default capacity. /// The constants hashmap default capacity.
const CONSTANTS_HASHMAP_INITIAL_CAPACITY: usize = 16; const CONSTANTS_HASHMAP_INITIAL_CAPACITY: usize = 16;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
///
/// Returns a constant if it has been saved. /// Returns a constant if it has been saved.
///
pub fn get_constant(&self, name: &str) -> Option<BigUint> { pub fn get_constant(&self, name: &str) -> Option<BigUint> {
self.constants.get(name).cloned() self.constants.get(name).cloned()
} }
///
/// Saves a constant detected with the partial constant propagation. /// Saves a constant detected with the partial constant propagation.
///
pub fn insert_constant(&mut self, name: String, value: BigUint) { pub fn insert_constant(&mut self, name: String, value: BigUint) {
self.constants.insert(name, value); self.constants.insert(name, value);
} }
@@ -1,6 +1,4 @@
//!
//! The LLVM global value. //! The LLVM global value.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
@@ -9,9 +7,7 @@ use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::EraVMDependency; use crate::EraVMDependency;
///
/// The LLVM global value. /// The LLVM global value.
///
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Global<'ctx> { pub struct Global<'ctx> {
/// The global type. /// The global type.
@@ -21,9 +17,7 @@ pub struct Global<'ctx> {
} }
impl<'ctx> Global<'ctx> { impl<'ctx> Global<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new<D, T, V>( pub fn new<D, T, V>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
r#type: T, r#type: T,
@@ -1,10 +1,6 @@
//!
//! The LLVM IR generator loop. //! The LLVM IR generator loop.
//!
///
/// The LLVM IR generator loop. /// The LLVM IR generator loop.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Loop<'ctx> { pub struct Loop<'ctx> {
/// The loop current block. /// The loop current block.
@@ -16,9 +12,7 @@ pub struct Loop<'ctx> {
} }
impl<'ctx> Loop<'ctx> { impl<'ctx> Loop<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
body_block: inkwell::basic_block::BasicBlock<'ctx>, body_block: inkwell::basic_block::BasicBlock<'ctx>,
continue_block: inkwell::basic_block::BasicBlock<'ctx>, continue_block: inkwell::basic_block::BasicBlock<'ctx>,
@@ -1,6 +1,4 @@
//!
//! The LLVM IR generator context. //! The LLVM IR generator context.
//!
pub mod address_space; pub mod address_space;
pub mod argument; pub mod argument;
@@ -52,12 +50,9 @@ use self::solidity_data::SolidityData;
use self::vyper_data::VyperData; use self::vyper_data::VyperData;
use self::yul_data::YulData; use self::yul_data::YulData;
///
/// The LLVM IR generator context. /// The LLVM IR generator context.
///
/// It is a not-so-big god-like object glueing all the compilers' complexity and act as an adapter /// It is a not-so-big god-like object glueing all the compilers' complexity and act as an adapter
/// and a superstructure over the inner `inkwell` LLVM context. /// and a superstructure over the inner `inkwell` LLVM context.
///
pub struct Context<'ctx, D> pub struct Context<'ctx, D>
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -191,9 +186,7 @@ where
); );
} }
///
/// Initializes a new LLVM context. /// Initializes a new LLVM context.
///
pub fn new( pub fn new(
llvm: &'ctx inkwell::context::Context, llvm: &'ctx inkwell::context::Context,
module: inkwell::module::Module<'ctx>, module: inkwell::module::Module<'ctx>,
@@ -235,9 +228,7 @@ where
} }
} }
///
/// Builds the LLVM IR module, returning the build artifacts. /// Builds the LLVM IR module, returning the build artifacts.
///
pub fn build( pub fn build(
mut self, mut self,
contract_path: &str, contract_path: &str,
@@ -312,53 +303,39 @@ where
Ok(build) Ok(build)
} }
///
/// Verifies the current LLVM IR module. /// Verifies the current LLVM IR module.
///
pub fn verify(&self) -> anyhow::Result<()> { pub fn verify(&self) -> anyhow::Result<()> {
self.module() self.module()
.verify() .verify()
.map_err(|error| anyhow::anyhow!(error.to_string())) .map_err(|error| anyhow::anyhow!(error.to_string()))
} }
///
/// Returns the inner LLVM context. /// Returns the inner LLVM context.
///
pub fn llvm(&self) -> &'ctx inkwell::context::Context { pub fn llvm(&self) -> &'ctx inkwell::context::Context {
self.llvm self.llvm
} }
///
/// Returns the LLVM IR builder. /// Returns the LLVM IR builder.
///
pub fn builder(&self) -> &inkwell::builder::Builder<'ctx> { pub fn builder(&self) -> &inkwell::builder::Builder<'ctx> {
&self.builder &self.builder
} }
///
/// Returns the current LLVM IR module reference. /// Returns the current LLVM IR module reference.
///
pub fn module(&self) -> &inkwell::module::Module<'ctx> { pub fn module(&self) -> &inkwell::module::Module<'ctx> {
&self.module &self.module
} }
///
/// Sets the current code type (deploy or runtime). /// Sets the current code type (deploy or runtime).
///
pub fn set_code_type(&mut self, code_type: CodeType) { pub fn set_code_type(&mut self, code_type: CodeType) {
self.code_type = Some(code_type); self.code_type = Some(code_type);
} }
///
/// Returns the current code type (deploy or runtime). /// Returns the current code type (deploy or runtime).
///
pub fn code_type(&self) -> Option<CodeType> { pub fn code_type(&self) -> Option<CodeType> {
self.code_type.to_owned() self.code_type.to_owned()
} }
///
/// Returns the pointer to a global variable. /// Returns the pointer to a global variable.
///
pub fn get_global(&self, name: &str) -> anyhow::Result<Global<'ctx>> { pub fn get_global(&self, name: &str) -> anyhow::Result<Global<'ctx>> {
match self.globals.get(name) { match self.globals.get(name) {
Some(global) => Ok(*global), Some(global) => Ok(*global),
@@ -366,9 +343,7 @@ where
} }
} }
///
/// Returns the value of a global variable. /// Returns the value of a global variable.
///
pub fn get_global_value( pub fn get_global_value(
&self, &self,
name: &str, name: &str,
@@ -377,9 +352,7 @@ where
self.build_load(global.into(), name) self.build_load(global.into(), name)
} }
///
/// Sets the value to a global variable. /// Sets the value to a global variable.
///
pub fn set_global<T, V>(&mut self, name: &str, r#type: T, address_space: AddressSpace, value: V) pub fn set_global<T, V>(&mut self, name: &str, r#type: T, address_space: AddressSpace, value: V)
where where
T: BasicType<'ctx> + Clone + Copy, T: BasicType<'ctx> + Clone + Copy,
@@ -397,16 +370,12 @@ where
} }
} }
///
/// Returns the LLVM intrinsics collection reference. /// Returns the LLVM intrinsics collection reference.
///
pub fn intrinsics(&self) -> &Intrinsics<'ctx> { pub fn intrinsics(&self) -> &Intrinsics<'ctx> {
&self.intrinsics &self.intrinsics
} }
///
/// Returns the LLVM runtime function collection reference. /// Returns the LLVM runtime function collection reference.
///
pub fn llvm_runtime(&self) -> &LLVMRuntime<'ctx> { pub fn llvm_runtime(&self) -> &LLVMRuntime<'ctx> {
&self.llvm_runtime &self.llvm_runtime
} }
@@ -440,9 +409,7 @@ where
Ok(function) Ok(function)
} }
///
/// Appends a function to the current module. /// Appends a function to the current module.
///
pub fn add_function( pub fn add_function(
&mut self, &mut self,
name: &str, name: &str,
@@ -504,25 +471,19 @@ where
Ok(function) Ok(function)
} }
///
/// Returns a shared reference to the specified function. /// Returns a shared reference to the specified function.
///
pub fn get_function(&self, name: &str) -> Option<Rc<RefCell<Function<'ctx>>>> { pub fn get_function(&self, name: &str) -> Option<Rc<RefCell<Function<'ctx>>>> {
self.functions.get(name).cloned() self.functions.get(name).cloned()
} }
///
/// Returns a shared reference to the current active function. /// Returns a shared reference to the current active function.
///
pub fn current_function(&self) -> Rc<RefCell<Function<'ctx>>> { pub fn current_function(&self) -> Rc<RefCell<Function<'ctx>>> {
self.current_function self.current_function
.clone() .clone()
.expect("Must be declared before use") .expect("Must be declared before use")
} }
///
/// Sets the current active function. /// Sets the current active function.
///
pub fn set_current_function(&mut self, name: &str) -> anyhow::Result<()> { pub fn set_current_function(&mut self, name: &str) -> anyhow::Result<()> {
let function = self.functions.get(name).cloned().ok_or_else(|| { let function = self.functions.get(name).cloned().ok_or_else(|| {
anyhow::anyhow!("Failed to activate an undeclared function `{}`", name) anyhow::anyhow!("Failed to activate an undeclared function `{}`", name)
@@ -531,9 +492,7 @@ where
Ok(()) Ok(())
} }
///
/// Pushes a new loop context to the stack. /// Pushes a new loop context to the stack.
///
pub fn push_loop( pub fn push_loop(
&mut self, &mut self,
body_block: inkwell::basic_block::BasicBlock<'ctx>, body_block: inkwell::basic_block::BasicBlock<'ctx>,
@@ -544,25 +503,19 @@ where
.push(Loop::new(body_block, continue_block, join_block)); .push(Loop::new(body_block, continue_block, join_block));
} }
///
/// Pops the current loop context from the stack. /// Pops the current loop context from the stack.
///
pub fn pop_loop(&mut self) { pub fn pop_loop(&mut self) {
self.loop_stack.pop(); self.loop_stack.pop();
} }
///
/// Returns the current loop context. /// Returns the current loop context.
///
pub fn r#loop(&self) -> &Loop<'ctx> { pub fn r#loop(&self) -> &Loop<'ctx> {
self.loop_stack self.loop_stack
.last() .last()
.expect("The current context is not in a loop") .expect("The current context is not in a loop")
} }
///
/// Compiles a contract dependency, if the dependency manager is set. /// Compiles a contract dependency, if the dependency manager is set.
///
pub fn compile_dependency(&mut self, name: &str) -> anyhow::Result<String> { pub fn compile_dependency(&mut self, name: &str) -> anyhow::Result<String> {
if let Some(vyper_data) = self.vyper_data.as_mut() { if let Some(vyper_data) = self.vyper_data.as_mut() {
vyper_data.set_is_forwarder_used(); vyper_data.set_is_forwarder_used();
@@ -585,9 +538,7 @@ where
}) })
} }
///
/// Gets a full contract_path from the dependency manager. /// Gets a full contract_path from the dependency manager.
///
pub fn resolve_path(&self, identifier: &str) -> anyhow::Result<String> { pub fn resolve_path(&self, identifier: &str) -> anyhow::Result<String> {
self.dependency_manager self.dependency_manager
.to_owned() .to_owned()
@@ -598,9 +549,7 @@ where
}) })
} }
///
/// Gets a deployed library address from the dependency manager. /// Gets a deployed library address from the dependency manager.
///
pub fn resolve_library(&self, path: &str) -> anyhow::Result<inkwell::values::IntValue<'ctx>> { pub fn resolve_library(&self, path: &str) -> anyhow::Result<inkwell::values::IntValue<'ctx>> {
self.dependency_manager self.dependency_manager
.to_owned() .to_owned()
@@ -612,49 +561,36 @@ where
}) })
} }
///
/// Extracts the dependency manager. /// Extracts the dependency manager.
///
pub fn take_dependency_manager(&mut self) -> D { pub fn take_dependency_manager(&mut self) -> D {
self.dependency_manager self.dependency_manager
.take() .take()
.expect("The dependency manager is unset") .expect("The dependency manager is unset")
} }
///
/// Returns the debug config reference. /// Returns the debug config reference.
///
pub fn debug_config(&self) -> Option<&DebugConfig> { pub fn debug_config(&self) -> Option<&DebugConfig> {
self.debug_config.as_ref() self.debug_config.as_ref()
} }
///
/// Appends a new basic block to the current function. /// Appends a new basic block to the current function.
///
pub fn append_basic_block(&self, name: &str) -> inkwell::basic_block::BasicBlock<'ctx> { pub fn append_basic_block(&self, name: &str) -> inkwell::basic_block::BasicBlock<'ctx> {
self.llvm self.llvm
.append_basic_block(self.current_function().borrow().declaration().value, name) .append_basic_block(self.current_function().borrow().declaration().value, name)
} }
///
/// Sets the current basic block. /// Sets the current basic block.
///
pub fn set_basic_block(&self, block: inkwell::basic_block::BasicBlock<'ctx>) { pub fn set_basic_block(&self, block: inkwell::basic_block::BasicBlock<'ctx>) {
self.builder.position_at_end(block); self.builder.position_at_end(block);
} }
///
/// Returns the current basic block. /// Returns the current basic block.
///
pub fn basic_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> { pub fn basic_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> {
self.builder.get_insert_block().expect("Always exists") self.builder.get_insert_block().expect("Always exists")
} }
///
/// Builds a stack allocation instruction. /// Builds a stack allocation instruction.
///
/// Sets the alignment to 128 bits. /// Sets the alignment to 128 bits.
///
pub fn build_alloca<T: BasicType<'ctx> + Clone + Copy>( pub fn build_alloca<T: BasicType<'ctx> + Clone + Copy>(
&self, &self,
r#type: T, r#type: T,
@@ -669,11 +605,8 @@ where
Pointer::new(r#type, AddressSpace::Stack, pointer) Pointer::new(r#type, AddressSpace::Stack, pointer)
} }
///
/// Builds a stack load instruction. /// Builds a stack load instruction.
///
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child. /// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
///
pub fn build_load( pub fn build_load(
&self, &self,
pointer: Pointer<'ctx>, pointer: Pointer<'ctx>,
@@ -784,11 +717,8 @@ where
} }
} }
///
/// Builds a stack store instruction. /// Builds a stack store instruction.
///
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child. /// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
///
pub fn build_store<V>(&self, pointer: Pointer<'ctx>, value: V) -> anyhow::Result<()> pub fn build_store<V>(&self, pointer: Pointer<'ctx>, value: V) -> anyhow::Result<()>
where where
V: BasicValue<'ctx>, V: BasicValue<'ctx>,
@@ -893,9 +823,7 @@ where
.expect("byte_swap should return a value") .expect("byte_swap should return a value")
} }
///
/// Builds a GEP instruction. /// Builds a GEP instruction.
///
pub fn build_gep<T>( pub fn build_gep<T>(
&self, &self,
pointer: Pointer<'ctx>, pointer: Pointer<'ctx>,
@@ -917,11 +845,8 @@ where
Pointer::new(element_type, pointer.address_space, value) Pointer::new(element_type, pointer.address_space, value)
} }
///
/// Builds a conditional branch. /// Builds a conditional branch.
///
/// Checks if there are no other terminators in the block. /// Checks if there are no other terminators in the block.
///
pub fn build_conditional_branch( pub fn build_conditional_branch(
&self, &self,
comparison: inkwell::values::IntValue<'ctx>, comparison: inkwell::values::IntValue<'ctx>,
@@ -938,11 +863,8 @@ where
Ok(()) Ok(())
} }
///
/// Builds an unconditional branch. /// Builds an unconditional branch.
///
/// Checks if there are no other terminators in the block. /// Checks if there are no other terminators in the block.
///
pub fn build_unconditional_branch( pub fn build_unconditional_branch(
&self, &self,
destination_block: inkwell::basic_block::BasicBlock<'ctx>, destination_block: inkwell::basic_block::BasicBlock<'ctx>,
@@ -956,9 +878,7 @@ where
.unwrap(); .unwrap();
} }
///
/// Builds a call. /// Builds a call.
///
pub fn build_call( pub fn build_call(
&self, &self,
function: FunctionDeclaration<'ctx>, function: FunctionDeclaration<'ctx>,
@@ -983,11 +903,8 @@ where
call_site_value.try_as_basic_value().left() call_site_value.try_as_basic_value().left()
} }
///
/// Builds an invoke. /// Builds an invoke.
///
/// Is defaulted to a call if there is no global exception handler. /// Is defaulted to a call if there is no global exception handler.
///
pub fn build_invoke( pub fn build_invoke(
&self, &self,
function: FunctionDeclaration<'ctx>, function: FunctionDeclaration<'ctx>,
@@ -1072,13 +989,10 @@ where
return_pointer.map(|pointer| self.build_load(pointer, "invoke_result").unwrap()) return_pointer.map(|pointer| self.build_load(pointer, "invoke_result").unwrap())
} }
///
/// Builds an invoke of local call covered with an exception handler. /// Builds an invoke of local call covered with an exception handler.
///
/// Yul does not the exception handling, so the user can declare a special handling function /// Yul does not the exception handling, so the user can declare a special handling function
/// called (see constant `ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER`. If the enclosed function /// called (see constant `ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER`. If the enclosed function
/// panics, the control flow will be transferred to the exception handler. /// panics, the control flow will be transferred to the exception handler.
///
pub fn build_invoke_near_call_abi( pub fn build_invoke_near_call_abi(
&self, &self,
_function: FunctionDeclaration<'ctx>, _function: FunctionDeclaration<'ctx>,
@@ -1088,11 +1002,8 @@ where
unimplemented!() unimplemented!()
} }
///
/// Builds a memory copy call. /// Builds a memory copy call.
///
/// Sets the alignment to `1`, since all non-stack memory pages have such alignment. /// Sets the alignment to `1`, since all non-stack memory pages have such alignment.
///
pub fn build_memcpy( pub fn build_memcpy(
&self, &self,
_function: FunctionDeclaration<'ctx>, _function: FunctionDeclaration<'ctx>,
@@ -1108,12 +1019,9 @@ where
Ok(()) Ok(())
} }
///
/// Builds a memory copy call for the return data. /// Builds a memory copy call for the return data.
///
/// Sets the output length to `min(output_length, return_data_size` and calls the default /// Sets the output length to `min(output_length, return_data_size` and calls the default
/// generic page memory copy builder. /// generic page memory copy builder.
///
pub fn build_memcpy_return_data( pub fn build_memcpy_return_data(
&self, &self,
function: FunctionDeclaration<'ctx>, function: FunctionDeclaration<'ctx>,
@@ -1159,11 +1067,8 @@ where
Ok(()) Ok(())
} }
///
/// Builds a return. /// Builds a return.
///
/// Checks if there are no other terminators in the block. /// Checks if there are no other terminators in the block.
///
pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) { pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) {
if self.basic_block().get_terminator().is_some() { if self.basic_block().get_terminator().is_some() {
return; return;
@@ -1172,11 +1077,8 @@ where
self.builder.build_return(value).unwrap(); self.builder.build_return(value).unwrap();
} }
///
/// Builds an unreachable. /// Builds an unreachable.
///
/// Checks if there are no other terminators in the block. /// Checks if there are no other terminators in the block.
///
pub fn build_unreachable(&self) { pub fn build_unreachable(&self) {
if self.basic_block().get_terminator().is_some() { if self.basic_block().get_terminator().is_some() {
return; return;
@@ -1185,14 +1087,11 @@ where
self.builder.build_unreachable().unwrap(); self.builder.build_unreachable().unwrap();
} }
///
/// Builds a long contract exit sequence. /// Builds a long contract exit sequence.
///
/// The deploy code does not return the runtime code like in EVM. Instead, it returns some /// The deploy code does not return the runtime code like in EVM. Instead, it returns some
/// additional contract metadata, e.g. the array of immutables. /// additional contract metadata, e.g. the array of immutables.
/// The deploy code uses the auxiliary heap for the return, because otherwise it is not possible /// The deploy code uses the auxiliary heap for the return, because otherwise it is not possible
/// to allocate memory together with the Yul allocator safely. /// to allocate memory together with the Yul allocator safely.
///
pub fn build_exit( pub fn build_exit(
&self, &self,
flags: inkwell::values::IntValue<'ctx>, flags: inkwell::values::IntValue<'ctx>,
@@ -1230,7 +1129,6 @@ where
} }
/// Truncate a memory offset into 32 bits, trapping if it doesn't fit. /// Truncate a memory offset into 32 bits, trapping if it doesn't fit.
///
/// Pointers are represented as opaque 256 bit integer values in EVM. /// Pointers are represented as opaque 256 bit integer values in EVM.
/// In practice, they should never exceed a 32 bit value. However, we /// In practice, they should never exceed a 32 bit value. However, we
/// still protect against this possibility here. /// still protect against this possibility here.
@@ -1287,7 +1185,6 @@ where
/// Call PolkaVM `sbrk` for extending the heap by `size`, /// Call PolkaVM `sbrk` for extending the heap by `size`,
/// trapping the contract if the call failed. /// trapping the contract if the call failed.
///
/// Returns the end of memory pointer. /// Returns the end of memory pointer.
pub fn build_heap_alloc( pub fn build_heap_alloc(
&self, &self,
@@ -1316,7 +1213,6 @@ where
/// Returns a pointer to `offset` into the heap, allocating /// Returns a pointer to `offset` into the heap, allocating
/// enough memory if `offset + length` would be out of bounds. /// enough memory if `offset + length` would be out of bounds.
///
/// # Panics /// # Panics
/// Assumes `offset` and `length` to be an i32 value. /// Assumes `offset` and `length` to be an i32 value.
pub fn build_heap_gep( pub fn build_heap_gep(
@@ -1369,9 +1265,7 @@ where
)) ))
} }
///
/// Writes the ABI pointer to the global variable. /// Writes the ABI pointer to the global variable.
///
pub fn write_abi_pointer(&mut self, pointer: Pointer<'ctx>, global_name: &str) { pub fn write_abi_pointer(&mut self, pointer: Pointer<'ctx>, global_name: &str) {
self.set_global( self.set_global(
global_name, global_name,
@@ -1381,9 +1275,7 @@ where
); );
} }
///
/// Writes the ABI data size to the global variable. /// Writes the ABI data size to the global variable.
///
pub fn write_abi_data_size(&mut self, _pointer: Pointer<'ctx>, _global_name: &str) { pub fn write_abi_data_size(&mut self, _pointer: Pointer<'ctx>, _global_name: &str) {
/* /*
let abi_pointer_value = self let abi_pointer_value = self
@@ -1416,46 +1308,34 @@ where
*/ */
} }
///
/// Returns a boolean type constant. /// Returns a boolean type constant.
///
pub fn bool_const(&self, value: bool) -> inkwell::values::IntValue<'ctx> { pub fn bool_const(&self, value: bool) -> inkwell::values::IntValue<'ctx> {
self.bool_type().const_int(u64::from(value), false) self.bool_type().const_int(u64::from(value), false)
} }
///
/// Returns an integer type constant. /// Returns an integer type constant.
///
pub fn integer_const(&self, bit_length: usize, value: u64) -> inkwell::values::IntValue<'ctx> { pub fn integer_const(&self, bit_length: usize, value: u64) -> inkwell::values::IntValue<'ctx> {
self.integer_type(bit_length).const_int(value, false) self.integer_type(bit_length).const_int(value, false)
} }
///
/// Returns a 256-bit field type constant. /// Returns a 256-bit field type constant.
///
pub fn field_const(&self, value: u64) -> inkwell::values::IntValue<'ctx> { pub fn field_const(&self, value: u64) -> inkwell::values::IntValue<'ctx> {
self.field_type().const_int(value, false) self.field_type().const_int(value, false)
} }
///
/// Returns a 256-bit field type undefined value. /// Returns a 256-bit field type undefined value.
///
pub fn field_undef(&self) -> inkwell::values::IntValue<'ctx> { pub fn field_undef(&self) -> inkwell::values::IntValue<'ctx> {
self.field_type().get_undef() self.field_type().get_undef()
} }
///
/// Returns a field type constant from a decimal string. /// Returns a field type constant from a decimal string.
///
pub fn field_const_str_dec(&self, value: &str) -> inkwell::values::IntValue<'ctx> { pub fn field_const_str_dec(&self, value: &str) -> inkwell::values::IntValue<'ctx> {
self.field_type() self.field_type()
.const_int_from_string(value, inkwell::types::StringRadix::Decimal) .const_int_from_string(value, inkwell::types::StringRadix::Decimal)
.unwrap_or_else(|| panic!("Invalid string constant `{value}`")) .unwrap_or_else(|| panic!("Invalid string constant `{value}`"))
} }
///
/// Returns a field type constant from a hexadecimal string. /// Returns a field type constant from a hexadecimal string.
///
pub fn field_const_str_hex(&self, value: &str) -> inkwell::values::IntValue<'ctx> { pub fn field_const_str_hex(&self, value: &str) -> inkwell::values::IntValue<'ctx> {
self.field_type() self.field_type()
.const_int_from_string( .const_int_from_string(
@@ -1465,31 +1345,23 @@ where
.unwrap_or_else(|| panic!("Invalid string constant `{value}`")) .unwrap_or_else(|| panic!("Invalid string constant `{value}`"))
} }
///
/// Returns the void type. /// Returns the void type.
///
pub fn void_type(&self) -> inkwell::types::VoidType<'ctx> { pub fn void_type(&self) -> inkwell::types::VoidType<'ctx> {
self.llvm.void_type() self.llvm.void_type()
} }
///
/// Returns the boolean type. /// Returns the boolean type.
///
pub fn bool_type(&self) -> inkwell::types::IntType<'ctx> { pub fn bool_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm.bool_type() self.llvm.bool_type()
} }
///
/// Returns the default byte type. /// Returns the default byte type.
///
pub fn byte_type(&self) -> inkwell::types::IntType<'ctx> { pub fn byte_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_BYTE as u32) .custom_width_int_type(revive_common::BIT_LENGTH_BYTE as u32)
} }
///
/// Returns the integer type of the specified bit-length. /// Returns the integer type of the specified bit-length.
///
pub fn integer_type(&self, bit_length: usize) -> inkwell::types::IntType<'ctx> { pub fn integer_type(&self, bit_length: usize) -> inkwell::types::IntType<'ctx> {
self.llvm.custom_width_int_type(bit_length as u32) self.llvm.custom_width_int_type(bit_length as u32)
} }
@@ -1505,17 +1377,13 @@ where
.custom_width_int_type(revive_common::BIT_LENGTH_VALUE as u32) .custom_width_int_type(revive_common::BIT_LENGTH_VALUE as u32)
} }
///
/// Returns the default field type. /// Returns the default field type.
///
pub fn field_type(&self) -> inkwell::types::IntType<'ctx> { pub fn field_type(&self) -> inkwell::types::IntType<'ctx> {
self.llvm self.llvm
.custom_width_int_type(revive_common::BIT_LENGTH_FIELD as u32) .custom_width_int_type(revive_common::BIT_LENGTH_FIELD as u32)
} }
///
/// Returns the array type with the specified length. /// Returns the array type with the specified length.
///
pub fn array_type<T>(&self, element_type: T, length: usize) -> inkwell::types::ArrayType<'ctx> pub fn array_type<T>(&self, element_type: T, length: usize) -> inkwell::types::ArrayType<'ctx>
where where
T: BasicType<'ctx>, T: BasicType<'ctx>,
@@ -1523,9 +1391,7 @@ where
element_type.array_type(length as u32) element_type.array_type(length as u32)
} }
///
/// Returns the structure type with specified fields. /// Returns the structure type with specified fields.
///
pub fn structure_type<T>(&self, field_types: &[T]) -> inkwell::types::StructType<'ctx> pub fn structure_type<T>(&self, field_types: &[T]) -> inkwell::types::StructType<'ctx>
where where
T: BasicType<'ctx>, T: BasicType<'ctx>,
@@ -1535,9 +1401,7 @@ where
self.llvm.struct_type(field_types.as_slice(), false) self.llvm.struct_type(field_types.as_slice(), false)
} }
///
/// Returns a Yul function type with the specified arguments and number of return values. /// Returns a Yul function type with the specified arguments and number of return values.
///
pub fn function_type<T>( pub fn function_type<T>(
&self, &self,
argument_types: Vec<T>, argument_types: Vec<T>,
@@ -1570,11 +1434,8 @@ where
} }
} }
///
/// Modifies the call site value, setting the default attributes. /// Modifies the call site value, setting the default attributes.
///
/// The attributes only affect the LLVM optimizations. /// The attributes only affect the LLVM optimizations.
///
pub fn modify_call_site_value( pub fn modify_call_site_value(
&self, &self,
arguments: &[inkwell::values::BasicValueEnum<'ctx>], arguments: &[inkwell::values::BasicValueEnum<'ctx>],
@@ -1680,124 +1541,92 @@ where
} }
} }
///
/// Sets the Solidity data. /// Sets the Solidity data.
///
pub fn set_solidity_data(&mut self, data: SolidityData) { pub fn set_solidity_data(&mut self, data: SolidityData) {
self.solidity_data = Some(data); self.solidity_data = Some(data);
} }
///
/// Returns the Solidity data reference. /// Returns the Solidity data reference.
///
/// # Panics /// # Panics
/// If the Solidity data has not been initialized. /// If the Solidity data has not been initialized.
///
pub fn solidity(&self) -> &SolidityData { pub fn solidity(&self) -> &SolidityData {
self.solidity_data self.solidity_data
.as_ref() .as_ref()
.expect("The Solidity data must have been initialized") .expect("The Solidity data must have been initialized")
} }
///
/// Returns the Solidity data mutable reference. /// Returns the Solidity data mutable reference.
///
/// # Panics /// # Panics
/// If the Solidity data has not been initialized. /// If the Solidity data has not been initialized.
///
pub fn solidity_mut(&mut self) -> &mut SolidityData { pub fn solidity_mut(&mut self) -> &mut SolidityData {
self.solidity_data self.solidity_data
.as_mut() .as_mut()
.expect("The Solidity data must have been initialized") .expect("The Solidity data must have been initialized")
} }
///
/// Sets the Yul data. /// Sets the Yul data.
///
pub fn set_yul_data(&mut self, data: YulData) { pub fn set_yul_data(&mut self, data: YulData) {
self.yul_data = Some(data); self.yul_data = Some(data);
} }
///
/// Returns the Yul data reference. /// Returns the Yul data reference.
///
/// # Panics /// # Panics
/// If the Yul data has not been initialized. /// If the Yul data has not been initialized.
///
pub fn yul(&self) -> &YulData { pub fn yul(&self) -> &YulData {
self.yul_data self.yul_data
.as_ref() .as_ref()
.expect("The Yul data must have been initialized") .expect("The Yul data must have been initialized")
} }
///
/// Returns the Yul data mutable reference. /// Returns the Yul data mutable reference.
///
/// # Panics /// # Panics
/// If the Yul data has not been initialized. /// If the Yul data has not been initialized.
///
pub fn yul_mut(&mut self) -> &mut YulData { pub fn yul_mut(&mut self) -> &mut YulData {
self.yul_data self.yul_data
.as_mut() .as_mut()
.expect("The Yul data must have been initialized") .expect("The Yul data must have been initialized")
} }
///
/// Sets the EVM legacy assembly data. /// Sets the EVM legacy assembly data.
///
pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) { pub fn set_evmla_data(&mut self, data: EVMLAData<'ctx>) {
self.evmla_data = Some(data); self.evmla_data = Some(data);
} }
///
/// Returns the EVM legacy assembly data reference. /// Returns the EVM legacy assembly data reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evmla(&self) -> &EVMLAData<'ctx> { pub fn evmla(&self) -> &EVMLAData<'ctx> {
self.evmla_data self.evmla_data
.as_ref() .as_ref()
.expect("The EVMLA data must have been initialized") .expect("The EVMLA data must have been initialized")
} }
///
/// Returns the EVM legacy assembly data mutable reference. /// Returns the EVM legacy assembly data mutable reference.
///
/// # Panics /// # Panics
/// If the EVM data has not been initialized. /// If the EVM data has not been initialized.
///
pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> { pub fn evmla_mut(&mut self) -> &mut EVMLAData<'ctx> {
self.evmla_data self.evmla_data
.as_mut() .as_mut()
.expect("The EVMLA data must have been initialized") .expect("The EVMLA data must have been initialized")
} }
///
/// Sets the EVM legacy assembly data. /// Sets the EVM legacy assembly data.
///
pub fn set_vyper_data(&mut self, data: VyperData) { pub fn set_vyper_data(&mut self, data: VyperData) {
self.vyper_data = Some(data); self.vyper_data = Some(data);
} }
///
/// Returns the Vyper data reference. /// Returns the Vyper data reference.
///
/// # Panics /// # Panics
/// If the Vyper data has not been initialized. /// If the Vyper data has not been initialized.
///
pub fn vyper(&self) -> &VyperData { pub fn vyper(&self) -> &VyperData {
self.vyper_data self.vyper_data
.as_ref() .as_ref()
.expect("The Solidity data must have been initialized") .expect("The Solidity data must have been initialized")
} }
///
/// Returns the current number of immutables values in the contract. /// Returns the current number of immutables values in the contract.
///
/// If the size is set manually, then it is returned. Otherwise, the number of elements in /// If the size is set manually, then it is returned. Otherwise, the number of elements in
/// the identifier-to-offset mapping tree is returned. /// the identifier-to-offset mapping tree is returned.
///
pub fn immutables_size(&self) -> anyhow::Result<usize> { pub fn immutables_size(&self) -> anyhow::Result<usize> {
if let Some(solidity) = self.solidity_data.as_ref() { if let Some(solidity) = self.solidity_data.as_ref() {
Ok(solidity.immutables_size()) Ok(solidity.immutables_size())
@@ -1808,9 +1637,7 @@ where
} }
} }
///
/// Whether the system mode is enabled. /// Whether the system mode is enabled.
///
pub fn is_system_mode(&self) -> bool { pub fn is_system_mode(&self) -> bool {
self.yul_data self.yul_data
.as_ref() .as_ref()
@@ -1,6 +1,4 @@
//!
//! The LLVM pointer. //! The LLVM pointer.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
@@ -9,9 +7,7 @@ use crate::eravm::context::global::Global;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// The LLVM pointer. /// The LLVM pointer.
///
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Pointer<'ctx> { pub struct Pointer<'ctx> {
/// The pointee type. /// The pointee type.
@@ -23,9 +19,7 @@ pub struct Pointer<'ctx> {
} }
impl<'ctx> Pointer<'ctx> { impl<'ctx> Pointer<'ctx> {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new<T>( pub fn new<T>(
r#type: T, r#type: T,
address_space: AddressSpace, address_space: AddressSpace,
@@ -41,9 +35,7 @@ impl<'ctx> Pointer<'ctx> {
} }
} }
///
/// Wraps a 256-bit primitive type pointer. /// Wraps a 256-bit primitive type pointer.
///
pub fn new_stack_field<D>( pub fn new_stack_field<D>(
context: &Context<'ctx, D>, context: &Context<'ctx, D>,
value: inkwell::values::PointerValue<'ctx>, value: inkwell::values::PointerValue<'ctx>,
@@ -58,9 +50,7 @@ impl<'ctx> Pointer<'ctx> {
} }
} }
///
/// Creates a new pointer with the specified `offset`. /// Creates a new pointer with the specified `offset`.
///
pub fn new_with_offset<D, T>( pub fn new_with_offset<D, T>(
context: &Context<'ctx, D>, context: &Context<'ctx, D>,
address_space: AddressSpace, address_space: AddressSpace,
@@ -86,9 +76,7 @@ impl<'ctx> Pointer<'ctx> {
Self::new(r#type, address_space, value) Self::new(r#type, address_space, value)
} }
///
/// Casts the pointer into another type. /// Casts the pointer into another type.
///
pub fn cast<T>(self, r#type: T) -> Self pub fn cast<T>(self, r#type: T) -> Self
where where
T: BasicType<'ctx>, T: BasicType<'ctx>,
@@ -1,14 +1,9 @@
//!
//! The LLVM IR generator Solidity data. //! The LLVM IR generator Solidity data.
//!
use std::collections::BTreeMap; use std::collections::BTreeMap;
///
/// The LLVM IR generator Solidity data. /// The LLVM IR generator Solidity data.
///
/// Describes some data that is only relevant to Solidity. /// Describes some data that is only relevant to Solidity.
///
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct SolidityData { pub struct SolidityData {
/// The immutables identifier-to-offset mapping. Is only used by Solidity due to /// The immutables identifier-to-offset mapping. Is only used by Solidity due to
@@ -17,25 +12,18 @@ pub struct SolidityData {
} }
impl SolidityData { impl SolidityData {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
///
/// Returns the current number of immutables values in the contract. /// Returns the current number of immutables values in the contract.
///
pub fn immutables_size(&self) -> usize { pub fn immutables_size(&self) -> usize {
self.immutables.len() * revive_common::BYTE_LENGTH_FIELD self.immutables.len() * revive_common::BYTE_LENGTH_FIELD
} }
///
/// Allocates memory for an immutable value in the auxiliary heap. /// Allocates memory for an immutable value in the auxiliary heap.
///
/// If the identifier is already known, just returns its offset. /// If the identifier is already known, just returns its offset.
///
pub fn allocate_immutable(&mut self, identifier: &str) -> usize { pub fn allocate_immutable(&mut self, identifier: &str) -> usize {
let number_of_elements = self.immutables.len(); let number_of_elements = self.immutables.len();
let new_offset = number_of_elements * revive_common::BYTE_LENGTH_FIELD; let new_offset = number_of_elements * revive_common::BYTE_LENGTH_FIELD;
@@ -45,11 +33,8 @@ impl SolidityData {
.or_insert(new_offset) .or_insert(new_offset)
} }
///
/// Gets the offset of the immutable value. /// Gets the offset of the immutable value.
///
/// If the value is not yet allocated, then it is done forcibly. /// If the value is not yet allocated, then it is done forcibly.
///
pub fn get_or_allocate_immutable(&mut self, identifier: &str) -> usize { pub fn get_or_allocate_immutable(&mut self, identifier: &str) -> usize {
match self.immutables.get(identifier).copied() { match self.immutables.get(identifier).copied() {
Some(offset) => offset, Some(offset) => offset,
@@ -1,6 +1,4 @@
//!
//! The LLVM IR generator context tests. //! The LLVM IR generator context tests.
//!
use crate::eravm::context::attribute::Attribute; use crate::eravm::context::attribute::Attribute;
use crate::eravm::context::Context; use crate::eravm::context::Context;
@@ -1,12 +1,7 @@
//!
//! The LLVM IR generator Vyper data. //! The LLVM IR generator Vyper data.
//!
///
/// The LLVM IR generator Vyper data. /// The LLVM IR generator Vyper data.
///
/// Describes some data that is only relevant to Vyper. /// Describes some data that is only relevant to Vyper.
///
#[derive(Debug)] #[derive(Debug)]
pub struct VyperData { pub struct VyperData {
/// The immutables size tracker. Stores the size in bytes. /// The immutables size tracker. Stores the size in bytes.
@@ -17,9 +12,7 @@ pub struct VyperData {
} }
impl VyperData { impl VyperData {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(immutables_size: usize, is_forwarder_used: bool) -> Self { pub fn new(immutables_size: usize, is_forwarder_used: bool) -> Self {
Self { Self {
immutables_size, immutables_size,
@@ -27,23 +20,17 @@ impl VyperData {
} }
} }
///
/// Returns the size of the immutables data of the contract. /// Returns the size of the immutables data of the contract.
///
pub fn immutables_size(&self) -> usize { pub fn immutables_size(&self) -> usize {
self.immutables_size self.immutables_size
} }
///
/// Sets the forwarder usage flag. /// Sets the forwarder usage flag.
///
pub fn set_is_forwarder_used(&mut self) { pub fn set_is_forwarder_used(&mut self) {
self.is_forwarder_used = true; self.is_forwarder_used = true;
} }
///
/// Returns the forwarder usage flag. /// Returns the forwarder usage flag.
///
pub fn is_forwarder_used(&self) -> bool { pub fn is_forwarder_used(&self) -> bool {
self.is_forwarder_used self.is_forwarder_used
} }
@@ -1,16 +1,11 @@
//!
//! The LLVM IR generator Yul data. //! The LLVM IR generator Yul data.
//!
use std::collections::BTreeMap; use std::collections::BTreeMap;
use num::Zero; use num::Zero;
///
/// The LLVM IR generator Yul data. /// The LLVM IR generator Yul data.
///
/// Describes some data that is only relevant to Yul. /// Describes some data that is only relevant to Yul.
///
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct YulData { pub struct YulData {
/// The system mode flag. /// The system mode flag.
@@ -22,9 +17,7 @@ pub struct YulData {
} }
impl YulData { impl YulData {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(is_system_mode: bool) -> Self { pub fn new(is_system_mode: bool) -> Self {
Self { Self {
is_system_mode, is_system_mode,
@@ -32,16 +25,12 @@ impl YulData {
} }
} }
///
/// Whether the system mode is enabled. /// Whether the system mode is enabled.
///
pub fn is_system_mode(&self) -> bool { pub fn is_system_mode(&self) -> bool {
self.is_system_mode self.is_system_mode
} }
///
/// Declares a temporary constant array representation. /// Declares a temporary constant array representation.
///
pub fn const_array_declare(&mut self, index: u8, size: u16) -> anyhow::Result<()> { pub fn const_array_declare(&mut self, index: u8, size: u16) -> anyhow::Result<()> {
if self.const_arrays.contains_key(&index) { if self.const_arrays.contains_key(&index) {
anyhow::bail!( anyhow::bail!(
@@ -56,9 +45,7 @@ impl YulData {
Ok(()) Ok(())
} }
///
/// Sets a value in the constant array representation. /// Sets a value in the constant array representation.
///
pub fn const_array_set( pub fn const_array_set(
&mut self, &mut self,
index: u8, index: u8,
@@ -81,9 +68,7 @@ impl YulData {
Ok(()) Ok(())
} }
///
/// Finalizes the constant array declaration. /// Finalizes the constant array declaration.
///
pub fn const_array_take(&mut self, index: u8) -> anyhow::Result<Vec<num::BigUint>> { pub fn const_array_take(&mut self, index: u8) -> anyhow::Result<Vec<num::BigUint>> {
self.const_arrays.remove(&index).ok_or_else(|| { self.const_arrays.remove(&index).ok_or_else(|| {
anyhow::anyhow!("The constant array with index {} is not declared", index) anyhow::anyhow!("The constant array with index {} is not declared", index)
@@ -1,15 +1,11 @@
//!
//! Translates the arithmetic operations. //! Translates the arithmetic operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the arithmetic addition. /// Translates the arithmetic addition.
///
pub fn addition<'ctx, D>( pub fn addition<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -24,9 +20,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the arithmetic subtraction. /// Translates the arithmetic subtraction.
///
pub fn subtraction<'ctx, D>( pub fn subtraction<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -41,9 +35,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the arithmetic multiplication. /// Translates the arithmetic multiplication.
///
pub fn multiplication<'ctx, D>( pub fn multiplication<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -58,9 +50,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the arithmetic division. /// Translates the arithmetic division.
///
pub fn division<'ctx, D>( pub fn division<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -75,9 +65,7 @@ where
.into()) .into())
} }
///
/// Translates the arithmetic remainder. /// Translates the arithmetic remainder.
///
pub fn remainder<'ctx, D>( pub fn remainder<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -98,13 +86,10 @@ where
.expect("Always exists")) .expect("Always exists"))
} }
///
/// Translates the signed arithmetic division. /// Translates the signed arithmetic division.
///
/// Two differences between the EVM and LLVM IR: /// Two differences between the EVM and LLVM IR:
/// 1. In case of division by zero, 0 is returned. /// 1. In case of division by zero, 0 is returned.
/// 2. In case of overflow, the first argument is returned. /// 2. In case of overflow, the first argument is returned.
///
pub fn division_signed<'ctx, D>( pub fn division_signed<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -125,9 +110,7 @@ where
.expect("Always exists")) .expect("Always exists"))
} }
///
/// Translates the signed arithmetic remainder. /// Translates the signed arithmetic remainder.
///
pub fn remainder_signed<'ctx, D>( pub fn remainder_signed<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -1,15 +1,11 @@
//!
//! Translates the bitwise operations. //! Translates the bitwise operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the bitwise OR. /// Translates the bitwise OR.
///
pub fn or<'ctx, D>( pub fn or<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -24,9 +20,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the bitwise XOR. /// Translates the bitwise XOR.
///
pub fn xor<'ctx, D>( pub fn xor<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -41,9 +35,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the bitwise AND. /// Translates the bitwise AND.
///
pub fn and<'ctx, D>( pub fn and<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -58,9 +50,7 @@ where
.as_basic_value_enum()) .as_basic_value_enum())
} }
///
/// Translates the bitwise shift left. /// Translates the bitwise shift left.
///
pub fn shift_left<'ctx, D>( pub fn shift_left<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
shift: inkwell::values::IntValue<'ctx>, shift: inkwell::values::IntValue<'ctx>,
@@ -98,9 +88,7 @@ where
context.build_load(result_pointer, "shift_left_result") context.build_load(result_pointer, "shift_left_result")
} }
///
/// Translates the bitwise shift right. /// Translates the bitwise shift right.
///
pub fn shift_right<'ctx, D>( pub fn shift_right<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
shift: inkwell::values::IntValue<'ctx>, shift: inkwell::values::IntValue<'ctx>,
@@ -140,9 +128,7 @@ where
context.build_load(result_pointer, "shift_right_result") context.build_load(result_pointer, "shift_right_result")
} }
///
/// Translates the arithmetic bitwise shift right. /// Translates the arithmetic bitwise shift right.
///
pub fn shift_right_arithmetic<'ctx, D>( pub fn shift_right_arithmetic<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
shift: inkwell::values::IntValue<'ctx>, shift: inkwell::values::IntValue<'ctx>,
@@ -211,9 +197,7 @@ where
context.build_load(result_pointer, "shift_right_arithmetic_result") context.build_load(result_pointer, "shift_right_arithmetic_result")
} }
///
/// Translates the `byte` instruction. /// Translates the `byte` instruction.
///
pub fn byte<'ctx, D>( pub fn byte<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -1,6 +1,4 @@
//!
//! Translates a contract call. //! Translates a contract call.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
@@ -9,12 +7,9 @@ use crate::eravm::context::function::declaration::Declaration as FunctionDeclara
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates a contract call. /// Translates a contract call.
///
/// If the `simulation_address` is specified, the call is substituted with another instruction /// If the `simulation_address` is specified, the call is substituted with another instruction
/// according to the specification. /// according to the specification.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn default<'ctx, D>( pub fn default<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
@@ -95,9 +90,7 @@ where
*/ */
} }
///
/// Translates the Yul `linkersymbol` instruction. /// Translates the Yul `linkersymbol` instruction.
///
pub fn linker_symbol<'ctx, D>( pub fn linker_symbol<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
mut arguments: [Argument<'ctx>; 1], mut arguments: [Argument<'ctx>; 1],
@@ -1,6 +1,4 @@
//!
//! Translates the calldata instructions. //! Translates the calldata instructions.
//!
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::pointer::Pointer; use crate::eravm::context::pointer::Pointer;
@@ -8,9 +6,7 @@ use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
use inkwell::types::BasicType; use inkwell::types::BasicType;
///
/// Translates the calldata load. /// Translates the calldata load.
///
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -33,9 +29,7 @@ where
.map(|value| context.build_byte_swap(value)) .map(|value| context.build_byte_swap(value))
} }
///
/// Translates the calldata size. /// Translates the calldata size.
///
pub fn size<'ctx, D>( pub fn size<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -47,9 +41,7 @@ where
Ok(value) Ok(value)
} }
///
/// Translates the calldata copy. /// Translates the calldata copy.
///
pub fn copy<'ctx, D>( pub fn copy<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
destination_offset: inkwell::values::IntValue<'ctx>, destination_offset: inkwell::values::IntValue<'ctx>,
@@ -1,17 +1,12 @@
//!
//! Translates the comparison operations. //! Translates the comparison operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the comparison operations. /// Translates the comparison operations.
///
/// There is not difference between the EVM and LLVM IR behaviors. /// There is not difference between the EVM and LLVM IR behaviors.
///
pub fn compare<'ctx, D>( pub fn compare<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -1,15 +1,11 @@
//!
//! Translates the context getter instructions. //! Translates the context getter instructions.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `gas_limit` instruction. /// Translates the `gas_limit` instruction.
///
pub fn gas_limit<'ctx, D>( pub fn gas_limit<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -19,9 +15,7 @@ where
todo!() todo!()
} }
///
/// Translates the `gas_price` instruction. /// Translates the `gas_price` instruction.
///
pub fn gas_price<'ctx, D>( pub fn gas_price<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -31,9 +25,7 @@ where
todo!() todo!()
} }
///
/// Translates the `tx.origin` instruction. /// Translates the `tx.origin` instruction.
///
pub fn origin<'ctx, D>( pub fn origin<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -43,9 +35,7 @@ where
todo!() todo!()
} }
///
/// Translates the `chain_id` instruction. /// Translates the `chain_id` instruction.
///
pub fn chain_id<'ctx, D>( pub fn chain_id<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -55,9 +45,7 @@ where
todo!() todo!()
} }
///
/// Translates the `block_number` instruction. /// Translates the `block_number` instruction.
///
pub fn block_number<'ctx, D>( pub fn block_number<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -67,9 +55,7 @@ where
todo!() todo!()
} }
///
/// Translates the `block_timestamp` instruction. /// Translates the `block_timestamp` instruction.
///
pub fn block_timestamp<'ctx, D>( pub fn block_timestamp<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -79,9 +65,7 @@ where
todo!() todo!()
} }
///
/// Translates the `block_hash` instruction. /// Translates the `block_hash` instruction.
///
pub fn block_hash<'ctx, D>( pub fn block_hash<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
_index: inkwell::values::IntValue<'ctx>, _index: inkwell::values::IntValue<'ctx>,
@@ -92,9 +76,7 @@ where
todo!() todo!()
} }
///
/// Translates the `difficulty` instruction. /// Translates the `difficulty` instruction.
///
pub fn difficulty<'ctx, D>( pub fn difficulty<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -104,9 +86,7 @@ where
todo!() todo!()
} }
///
/// Translates the `coinbase` instruction. /// Translates the `coinbase` instruction.
///
pub fn coinbase<'ctx, D>( pub fn coinbase<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -116,9 +96,7 @@ where
todo!() todo!()
} }
///
/// Translates the `basefee` instruction. /// Translates the `basefee` instruction.
///
pub fn basefee<'ctx, D>( pub fn basefee<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -128,9 +106,7 @@ where
todo!() todo!()
} }
///
/// Translates the `msize` instruction. /// Translates the `msize` instruction.
///
pub fn msize<'ctx, D>( pub fn msize<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -1,6 +1,4 @@
//!
//! Translates the contract creation instructions. //! Translates the contract creation instructions.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use num::Zero; use num::Zero;
@@ -11,11 +9,8 @@ use crate::eravm::context::function::runtime::Runtime;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the contract `create` instruction. /// Translates the contract `create` instruction.
///
/// The instruction is simulated by a call to a system contract. /// The instruction is simulated by a call to a system contract.
///
pub fn create<'ctx, D>( pub fn create<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
value: inkwell::values::IntValue<'ctx>, value: inkwell::values::IntValue<'ctx>,
@@ -49,11 +44,8 @@ where
Ok(result) Ok(result)
} }
///
/// Translates the contract `create2` instruction. /// Translates the contract `create2` instruction.
///
/// The instruction is simulated by a call to a system contract. /// The instruction is simulated by a call to a system contract.
///
pub fn create2<'ctx, D>( pub fn create2<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
value: inkwell::values::IntValue<'ctx>, value: inkwell::values::IntValue<'ctx>,
@@ -88,12 +80,9 @@ where
Ok(result) Ok(result)
} }
///
/// Translates the contract hash instruction, which is actually used to set the hash of the contract /// Translates the contract hash instruction, which is actually used to set the hash of the contract
/// being created, or other related auxiliary data. /// being created, or other related auxiliary data.
///
/// Represents `dataoffset` in Yul and `PUSH [$]` in the EVM legacy assembly. /// Represents `dataoffset` in Yul and `PUSH [$]` in the EVM legacy assembly.
///
pub fn contract_hash<'ctx, D>( pub fn contract_hash<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
identifier: String, identifier: String,
@@ -132,20 +121,16 @@ where
Ok(Argument::new_with_original(hash_value, hash_string)) Ok(Argument::new_with_original(hash_value, hash_string))
} }
///
/// Translates the deployer call header size instruction, Usually, the header consists of: /// Translates the deployer call header size instruction, Usually, the header consists of:
/// - the deployer contract method signature /// - the deployer contract method signature
/// - the salt if the call is `create2`, or zero if the call is `create1` /// - the salt if the call is `create2`, or zero if the call is `create1`
/// - the hash of the bytecode of the contract whose instance is being created /// - the hash of the bytecode of the contract whose instance is being created
/// - the offset of the constructor arguments /// - the offset of the constructor arguments
/// - the length of the constructor arguments /// - the length of the constructor arguments
///
/// If the call is `create1`, the space for the salt is still allocated, because the memory for the /// If the call is `create1`, the space for the salt is still allocated, because the memory for the
/// header is allocated by the Yul or EVM legacy assembly before it is known which version of /// header is allocated by the Yul or EVM legacy assembly before it is known which version of
/// `create` is going to be used. /// `create` is going to be used.
///
/// Represents `datasize` in Yul and `PUSH #[$]` in the EVM legacy assembly. /// Represents `datasize` in Yul and `PUSH #[$]` in the EVM legacy assembly.
///
pub fn header_size<'ctx, D>( pub fn header_size<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
identifier: String, identifier: String,
@@ -1,13 +1,9 @@
//!
//! Translates the cryptographic operations. //! Translates the cryptographic operations.
//!
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `sha3` instruction. /// Translates the `sha3` instruction.
///
pub fn sha3<'ctx, D>( pub fn sha3<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -1,15 +1,11 @@
//!
//! Translates the value and balance operations. //! Translates the value and balance operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `gas` instruction. /// Translates the `gas` instruction.
///
pub fn gas<'ctx, D>( pub fn gas<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -19,9 +15,7 @@ where
Ok(context.integer_const(256, 0).as_basic_value_enum()) Ok(context.integer_const(256, 0).as_basic_value_enum())
} }
///
/// Translates the `value` instruction. /// Translates the `value` instruction.
///
pub fn value<'ctx, D>( pub fn value<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -67,9 +61,7 @@ where
Ok(value_extended.as_basic_value_enum()) Ok(value_extended.as_basic_value_enum())
} }
///
/// Translates the `balance` instructions. /// Translates the `balance` instructions.
///
pub fn balance<'ctx, D>( pub fn balance<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
_address: inkwell::values::IntValue<'ctx>, _address: inkwell::values::IntValue<'ctx>,
@@ -1,19 +1,13 @@
//!
//! Translates a log or event call. //! Translates a log or event call.
//!
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates a log or event call. /// Translates a log or event call.
///
/// The decoding logic is implemented in a system contract, which is called from here. /// The decoding logic is implemented in a system contract, which is called from here.
///
/// There are several cases of the translation for the sake of efficiency, since the front-end /// There are several cases of the translation for the sake of efficiency, since the front-end
/// emits topics and values sequentially by one, but the LLVM intrinsic and bytecode instruction /// emits topics and values sequentially by one, but the LLVM intrinsic and bytecode instruction
/// accept two at once. /// accept two at once.
///
pub fn log<'ctx, D>( pub fn log<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
_input_offset: inkwell::values::IntValue<'ctx>, _input_offset: inkwell::values::IntValue<'ctx>,
@@ -1,13 +1,9 @@
//!
//! Translates the external code operations. //! Translates the external code operations.
//!
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `extcodesize` instruction. /// Translates the `extcodesize` instruction.
///
pub fn size<'ctx, D>( pub fn size<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
_address: inkwell::values::IntValue<'ctx>, _address: inkwell::values::IntValue<'ctx>,
@@ -18,9 +14,7 @@ where
todo!() todo!()
} }
///
/// Translates the `extcodehash` instruction. /// Translates the `extcodehash` instruction.
///
pub fn hash<'ctx, D>( pub fn hash<'ctx, D>(
_context: &mut Context<'ctx, D>, _context: &mut Context<'ctx, D>,
_address: inkwell::values::IntValue<'ctx>, _address: inkwell::values::IntValue<'ctx>,
@@ -1,6 +1,4 @@
//!
//! Translates the contract immutable operations. //! Translates the contract immutable operations.
//!
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::code_type::CodeType; use crate::eravm::context::code_type::CodeType;
@@ -8,12 +6,9 @@ use crate::eravm::context::pointer::Pointer;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the contract immutable load. /// Translates the contract immutable load.
///
/// In the deploy code the values are read from the auxiliary heap. /// In the deploy code the values are read from the auxiliary heap.
/// In the runtime code they are requested from the system contract. /// In the runtime code they are requested from the system contract.
///
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
index: inkwell::values::IntValue<'ctx>, index: inkwell::values::IntValue<'ctx>,
@@ -54,14 +49,10 @@ where
} }
} }
///
/// Translates the contract immutable store. /// Translates the contract immutable store.
///
/// In the deploy code the values are written to the auxiliary heap at the predefined offset, /// In the deploy code the values are written to the auxiliary heap at the predefined offset,
/// being prepared for returning to the system contract for saving. /// being prepared for returning to the system contract for saving.
///
/// Ignored in the runtime code. /// Ignored in the runtime code.
///
pub fn store<'ctx, D>( pub fn store<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
index: inkwell::values::IntValue<'ctx>, index: inkwell::values::IntValue<'ctx>,
-10
View File
@@ -1,15 +1,11 @@
//!
//! Translates the mathematical operations. //! Translates the mathematical operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `addmod` instruction. /// Translates the `addmod` instruction.
///
pub fn add_mod<'ctx, D>( pub fn add_mod<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -32,9 +28,7 @@ where
.expect("Always exists")) .expect("Always exists"))
} }
///
/// Translates the `mulmod` instruction. /// Translates the `mulmod` instruction.
///
pub fn mul_mod<'ctx, D>( pub fn mul_mod<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
operand_1: inkwell::values::IntValue<'ctx>, operand_1: inkwell::values::IntValue<'ctx>,
@@ -57,9 +51,7 @@ where
.expect("Always exists")) .expect("Always exists"))
} }
///
/// Translates the `exp` instruction. /// Translates the `exp` instruction.
///
pub fn exponent<'ctx, D>( pub fn exponent<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
value: inkwell::values::IntValue<'ctx>, value: inkwell::values::IntValue<'ctx>,
@@ -77,9 +69,7 @@ where
.expect("Always exists")) .expect("Always exists"))
} }
///
/// Translates the `signextend` instruction. /// Translates the `signextend` instruction.
///
pub fn sign_extend<'ctx, D>( pub fn sign_extend<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
bytes: inkwell::values::IntValue<'ctx>, bytes: inkwell::values::IntValue<'ctx>,
@@ -1,17 +1,12 @@
//!
//! Translates the heap memory operations. //! Translates the heap memory operations.
//!
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::pointer::Pointer; use crate::eravm::context::pointer::Pointer;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `mload` instruction. /// Translates the `mload` instruction.
///
/// Uses the main heap. /// Uses the main heap.
///
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -29,11 +24,8 @@ where
context.build_load(pointer, "memory_load_result") context.build_load(pointer, "memory_load_result")
} }
///
/// Translates the `mstore` instruction. /// Translates the `mstore` instruction.
///
/// Uses the main heap. /// Uses the main heap.
///
pub fn store<'ctx, D>( pub fn store<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -53,11 +45,8 @@ where
Ok(()) Ok(())
} }
///
/// Translates the `mstore8` instruction. /// Translates the `mstore8` instruction.
///
/// Uses the main heap. /// Uses the main heap.
///
pub fn store_byte<'ctx, D>( pub fn store_byte<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
-2
View File
@@ -1,6 +1,4 @@
//!
//! The EVM instructions translation utils. //! The EVM instructions translation utils.
//!
pub mod arithmetic; pub mod arithmetic;
pub mod bitwise; pub mod bitwise;
@@ -1,6 +1,4 @@
//!
//! Translates the transaction return operations. //! Translates the transaction return operations.
//!
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::code_type::CodeType; use crate::eravm::context::code_type::CodeType;
@@ -8,11 +6,8 @@ use crate::eravm::context::pointer::Pointer;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the `return` instruction. /// Translates the `return` instruction.
///
/// Unlike in EVM, zkSync constructors return the array of contract immutables. /// Unlike in EVM, zkSync constructors return the array of contract immutables.
///
pub fn r#return<'ctx, D>( pub fn r#return<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -79,9 +74,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the `revert` instruction. /// Translates the `revert` instruction.
///
pub fn revert<'ctx, D>( pub fn revert<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -93,11 +86,8 @@ where
context.build_exit(context.integer_const(32, 1), offset, length) context.build_exit(context.integer_const(32, 1), offset, length)
} }
///
/// Translates the `stop` instruction. /// Translates the `stop` instruction.
///
/// Is the same as `return(0, 0)`. /// Is the same as `return(0, 0)`.
///
pub fn stop<D>(context: &mut Context<D>) -> anyhow::Result<()> pub fn stop<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -109,11 +99,8 @@ where
) )
} }
///
/// Translates the `invalid` instruction. /// Translates the `invalid` instruction.
///
/// Burns all gas using an out-of-bounds memory store, causing a panic. /// Burns all gas using an out-of-bounds memory store, causing a panic.
///
pub fn invalid<D>(context: &mut Context<D>) -> anyhow::Result<()> pub fn invalid<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -1,6 +1,4 @@
//!
//! Translates the return data instructions. //! Translates the return data instructions.
//!
use inkwell::types::BasicType; use inkwell::types::BasicType;
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
@@ -10,9 +8,7 @@ use crate::eravm::context::pointer::Pointer;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the return data size. /// Translates the return data size.
///
pub fn size<'ctx, D>( pub fn size<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
@@ -25,9 +21,7 @@ where
} }
} }
///
/// Translates the return data copy. /// Translates the return data copy.
///
pub fn copy<'ctx, D>( pub fn copy<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
destination_offset: inkwell::values::IntValue<'ctx>, destination_offset: inkwell::values::IntValue<'ctx>,
@@ -1,15 +1,11 @@
//!
//! Translates the storage operations. //! Translates the storage operations.
//!
use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::address_space::AddressSpace;
use crate::eravm::context::pointer::Pointer; use crate::eravm::context::pointer::Pointer;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Translates the storage load. /// Translates the storage load.
///
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
position: inkwell::values::IntValue<'ctx>, position: inkwell::values::IntValue<'ctx>,
@@ -27,9 +23,7 @@ where
context.build_load(position_pointer, "storage_load_value") context.build_load(position_pointer, "storage_load_value")
} }
///
/// Translates the storage store. /// Translates the storage store.
///
pub fn store<'ctx, D>( pub fn store<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
position: inkwell::values::IntValue<'ctx>, position: inkwell::values::IntValue<'ctx>,
@@ -49,9 +43,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the transient storage load. /// Translates the transient storage load.
///
pub fn transient_load<'ctx, D>( pub fn transient_load<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
position: inkwell::values::IntValue<'ctx>, position: inkwell::values::IntValue<'ctx>,
@@ -69,9 +61,7 @@ where
context.build_load(position_pointer, "transient_storage_load_value") context.build_load(position_pointer, "transient_storage_load_value")
} }
///
/// Translates the transient storage store. /// Translates the transient storage store.
///
pub fn transient_store<'ctx, D>( pub fn transient_store<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
position: inkwell::values::IntValue<'ctx>, position: inkwell::values::IntValue<'ctx>,
@@ -1,15 +1,11 @@
//!
//! The metadata hash mode. //! The metadata hash mode.
//!
use std::str::FromStr; use std::str::FromStr;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
///
/// The metadata hash mode. /// The metadata hash mode.
///
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MetadataHash { pub enum MetadataHash {
/// Do not include bytecode hash. /// Do not include bytecode hash.
-28
View File
@@ -1,6 +1,4 @@
//!
//! The LLVM context library. //! The LLVM context library.
//!
pub mod r#const; pub mod r#const;
pub mod context; pub mod context;
@@ -16,16 +14,12 @@ use crate::optimizer::settings::Settings as OptimizerSettings;
use self::context::build::Build; use self::context::build::Build;
use self::context::Context; use self::context::Context;
///
/// Initializes the EraVM target machine. /// Initializes the EraVM target machine.
///
pub fn initialize_target() { pub fn initialize_target() {
inkwell::targets::Target::initialize_riscv(&Default::default()); inkwell::targets::Target::initialize_riscv(&Default::default());
} }
///
/// Builds EraVM assembly text. /// Builds EraVM assembly text.
///
pub fn build_assembly_text( pub fn build_assembly_text(
contract_path: &str, contract_path: &str,
assembly_text: &str, assembly_text: &str,
@@ -90,31 +84,23 @@ pub fn build_assembly_text(
)) ))
} }
///
/// Implemented by items which are translated into LLVM IR. /// Implemented by items which are translated into LLVM IR.
///
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
pub trait WriteLLVM<D> pub trait WriteLLVM<D>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
///
/// Declares the entity in the LLVM IR. /// Declares the entity in the LLVM IR.
/// Is usually performed in order to use the item before defining it. /// Is usually performed in order to use the item before defining it.
///
fn declare(&mut self, _context: &mut Context<D>) -> anyhow::Result<()> { fn declare(&mut self, _context: &mut Context<D>) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
///
/// Translates the entity into LLVM IR. /// Translates the entity into LLVM IR.
///
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()>; fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()>;
} }
///
/// The dummy LLVM writable entity. /// The dummy LLVM writable entity.
///
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct DummyLLVMWritable {} pub struct DummyLLVMWritable {}
@@ -127,13 +113,9 @@ where
} }
} }
///
/// Implemented by items managing project dependencies. /// Implemented by items managing project dependencies.
///
pub trait Dependency { pub trait Dependency {
///
/// Compiles a project dependency. /// Compiles a project dependency.
///
fn compile( fn compile(
dependency: Self, dependency: Self,
path: &str, path: &str,
@@ -143,20 +125,14 @@ pub trait Dependency {
debug_config: Option<DebugConfig>, debug_config: Option<DebugConfig>,
) -> anyhow::Result<String>; ) -> anyhow::Result<String>;
///
/// Resolves a full contract path. /// Resolves a full contract path.
///
fn resolve_path(&self, identifier: &str) -> anyhow::Result<String>; fn resolve_path(&self, identifier: &str) -> anyhow::Result<String>;
///
/// Resolves a library address. /// Resolves a library address.
///
fn resolve_library(&self, path: &str) -> anyhow::Result<String>; fn resolve_library(&self, path: &str) -> anyhow::Result<String>;
} }
///
/// The dummy dependency entity. /// The dummy dependency entity.
///
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct DummyDependency {} pub struct DummyDependency {}
@@ -172,16 +148,12 @@ impl Dependency for DummyDependency {
Ok(String::new()) Ok(String::new())
} }
///
/// Resolves a full contract path. /// Resolves a full contract path.
///
fn resolve_path(&self, _identifier: &str) -> anyhow::Result<String> { fn resolve_path(&self, _identifier: &str) -> anyhow::Result<String> {
Ok(String::new()) Ok(String::new())
} }
///
/// Resolves a library address. /// Resolves a library address.
///
fn resolve_library(&self, _path: &str) -> anyhow::Result<String> { fn resolve_library(&self, _path: &str) -> anyhow::Result<String> {
Ok(String::new()) Ok(String::new())
} }
-16
View File
@@ -1,6 +1,4 @@
//!
//! Some LLVM IR generator utilies. //! Some LLVM IR generator utilies.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
@@ -9,9 +7,7 @@ use crate::eravm::context::function::llvm_runtime::LLVMRuntime;
use crate::eravm::context::Context; use crate::eravm::context::Context;
use crate::eravm::Dependency; use crate::eravm::Dependency;
///
/// Clamps `value` to `max_value`, if `value` is bigger than `max_value`. /// Clamps `value` to `max_value`, if `value` is bigger than `max_value`.
///
pub fn clamp<'ctx, D>( pub fn clamp<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
value: inkwell::values::IntValue<'ctx>, value: inkwell::values::IntValue<'ctx>,
@@ -44,9 +40,7 @@ where
Ok(result.into_int_value()) Ok(result.into_int_value())
} }
///
/// Generates an exception. /// Generates an exception.
///
pub fn throw<D>(context: &Context<D>) pub fn throw<D>(context: &Context<D>)
where where
D: Dependency + Clone, D: Dependency + Clone,
@@ -63,11 +57,8 @@ where
context.build_unreachable(); context.build_unreachable();
} }
///
/// Returns the full list of arguments for an external call. /// Returns the full list of arguments for an external call.
///
/// Performs the extra ABI data padding and adds the mimic call extra argument. /// Performs the extra ABI data padding and adds the mimic call extra argument.
///
pub fn external_call_arguments<'ctx, D>( pub fn external_call_arguments<'ctx, D>(
_context: &Context<'ctx, D>, _context: &Context<'ctx, D>,
abi_data: inkwell::values::BasicValueEnum<'ctx>, abi_data: inkwell::values::BasicValueEnum<'ctx>,
@@ -96,11 +87,8 @@ where
result result
} }
///
/// Generates an ABI data for an external call. /// Generates an ABI data for an external call.
///
/// If `gas` is `None`, it is fetched from the contract context. /// If `gas` is `None`, it is fetched from the contract context.
///
pub fn abi_data<'ctx, D>( pub fn abi_data<'ctx, D>(
context: &mut Context<'ctx, D>, context: &mut Context<'ctx, D>,
input_offset: inkwell::values::IntValue<'ctx>, input_offset: inkwell::values::IntValue<'ctx>,
@@ -190,9 +178,7 @@ where
Ok(abi_data.as_basic_value_enum()) Ok(abi_data.as_basic_value_enum())
} }
///
/// Pads the extra ABI data with `i256::undef`, so it always consists of 10 values. /// Pads the extra ABI data with `i256::undef`, so it always consists of 10 values.
///
pub fn pad_extra_abi_data<'ctx, D>( pub fn pad_extra_abi_data<'ctx, D>(
context: &Context<'ctx, D>, context: &Context<'ctx, D>,
initial_data: Vec<inkwell::values::IntValue<'ctx>>, initial_data: Vec<inkwell::values::IntValue<'ctx>>,
@@ -208,9 +194,7 @@ where
padded_data.try_into().expect("Always valid") padded_data.try_into().expect("Always valid")
} }
///
/// Computes the `keccak256` hash for `preimage`. /// Computes the `keccak256` hash for `preimage`.
///
pub fn keccak256(preimage: &[u8]) -> String { pub fn keccak256(preimage: &[u8]) -> String {
use sha3::Digest; use sha3::Digest;
-4
View File
@@ -1,6 +1,4 @@
//!
//! The LLVM context library. //! The LLVM context library.
//!
pub(crate) mod debug_config; pub(crate) mod debug_config;
pub(crate) mod eravm; pub(crate) mod eravm;
@@ -68,9 +66,7 @@ pub use self::optimizer::Optimizer;
pub use self::target_machine::target::Target; pub use self::target_machine::target::Target;
pub use self::target_machine::TargetMachine; pub use self::target_machine::TargetMachine;
///
/// Initializes the target machine. /// Initializes the target machine.
///
pub fn initialize_target(target: Target) { pub fn initialize_target(target: Target) {
match target { match target {
Target::PVM => self::eravm::initialize_target(), Target::PVM => self::eravm::initialize_target(),
-10
View File
@@ -1,6 +1,4 @@
//!
//! The LLVM optimizing tools. //! The LLVM optimizing tools.
//!
pub mod settings; pub mod settings;
@@ -11,9 +9,7 @@ use crate::target_machine::TargetMachine;
use self::settings::Settings; use self::settings::Settings;
///
/// The LLVM optimizing tools. /// The LLVM optimizing tools.
///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Optimizer { pub struct Optimizer {
/// The optimizer settings. /// The optimizer settings.
@@ -21,16 +17,12 @@ pub struct Optimizer {
} }
impl Optimizer { impl Optimizer {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(settings: Settings) -> Self { pub fn new(settings: Settings) -> Self {
Self { settings } Self { settings }
} }
///
/// Runs the new pass manager. /// Runs the new pass manager.
///
pub fn run( pub fn run(
&self, &self,
target_machine: &TargetMachine, target_machine: &TargetMachine,
@@ -42,9 +34,7 @@ impl Optimizer {
) )
} }
///
/// Returns the optimizer settings reference. /// Returns the optimizer settings reference.
///
pub fn settings(&self) -> &Settings { pub fn settings(&self) -> &Settings {
&self.settings &self.settings
} }
@@ -1,6 +1,4 @@
//!
//! The LLVM optimizer settings. //! The LLVM optimizer settings.
//!
pub mod size_level; pub mod size_level;
@@ -11,9 +9,7 @@ use itertools::Itertools;
use self::size_level::SizeLevel; use self::size_level::SizeLevel;
///
/// The LLVM optimizer settings. /// The LLVM optimizer settings.
///
#[derive(Debug, Serialize, Deserialize, Clone, Eq)] #[derive(Debug, Serialize, Deserialize, Clone, Eq)]
pub struct Settings { pub struct Settings {
/// The middle-end optimization level. /// The middle-end optimization level.
@@ -35,9 +31,7 @@ pub struct Settings {
} }
impl Settings { impl Settings {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
level_middle_end: inkwell::OptimizationLevel, level_middle_end: inkwell::OptimizationLevel,
level_middle_end_size: SizeLevel, level_middle_end_size: SizeLevel,
@@ -56,9 +50,7 @@ impl Settings {
} }
} }
///
/// A shortcut constructor with debugging tools. /// A shortcut constructor with debugging tools.
///
pub fn new_debug( pub fn new_debug(
level_middle_end: inkwell::OptimizationLevel, level_middle_end: inkwell::OptimizationLevel,
level_middle_end_size: SizeLevel, level_middle_end_size: SizeLevel,
@@ -80,9 +72,7 @@ impl Settings {
} }
} }
///
/// Creates settings from a CLI optimization parameter. /// Creates settings from a CLI optimization parameter.
///
pub fn try_from_cli(value: char) -> anyhow::Result<Self> { pub fn try_from_cli(value: char) -> anyhow::Result<Self> {
Ok(match value { Ok(match value {
'0' => Self::new( '0' => Self::new(
@@ -126,9 +116,7 @@ impl Settings {
}) })
} }
///
/// Returns the settings without optimizations. /// Returns the settings without optimizations.
///
pub fn none() -> Self { pub fn none() -> Self {
Self::new( Self::new(
inkwell::OptimizationLevel::None, inkwell::OptimizationLevel::None,
@@ -137,9 +125,7 @@ impl Settings {
) )
} }
///
/// Returns the settings for the optimal number of VM execution cycles. /// Returns the settings for the optimal number of VM execution cycles.
///
pub fn cycles() -> Self { pub fn cycles() -> Self {
Self::new( Self::new(
inkwell::OptimizationLevel::Aggressive, inkwell::OptimizationLevel::Aggressive,
@@ -148,9 +134,7 @@ impl Settings {
) )
} }
///
/// Returns the settings for the optimal size. /// Returns the settings for the optimal size.
///
pub fn size() -> Self { pub fn size() -> Self {
Self::new( Self::new(
inkwell::OptimizationLevel::Default, inkwell::OptimizationLevel::Default,
@@ -159,9 +143,7 @@ impl Settings {
) )
} }
///
/// Returns the middle-end optimization parameter as string. /// Returns the middle-end optimization parameter as string.
///
pub fn middle_end_as_string(&self) -> String { pub fn middle_end_as_string(&self) -> String {
match self.level_middle_end_size { match self.level_middle_end_size {
SizeLevel::Zero => (self.level_middle_end as u8).to_string(), SizeLevel::Zero => (self.level_middle_end as u8).to_string(),
@@ -169,19 +151,14 @@ impl Settings {
} }
} }
///
/// Checks whether there are middle-end optimizations enabled. /// Checks whether there are middle-end optimizations enabled.
///
pub fn is_middle_end_enabled(&self) -> bool { pub fn is_middle_end_enabled(&self) -> bool {
self.level_middle_end != inkwell::OptimizationLevel::None self.level_middle_end != inkwell::OptimizationLevel::None
|| self.level_middle_end_size != SizeLevel::Zero || self.level_middle_end_size != SizeLevel::Zero
} }
///
/// Returns all possible combinations of the optimizer settings. /// Returns all possible combinations of the optimizer settings.
///
/// Used only for testing purposes. /// Used only for testing purposes.
///
pub fn combinations() -> Vec<Self> { pub fn combinations() -> Vec<Self> {
let performance_combinations: Vec<Self> = vec![ let performance_combinations: Vec<Self> = vec![
inkwell::OptimizationLevel::None, inkwell::OptimizationLevel::None,
@@ -224,30 +201,22 @@ impl Settings {
combinations combinations
} }
///
/// Sets the fallback to optimizing for size if the bytecode is too large. /// Sets the fallback to optimizing for size if the bytecode is too large.
///
pub fn enable_fallback_to_size(&mut self) { pub fn enable_fallback_to_size(&mut self) {
self.is_fallback_to_size_enabled = true; self.is_fallback_to_size_enabled = true;
} }
///
/// Disables the system request memoization. /// Disables the system request memoization.
///
pub fn disable_system_request_memoization(&mut self) { pub fn disable_system_request_memoization(&mut self) {
self.is_system_request_memoization_disabled = true; self.is_system_request_memoization_disabled = true;
} }
///
/// Whether the fallback to optimizing for size is enabled. /// Whether the fallback to optimizing for size is enabled.
///
pub fn is_fallback_to_size_enabled(&self) -> bool { pub fn is_fallback_to_size_enabled(&self) -> bool {
self.is_fallback_to_size_enabled self.is_fallback_to_size_enabled
} }
///
/// Whether the system request memoization is disabled. /// Whether the system request memoization is disabled.
///
pub fn is_system_request_memoization_disabled(&self) -> bool { pub fn is_system_request_memoization_disabled(&self) -> bool {
self.is_system_request_memoization_disabled self.is_system_request_memoization_disabled
} }
@@ -1,13 +1,9 @@
//!
//! The LLVM optimizer settings size level. //! The LLVM optimizer settings size level.
//!
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
///
/// The LLVM optimizer settings size level. /// The LLVM optimizer settings size level.
///
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum SizeLevel { pub enum SizeLevel {
/// No size optimizations. /// No size optimizations.
@@ -1,6 +1,4 @@
//!
//! The LLVM target machine. //! The LLVM target machine.
//!
pub mod target; pub mod target;
@@ -9,9 +7,7 @@ use crate::optimizer::settings::Settings as OptimizerSettings;
use self::target::Target; use self::target::Target;
///
/// The LLVM target machine. /// The LLVM target machine.
///
#[derive(Debug)] #[derive(Debug)]
pub struct TargetMachine { pub struct TargetMachine {
/// The LLVM target. /// The LLVM target.
@@ -35,11 +31,8 @@ impl TargetMachine {
#[cfg(not(feature = "riscv-zbb"))] #[cfg(not(feature = "riscv-zbb"))]
pub const VM_FEATURES: &'static str = "+e,+m"; pub const VM_FEATURES: &'static str = "+e,+m";
///
/// A shortcut constructor. /// A shortcut constructor.
///
/// A separate instance for every optimization level is created. /// A separate instance for every optimization level is created.
///
pub fn new(target: Target, optimizer_settings: &OptimizerSettings) -> anyhow::Result<Self> { pub fn new(target: Target, optimizer_settings: &OptimizerSettings) -> anyhow::Result<Self> {
let target_machine = inkwell::targets::Target::from_name(target.name()) let target_machine = inkwell::targets::Target::from_name(target.name())
.ok_or_else(|| anyhow::anyhow!("LLVM target machine `{}` not found", target.name()))? .ok_or_else(|| anyhow::anyhow!("LLVM target machine `{}` not found", target.name()))?
@@ -65,17 +58,13 @@ impl TargetMachine {
}) })
} }
///
/// Sets the target-specific data in the module. /// Sets the target-specific data in the module.
///
pub fn set_target_data(&self, module: &inkwell::module::Module) { pub fn set_target_data(&self, module: &inkwell::module::Module) {
module.set_triple(&self.target_machine.get_triple()); module.set_triple(&self.target_machine.get_triple());
module.set_data_layout(&self.target_machine.get_target_data().get_data_layout()); module.set_data_layout(&self.target_machine.get_target_data().get_data_layout());
} }
///
/// Writes the LLVM module to a memory buffer. /// Writes the LLVM module to a memory buffer.
///
pub fn write_to_memory_buffer( pub fn write_to_memory_buffer(
&self, &self,
module: &inkwell::module::Module, module: &inkwell::module::Module,
@@ -87,9 +76,7 @@ impl TargetMachine {
} }
} }
///
/// Runs the optimization passes on `module`. /// Runs the optimization passes on `module`.
///
pub fn run_optimization_passes( pub fn run_optimization_passes(
&self, &self,
module: &inkwell::module::Module, module: &inkwell::module::Module,
@@ -107,16 +94,12 @@ impl TargetMachine {
module.run_passes(passes, &self.target_machine, pass_builder_options) module.run_passes(passes, &self.target_machine, pass_builder_options)
} }
///
/// Returns the target triple. /// Returns the target triple.
///
pub fn get_triple(&self) -> inkwell::targets::TargetTriple { pub fn get_triple(&self) -> inkwell::targets::TargetTriple {
self.target_machine.get_triple() self.target_machine.get_triple()
} }
///
/// Returns the target data. /// Returns the target data.
///
pub fn get_target_data(&self) -> inkwell::targets::TargetData { pub fn get_target_data(&self) -> inkwell::targets::TargetData {
self.target_machine.get_target_data() self.target_machine.get_target_data()
} }
@@ -1,12 +1,8 @@
//!
//! The LLVM target. //! The LLVM target.
//!
use std::str::FromStr; use std::str::FromStr;
///
/// The LLVM target. /// The LLVM target.
///
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Target { pub enum Target {
/// The EraVM target. /// The EraVM target.
@@ -14,27 +10,21 @@ pub enum Target {
} }
impl Target { impl Target {
///
/// Returns the target name. /// Returns the target name.
///
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match self {
Self::PVM => "riscv32", Self::PVM => "riscv32",
} }
} }
///
/// Returns the target triple. /// Returns the target triple.
///
pub fn triple(&self) -> &str { pub fn triple(&self) -> &str {
match self { match self {
Self::PVM => "riscv32-unknown-unknown-elf", Self::PVM => "riscv32-unknown-unknown-elf",
} }
} }
///
/// Returns the target production name. /// Returns the target production name.
///
pub fn production_name(&self) -> &str { pub fn production_name(&self) -> &str {
match self { match self {
Self::PVM => "PVM", Self::PVM => "PVM",
@@ -1,24 +1,19 @@
//! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting //! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting
//! with the `pallet-contracts` runtime API. //! with the `pallet-contracts` runtime API.
//!
//! At present, the contracts pallet requires blobs to export `call` and `deploy`, //! At present, the contracts pallet requires blobs to export `call` and `deploy`,
//! and offers a bunch of [runtime API methods][1]. The provided [module] implements //! and offers a bunch of [runtime API methods][1]. The provided [module] implements
//! those exports and imports. //! those exports and imports.
//!
//! [0]: [https://crates.io/crates/polkavm] //! [0]: [https://crates.io/crates/polkavm]
//! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html] //! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html]
//!
use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString}; use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString};
include!(concat!(env!("OUT_DIR"), "/polkavm_guest.rs")); include!(concat!(env!("OUT_DIR"), "/polkavm_guest.rs"));
/// Creates a LLVM module from the [BITCODE]. /// Creates a LLVM module from the [BITCODE].
///
/// The module does: /// The module does:
/// - Export the `call` and `deploy` functions (which are named thereafter). /// - Export the `call` and `deploy` functions (which are named thereafter).
/// - Import (most) `pallet-contracts` runtime API functions. /// - Import (most) `pallet-contracts` runtime API functions.
///
/// Returns `Error` if the bitcode fails to parse, which should never happen. /// Returns `Error` if the bitcode fails to parse, which should never happen.
pub fn module<'context>( pub fn module<'context>(
context: &'context Context, context: &'context Context,
-14
View File
@@ -1,6 +1,4 @@
//!
//! The Solidity contract build. //! The Solidity contract build.
//!
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::File; use std::fs::File;
@@ -13,9 +11,7 @@ use serde::Serialize;
use crate::solc::combined_json::contract::Contract as CombinedJsonContract; use crate::solc::combined_json::contract::Contract as CombinedJsonContract;
use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract; use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract;
///
/// The Solidity contract build. /// The Solidity contract build.
///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Contract { pub struct Contract {
/// The contract path. /// The contract path.
@@ -31,9 +27,7 @@ pub struct Contract {
} }
impl Contract { impl Contract {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
path: String, path: String,
identifier: String, identifier: String,
@@ -50,9 +44,7 @@ impl Contract {
} }
} }
///
/// Writes the contract text assembly and bytecode to files. /// Writes the contract text assembly and bytecode to files.
///
pub fn write_to_directory( pub fn write_to_directory(
self, self,
path: &Path, path: &Path,
@@ -107,9 +99,7 @@ impl Contract {
Ok(()) Ok(())
} }
///
/// Writes the contract text assembly and bytecode to the combined JSON. /// Writes the contract text assembly and bytecode to the combined JSON.
///
pub fn write_to_combined_json( pub fn write_to_combined_json(
self, self,
combined_json_contract: &mut CombinedJsonContract, combined_json_contract: &mut CombinedJsonContract,
@@ -130,9 +120,7 @@ impl Contract {
Ok(()) Ok(())
} }
///
/// Writes the contract text assembly and bytecode to the standard JSON. /// Writes the contract text assembly and bytecode to the standard JSON.
///
pub fn write_to_standard_json( pub fn write_to_standard_json(
self, self,
standard_json_contract: &mut StandardJsonOutputContract, standard_json_contract: &mut StandardJsonOutputContract,
@@ -151,9 +139,7 @@ impl Contract {
Ok(()) Ok(())
} }
///
/// Converts the full path to a short one. /// Converts the full path to a short one.
///
pub fn short_path(path: &str) -> &str { pub fn short_path(path: &str) -> &str {
path.rfind('/') path.rfind('/')
.map(|last_slash| &path[last_slash + 1..]) .map(|last_slash| &path[last_slash + 1..])
-10
View File
@@ -1,6 +1,4 @@
//!
//! The Solidity project build. //! The Solidity project build.
//!
pub mod contract; pub mod contract;
@@ -13,9 +11,7 @@ use crate::solc::version::Version as SolcVersion;
use self::contract::Contract; use self::contract::Contract;
///
/// The Solidity project build. /// The Solidity project build.
///
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Build { pub struct Build {
/// The contract data, /// The contract data,
@@ -23,9 +19,7 @@ pub struct Build {
} }
impl Build { impl Build {
///
/// Writes all contracts to the specified directory. /// Writes all contracts to the specified directory.
///
pub fn write_to_directory( pub fn write_to_directory(
self, self,
output_directory: &Path, output_directory: &Path,
@@ -45,9 +39,7 @@ impl Build {
Ok(()) Ok(())
} }
///
/// Writes all contracts assembly and bytecode to the combined JSON. /// Writes all contracts assembly and bytecode to the combined JSON.
///
pub fn write_to_combined_json( pub fn write_to_combined_json(
self, self,
combined_json: &mut CombinedJson, combined_json: &mut CombinedJson,
@@ -74,9 +66,7 @@ impl Build {
Ok(()) Ok(())
} }
///
/// Writes all contracts assembly and bytecode to the standard JSON. /// Writes all contracts assembly and bytecode to the standard JSON.
///
pub fn write_to_standard_json( pub fn write_to_standard_json(
mut self, mut self,
standard_json: &mut StandardJsonOutput, standard_json: &mut StandardJsonOutput,
-2
View File
@@ -1,6 +1,4 @@
//!
//! Solidity to EraVM compiler constants. //! Solidity to EraVM compiler constants.
//!
#![allow(dead_code)] #![allow(dead_code)]
@@ -1,6 +1,4 @@
//!
//! The inner JSON legacy assembly code element. //! The inner JSON legacy assembly code element.
//!
use std::collections::HashSet; use std::collections::HashSet;
@@ -9,9 +7,7 @@ use serde::Serialize;
use crate::evmla::assembly::Assembly; use crate::evmla::assembly::Assembly;
///
/// The inner JSON legacy assembly code element. /// The inner JSON legacy assembly code element.
///
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
pub enum Data { pub enum Data {
@@ -24,9 +20,7 @@ pub enum Data {
} }
impl Data { impl Data {
///
/// Returns the inner assembly reference if it is present. /// Returns the inner assembly reference if it is present.
///
pub fn get_assembly(&self) -> Option<&Assembly> { pub fn get_assembly(&self) -> Option<&Assembly> {
match self { match self {
Self::Assembly(ref assembly) => Some(assembly), Self::Assembly(ref assembly) => Some(assembly),
@@ -34,9 +28,7 @@ impl Data {
Self::Path(_) => None, Self::Path(_) => None,
} }
} }
///
/// Returns the inner assembly mutable reference if it is present. /// Returns the inner assembly mutable reference if it is present.
///
pub fn get_assembly_mut(&mut self) -> Option<&mut Assembly> { pub fn get_assembly_mut(&mut self) -> Option<&mut Assembly> {
match self { match self {
Self::Assembly(ref mut assembly) => Some(assembly), Self::Assembly(ref mut assembly) => Some(assembly),
@@ -45,9 +37,7 @@ impl Data {
} }
} }
///
/// Get the list of missing deployable libraries. /// Get the list of missing deployable libraries.
///
pub fn get_missing_libraries(&self) -> HashSet<String> { pub fn get_missing_libraries(&self) -> HashSet<String> {
match self { match self {
Self::Assembly(assembly) => assembly.get_missing_libraries(), Self::Assembly(assembly) => assembly.get_missing_libraries(),
@@ -56,9 +46,7 @@ impl Data {
} }
} }
///
/// Gets the contract `keccak256` hash. /// Gets the contract `keccak256` hash.
///
pub fn keccak256(&self) -> String { pub fn keccak256(&self) -> String {
match self { match self {
Self::Assembly(assembly) => assembly.keccak256(), Self::Assembly(assembly) => assembly.keccak256(),
@@ -1,10 +1,6 @@
//!
//! Translates the CODECOPY use cases. //! Translates the CODECOPY use cases.
//!
///
/// Translates the contract hash copying. /// Translates the contract hash copying.
///
pub fn contract_hash<'ctx, D>( pub fn contract_hash<'ctx, D>(
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
offset: inkwell::values::IntValue<'ctx>, offset: inkwell::values::IntValue<'ctx>,
@@ -26,9 +22,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the library marker copying. /// Translates the library marker copying.
///
pub fn library_marker<D>( pub fn library_marker<D>(
context: &mut revive_llvm_context::EraVMContext<D>, context: &mut revive_llvm_context::EraVMContext<D>,
offset: u64, offset: u64,
@@ -46,9 +40,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the static data copying. /// Translates the static data copying.
///
pub fn static_data<'ctx, D>( pub fn static_data<'ctx, D>(
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
destination: inkwell::values::IntValue<'ctx>, destination: inkwell::values::IntValue<'ctx>,
@@ -1,10 +1,6 @@
//!
//! Translates the jump operations. //! Translates the jump operations.
//!
///
/// Translates the unconditional jump. /// Translates the unconditional jump.
///
pub fn unconditional<D>( pub fn unconditional<D>(
context: &mut revive_llvm_context::EraVMContext<D>, context: &mut revive_llvm_context::EraVMContext<D>,
destination: num::BigUint, destination: num::BigUint,
@@ -28,9 +24,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the conditional jump. /// Translates the conditional jump.
///
pub fn conditional<D>( pub fn conditional<D>(
context: &mut revive_llvm_context::EraVMContext<D>, context: &mut revive_llvm_context::EraVMContext<D>,
destination: num::BigUint, destination: num::BigUint,
@@ -1,6 +1,4 @@
//!
//! The EVM instruction. //! The EVM instruction.
//!
pub mod codecopy; pub mod codecopy;
pub mod jump; pub mod jump;
@@ -14,9 +12,7 @@ use serde::Serialize;
use self::name::Name; use self::name::Name;
///
/// The EVM instruction. /// The EVM instruction.
///
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Instruction { pub struct Instruction {
/// The opcode or tag identifier. /// The opcode or tag identifier.
@@ -34,9 +30,7 @@ pub struct Instruction {
} }
impl Instruction { impl Instruction {
///
/// Returns the number of input stack arguments. /// Returns the number of input stack arguments.
///
pub const fn input_size(&self, version: &semver::Version) -> usize { pub const fn input_size(&self, version: &semver::Version) -> usize {
match self.name { match self.name {
Name::POP => 1, Name::POP => 1,
@@ -135,9 +129,7 @@ impl Instruction {
} }
} }
///
/// Returns the number of output stack arguments. /// Returns the number of output stack arguments.
///
pub const fn output_size(&self) -> usize { pub const fn output_size(&self) -> usize {
match self.name { match self.name {
Name::PUSH => 1, Name::PUSH => 1,
@@ -285,9 +277,7 @@ impl Instruction {
} }
} }
///
/// Replaces the instruction data aliases with the actual data. /// Replaces the instruction data aliases with the actual data.
///
pub fn replace_data_aliases( pub fn replace_data_aliases(
instructions: &mut [Self], instructions: &mut [Self],
mapping: &BTreeMap<String, String>, mapping: &BTreeMap<String, String>,
@@ -323,9 +313,7 @@ impl Instruction {
Ok(()) Ok(())
} }
///
/// Initializes an `INVALID` instruction to terminate an invalid unreachable block part. /// Initializes an `INVALID` instruction to terminate an invalid unreachable block part.
///
pub fn invalid(previous: &Self) -> Self { pub fn invalid(previous: &Self) -> Self {
Self { Self {
name: Name::INVALID, name: Name::INVALID,
@@ -337,9 +325,7 @@ impl Instruction {
} }
} }
///
/// Initializes a recursive function `Call` instruction. /// Initializes a recursive function `Call` instruction.
///
pub fn recursive_call( pub fn recursive_call(
name: String, name: String,
entry_key: revive_llvm_context::EraVMFunctionBlockKey, entry_key: revive_llvm_context::EraVMFunctionBlockKey,
@@ -366,9 +352,7 @@ impl Instruction {
} }
} }
///
/// Initializes a recursive function `Return` instruction. /// Initializes a recursive function `Return` instruction.
///
pub fn recursive_return(input_size: usize, previous: &Self) -> Self { pub fn recursive_return(input_size: usize, previous: &Self) -> Self {
Self { Self {
name: Name::RecursiveReturn { input_size }, name: Name::RecursiveReturn { input_size },
@@ -1,13 +1,9 @@
//!
//! The EVM instruction name. //! The EVM instruction name.
//!
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
///
/// The EVM instruction name. /// The EVM instruction name.
///
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
@@ -1,12 +1,8 @@
//!
//! Translates the stack memory operations. //! Translates the stack memory operations.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
///
/// Translates the ordinar value push. /// Translates the ordinar value push.
///
pub fn push<'ctx, D>( pub fn push<'ctx, D>(
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
value: String, value: String,
@@ -25,9 +21,7 @@ where
Ok(result) Ok(result)
} }
///
/// Translates the block tag label push. /// Translates the block tag label push.
///
pub fn push_tag<'ctx, D>( pub fn push_tag<'ctx, D>(
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
value: String, value: String,
@@ -42,9 +36,7 @@ where
Ok(result.as_basic_value_enum()) Ok(result.as_basic_value_enum())
} }
///
/// Translates the stack memory duplicate. /// Translates the stack memory duplicate.
///
pub fn dup<'ctx, D>( pub fn dup<'ctx, D>(
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
offset: usize, offset: usize,
@@ -68,9 +60,7 @@ where
Ok(value) Ok(value)
} }
///
/// Translates the stack memory swap. /// Translates the stack memory swap.
///
pub fn swap<D>( pub fn swap<D>(
context: &mut revive_llvm_context::EraVMContext<D>, context: &mut revive_llvm_context::EraVMContext<D>,
offset: usize, offset: usize,
@@ -103,9 +93,7 @@ where
Ok(()) Ok(())
} }
///
/// Translates the stack memory pop. /// Translates the stack memory pop.
///
pub fn pop<D>(_context: &mut revive_llvm_context::EraVMContext<D>) -> anyhow::Result<()> pub fn pop<D>(_context: &mut revive_llvm_context::EraVMContext<D>) -> anyhow::Result<()>
where where
D: revive_llvm_context::EraVMDependency + Clone, D: revive_llvm_context::EraVMDependency + Clone,
-17
View File
@@ -1,6 +1,4 @@
//!
//! The `solc --asm-json` output. //! The `solc --asm-json` output.
//!
pub mod data; pub mod data;
pub mod instruction; pub mod instruction;
@@ -19,9 +17,7 @@ use self::data::Data;
use self::instruction::name::Name as InstructionName; use self::instruction::name::Name as InstructionName;
use self::instruction::Instruction; use self::instruction::Instruction;
///
/// The JSON assembly. /// The JSON assembly.
///
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Assembly { pub struct Assembly {
/// The metadata string. /// The metadata string.
@@ -46,36 +42,27 @@ pub struct Assembly {
} }
impl Assembly { impl Assembly {
///
/// Gets the contract `keccak256` hash. /// Gets the contract `keccak256` hash.
///
pub fn keccak256(&self) -> String { pub fn keccak256(&self) -> String {
let json = serde_json::to_vec(self).expect("Always valid"); let json = serde_json::to_vec(self).expect("Always valid");
revive_llvm_context::eravm_utils::keccak256(json.as_slice()) revive_llvm_context::eravm_utils::keccak256(json.as_slice())
} }
///
/// Sets the full contract path. /// Sets the full contract path.
///
pub fn set_full_path(&mut self, full_path: String) { pub fn set_full_path(&mut self, full_path: String) {
self.full_path = Some(full_path); self.full_path = Some(full_path);
} }
///
/// Returns the full contract path if it is set, or `<undefined>` otherwise. /// Returns the full contract path if it is set, or `<undefined>` otherwise.
///
/// # Panics /// # Panics
/// If the `full_path` has not been set. /// If the `full_path` has not been set.
///
pub fn full_path(&self) -> &str { pub fn full_path(&self) -> &str {
self.full_path self.full_path
.as_deref() .as_deref()
.unwrap_or_else(|| panic!("The full path of some contracts is unset")) .unwrap_or_else(|| panic!("The full path of some contracts is unset"))
} }
///
/// Get the list of missing deployable libraries. /// Get the list of missing deployable libraries.
///
pub fn get_missing_libraries(&self) -> HashSet<String> { pub fn get_missing_libraries(&self) -> HashSet<String> {
let mut missing_libraries = HashSet::new(); let mut missing_libraries = HashSet::new();
if let Some(code) = self.code.as_ref() { if let Some(code) = self.code.as_ref() {
@@ -94,9 +81,7 @@ impl Assembly {
missing_libraries missing_libraries
} }
///
/// Replaces the deploy code dependencies with full contract path and returns the list. /// Replaces the deploy code dependencies with full contract path and returns the list.
///
pub fn deploy_dependencies_pass( pub fn deploy_dependencies_pass(
&mut self, &mut self,
full_path: &str, full_path: &str,
@@ -144,9 +129,7 @@ impl Assembly {
Ok(index_path_mapping) Ok(index_path_mapping)
} }
///
/// Replaces the runtime code dependencies with full contract path and returns the list. /// Replaces the runtime code dependencies with full contract path and returns the list.
///
pub fn runtime_dependencies_pass( pub fn runtime_dependencies_pass(
&mut self, &mut self,
full_path: &str, full_path: &str,
@@ -1,16 +1,11 @@
//!
//! The Ethereal IR entry function link. //! The Ethereal IR entry function link.
//!
use inkwell::values::BasicValue; use inkwell::values::BasicValue;
use crate::evmla::ethereal_ir::EtherealIR; use crate::evmla::ethereal_ir::EtherealIR;
///
/// The Ethereal IR entry function link. /// The Ethereal IR entry function link.
///
/// The link represents branching between the deploy and runtime code. /// The link represents branching between the deploy and runtime code.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EntryLink { pub struct EntryLink {
/// The code part type. /// The code part type.
@@ -18,9 +13,7 @@ pub struct EntryLink {
} }
impl EntryLink { impl EntryLink {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(code_type: revive_llvm_context::EraVMCodeType) -> Self { pub fn new(code_type: revive_llvm_context::EraVMCodeType) -> Self {
Self { code_type } Self { code_type }
} }
@@ -1,6 +1,4 @@
//!
//! The Ethereal IR block element. //! The Ethereal IR block element.
//!
pub mod stack; pub mod stack;
@@ -13,9 +11,7 @@ use crate::evmla::assembly::instruction::Instruction;
use self::stack::element::Element as StackElement; use self::stack::element::Element as StackElement;
use self::stack::Stack; use self::stack::Stack;
///
/// The Ethereal IR block element. /// The Ethereal IR block element.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Element { pub struct Element {
/// The Solidity compiler version. /// The Solidity compiler version.
@@ -31,9 +27,7 @@ pub struct Element {
} }
impl Element { impl Element {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(solc_version: semver::Version, instruction: Instruction) -> Self { pub fn new(solc_version: semver::Version, instruction: Instruction) -> Self {
let input_size = instruction.input_size(&solc_version); let input_size = instruction.input_size(&solc_version);
let output_size = instruction.output_size(); let output_size = instruction.output_size();
@@ -47,9 +41,7 @@ impl Element {
} }
} }
///
/// Pops the specified number of arguments, converted into their LLVM values. /// Pops the specified number of arguments, converted into their LLVM values.
///
fn pop_arguments_llvm<'ctx, D>( fn pop_arguments_llvm<'ctx, D>(
&mut self, &mut self,
context: &mut revive_llvm_context::EraVMContext<'ctx, D>, context: &mut revive_llvm_context::EraVMContext<'ctx, D>,
@@ -1,10 +1,6 @@
//!
//! The Ethereal IR block element stack element. //! The Ethereal IR block element stack element.
//!
///
/// The Ethereal IR block element stack element. /// The Ethereal IR block element stack element.
///
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Element { pub enum Element {
/// The runtime value. /// The runtime value.
@@ -1,14 +1,10 @@
//!
//! The Ethereal IR block element stack. //! The Ethereal IR block element stack.
//!
pub mod element; pub mod element;
use self::element::Element; use self::element::Element;
///
/// The Ethereal IR block element stack. /// The Ethereal IR block element stack.
///
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct Stack { pub struct Stack {
/// The stack elements. /// The stack elements.
@@ -19,36 +15,27 @@ impl Stack {
/// The default stack size. /// The default stack size.
pub const DEFAULT_STACK_SIZE: usize = 16; pub const DEFAULT_STACK_SIZE: usize = 16;
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
elements: Vec::with_capacity(Self::DEFAULT_STACK_SIZE), elements: Vec::with_capacity(Self::DEFAULT_STACK_SIZE),
} }
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
Self { Self {
elements: Vec::with_capacity(capacity), elements: Vec::with_capacity(capacity),
} }
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new_with_elements(elements: Vec<Element>) -> Self { pub fn new_with_elements(elements: Vec<Element>) -> Self {
Self { elements } Self { elements }
} }
///
/// The stack state hash, which acts as a block identifier. /// The stack state hash, which acts as a block identifier.
///
/// Each block clone has its own initial stack state, which uniquely identifies the block. /// Each block clone has its own initial stack state, which uniquely identifies the block.
///
pub fn hash(&self) -> md5::Digest { pub fn hash(&self) -> md5::Digest {
let mut hash_context = md5::Context::new(); let mut hash_context = md5::Context::new();
for element in self.elements.iter() { for element in self.elements.iter() {
@@ -60,32 +47,24 @@ impl Stack {
hash_context.compute() hash_context.compute()
} }
///
/// Pushes an element onto the stack. /// Pushes an element onto the stack.
///
pub fn push(&mut self, element: Element) { pub fn push(&mut self, element: Element) {
self.elements.push(element); self.elements.push(element);
} }
///
/// Appends another stack on top of this one. /// Appends another stack on top of this one.
///
pub fn append(&mut self, other: &mut Self) { pub fn append(&mut self, other: &mut Self) {
self.elements.append(&mut other.elements); self.elements.append(&mut other.elements);
} }
///
/// Pops a stack element. /// Pops a stack element.
///
pub fn pop(&mut self) -> anyhow::Result<Element> { pub fn pop(&mut self) -> anyhow::Result<Element> {
self.elements self.elements
.pop() .pop()
.ok_or_else(|| anyhow::anyhow!("Stack underflow")) .ok_or_else(|| anyhow::anyhow!("Stack underflow"))
} }
///
/// Pops the tag from the top. /// Pops the tag from the top.
///
pub fn pop_tag(&mut self) -> anyhow::Result<num::BigUint> { pub fn pop_tag(&mut self) -> anyhow::Result<num::BigUint> {
match self.elements.pop() { match self.elements.pop() {
Some(Element::Tag(tag)) => Ok(tag), Some(Element::Tag(tag)) => Ok(tag),
@@ -94,9 +73,7 @@ impl Stack {
} }
} }
///
/// Swaps two stack elements. /// Swaps two stack elements.
///
pub fn swap(&mut self, index: usize) -> anyhow::Result<()> { pub fn swap(&mut self, index: usize) -> anyhow::Result<()> {
if self.elements.len() < index + 1 { if self.elements.len() < index + 1 {
anyhow::bail!("Stack underflow"); anyhow::bail!("Stack underflow");
@@ -108,9 +85,7 @@ impl Stack {
Ok(()) Ok(())
} }
///
/// Duplicates a stack element. /// Duplicates a stack element.
///
pub fn dup(&mut self, index: usize) -> anyhow::Result<Element> { pub fn dup(&mut self, index: usize) -> anyhow::Result<Element> {
if self.elements.len() < index { if self.elements.len() < index {
anyhow::bail!("Stack underflow"); anyhow::bail!("Stack underflow");
@@ -119,16 +94,12 @@ impl Stack {
Ok(self.elements[self.elements.len() - index].to_owned()) Ok(self.elements[self.elements.len() - index].to_owned())
} }
///
/// Returns the stack length. /// Returns the stack length.
///
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.elements.len() self.elements.len()
} }
///
/// Returns an emptiness flag. /// Returns an emptiness flag.
///
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.elements.len() == 0 self.elements.len() == 0
} }
@@ -1,6 +1,4 @@
//!
//! The Ethereal IR block. //! The Ethereal IR block.
//!
pub mod element; pub mod element;
@@ -14,9 +12,7 @@ use crate::evmla::assembly::instruction::Instruction;
use self::element::stack::Stack as ElementStack; use self::element::stack::Stack as ElementStack;
use self::element::Element; use self::element::Element;
///
/// The Ethereal IR block. /// The Ethereal IR block.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Block { pub struct Block {
/// The Solidity compiler version. /// The Solidity compiler version.
@@ -43,9 +39,7 @@ impl Block {
/// The predecessors hashset initial capacity. /// The predecessors hashset initial capacity.
pub const PREDECESSORS_HASHSET_DEFAULT_CAPACITY: usize = 4; pub const PREDECESSORS_HASHSET_DEFAULT_CAPACITY: usize = 4;
///
/// Assembles a block from the sequence of instructions. /// Assembles a block from the sequence of instructions.
///
pub fn try_from_instructions( pub fn try_from_instructions(
solc_version: semver::Version, solc_version: semver::Version,
code_type: revive_llvm_context::EraVMCodeType, code_type: revive_llvm_context::EraVMCodeType,
@@ -109,9 +103,7 @@ impl Block {
Ok((block, cursor)) Ok((block, cursor))
} }
///
/// Inserts a predecessor tag. /// Inserts a predecessor tag.
///
pub fn insert_predecessor( pub fn insert_predecessor(
&mut self, &mut self,
key: revive_llvm_context::EraVMFunctionBlockKey, key: revive_llvm_context::EraVMFunctionBlockKey,
@@ -1,6 +1,4 @@
//!
//! The Ethereal IR function. //! The Ethereal IR function.
//!
pub mod block; pub mod block;
pub mod queue_element; pub mod queue_element;
@@ -37,9 +35,7 @@ use self::queue_element::QueueElement;
use self::r#type::Type; use self::r#type::Type;
use self::visited_element::VisitedElement; use self::visited_element::VisitedElement;
///
/// The Ethereal IR function. /// The Ethereal IR function.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
/// The Solidity compiler version. /// The Solidity compiler version.
@@ -55,9 +51,7 @@ pub struct Function {
} }
impl Function { impl Function {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(solc_version: semver::Version, r#type: Type) -> Self { pub fn new(solc_version: semver::Version, r#type: Type) -> Self {
let name = match r#type { let name = match r#type {
Type::Initial => EtherealIR::DEFAULT_ENTRY_FUNCTION_NAME.to_string(), Type::Initial => EtherealIR::DEFAULT_ENTRY_FUNCTION_NAME.to_string(),
@@ -77,9 +71,7 @@ impl Function {
} }
} }
///
/// Runs the function block traversal. /// Runs the function block traversal.
///
pub fn traverse( pub fn traverse(
&mut self, &mut self,
blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>, blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>,
@@ -143,9 +135,7 @@ impl Function {
Ok(()) Ok(())
} }
///
/// Consumes the entry or a conditional block attached to another one. /// Consumes the entry or a conditional block attached to another one.
///
fn consume_block( fn consume_block(
&mut self, &mut self,
blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>, blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>,
@@ -219,12 +209,9 @@ impl Function {
Ok(()) Ok(())
} }
///
/// Processes an instruction, returning an error, if there is an invalid stack state. /// Processes an instruction, returning an error, if there is an invalid stack state.
///
/// The blocks with an invalid stack state are considered being partially unreachable, and /// The blocks with an invalid stack state are considered being partially unreachable, and
/// the invalid part is truncated after terminating with an `INVALID` instruction. /// the invalid part is truncated after terminating with an `INVALID` instruction.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn handle_instruction( fn handle_instruction(
blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>, blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>,
@@ -993,9 +980,7 @@ impl Function {
Ok(()) Ok(())
} }
///
/// Updates the stack data with input and output data. /// Updates the stack data with input and output data.
///
fn update_io_data( fn update_io_data(
block_stack: &mut Stack, block_stack: &mut Stack,
block_element: &mut BlockElement, block_element: &mut BlockElement,
@@ -1017,9 +1002,7 @@ impl Function {
Ok(()) Ok(())
} }
///
/// Handles the recursive function call. /// Handles the recursive function call.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn handle_recursive_function_call( fn handle_recursive_function_call(
recursive_function: &RecursiveFunction, recursive_function: &RecursiveFunction,
@@ -1095,9 +1078,7 @@ impl Function {
Ok((return_address, stack_output)) Ok((return_address, stack_output))
} }
///
/// Pushes a block into the function. /// Pushes a block into the function.
///
fn insert_block(&mut self, mut block: Block) -> &mut Block { fn insert_block(&mut self, mut block: Block) -> &mut Block {
let key = block.key.clone(); let key = block.key.clone();
@@ -1120,11 +1101,8 @@ impl Function {
.expect("Always exists") .expect("Always exists")
} }
///
/// Checks whether the tag value actually references an existing block. /// Checks whether the tag value actually references an existing block.
///
/// Checks both deploy and runtime code. /// Checks both deploy and runtime code.
///
fn is_tag_value_valid( fn is_tag_value_valid(
blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>, blocks: &HashMap<revive_llvm_context::EraVMFunctionBlockKey, Block>,
tag: &num::BigUint, tag: &num::BigUint,
@@ -1138,9 +1116,7 @@ impl Function {
)) ))
} }
///
/// Finalizes the function data. /// Finalizes the function data.
///
fn finalize(&mut self) { fn finalize(&mut self) {
for (_tag, blocks) in self.blocks.iter() { for (_tag, blocks) in self.blocks.iter() {
for block in blocks.iter() { for block in blocks.iter() {
@@ -1,12 +1,8 @@
//!
//! The Ethereal IR block queue element. //! The Ethereal IR block queue element.
//!
use crate::evmla::ethereal_ir::function::block::element::stack::Stack; use crate::evmla::ethereal_ir::function::block::element::stack::Stack;
///
/// The Ethereal IR block queue element. /// The Ethereal IR block queue element.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct QueueElement { pub struct QueueElement {
/// The block key. /// The block key.
@@ -18,9 +14,7 @@ pub struct QueueElement {
} }
impl QueueElement { impl QueueElement {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
block_key: revive_llvm_context::EraVMFunctionBlockKey, block_key: revive_llvm_context::EraVMFunctionBlockKey,
predecessor: Option<(revive_llvm_context::EraVMFunctionBlockKey, usize)>, predecessor: Option<(revive_llvm_context::EraVMFunctionBlockKey, usize)>,
@@ -1,10 +1,6 @@
//!
//! The Ethereal IR function type. //! The Ethereal IR function type.
//!
///
/// The Ethereal IR function type. /// The Ethereal IR function type.
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Type { pub enum Type {
/// The initial function, combining deploy and runtime code. /// The initial function, combining deploy and runtime code.
@@ -23,16 +19,12 @@ pub enum Type {
} }
impl Type { impl Type {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new_initial() -> Self { pub fn new_initial() -> Self {
Self::Initial Self::Initial
} }
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new_recursive( pub fn new_recursive(
name: String, name: String,
block_key: revive_llvm_context::EraVMFunctionBlockKey, block_key: revive_llvm_context::EraVMFunctionBlockKey,
@@ -1,12 +1,8 @@
//!
//! The Ethereal IR block visited element. //! The Ethereal IR block visited element.
//!
use std::cmp::Ordering; use std::cmp::Ordering;
///
/// The Ethereal IR block visited element. /// The Ethereal IR block visited element.
///
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VisitedElement { pub struct VisitedElement {
/// The block key. /// The block key.
@@ -16,9 +12,7 @@ pub struct VisitedElement {
} }
impl VisitedElement { impl VisitedElement {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
block_key: revive_llvm_context::EraVMFunctionBlockKey, block_key: revive_llvm_context::EraVMFunctionBlockKey,
stack_hash: md5::Digest, stack_hash: md5::Digest,
@@ -1,6 +1,4 @@
//!
//! The Ethereal IR of the EVM bytecode. //! The Ethereal IR of the EVM bytecode.
//!
pub mod entry_link; pub mod entry_link;
pub mod function; pub mod function;
@@ -16,18 +14,14 @@ use self::function::block::Block;
use self::function::r#type::Type as FunctionType; use self::function::r#type::Type as FunctionType;
use self::function::Function; use self::function::Function;
///
/// The Ethereal IR of the EVM bytecode. /// The Ethereal IR of the EVM bytecode.
///
/// The Ethereal IR (EthIR) is a special IR between the EVM legacy assembly and LLVM IR. It is /// The Ethereal IR (EthIR) is a special IR between the EVM legacy assembly and LLVM IR. It is
/// created to facilitate the translation and provide an additional environment for applying some /// created to facilitate the translation and provide an additional environment for applying some
/// transformations, duplicating parts of the call and control flow graphs, tracking the /// transformations, duplicating parts of the call and control flow graphs, tracking the
/// data flow, and a few more algorithms of static analysis. /// data flow, and a few more algorithms of static analysis.
///
/// The most important feature of EthIR is flattening the block tags and duplicating blocks for /// The most important feature of EthIR is flattening the block tags and duplicating blocks for
/// each of initial states of the stack. The LLVM IR supports only static control flow, so the /// each of initial states of the stack. The LLVM IR supports only static control flow, so the
/// stack state must be known all the way throughout the program. /// stack state must be known all the way throughout the program.
///
#[derive(Debug)] #[derive(Debug)]
pub struct EtherealIR { pub struct EtherealIR {
/// The Solidity compiler version. /// The Solidity compiler version.
@@ -47,9 +41,7 @@ impl EtherealIR {
/// The blocks hashmap initial capacity. /// The blocks hashmap initial capacity.
pub const BLOCKS_HASHMAP_DEFAULT_CAPACITY: usize = 64; pub const BLOCKS_HASHMAP_DEFAULT_CAPACITY: usize = 64;
///
/// Assembles a sequence of functions from the sequence of instructions. /// Assembles a sequence of functions from the sequence of instructions.
///
pub fn new( pub fn new(
solc_version: semver::Version, solc_version: semver::Version,
extra_metadata: ExtraMetadata, extra_metadata: ExtraMetadata,
@@ -73,9 +65,7 @@ impl EtherealIR {
}) })
} }
///
/// Gets blocks for the specified type of the contract code. /// Gets blocks for the specified type of the contract code.
///
pub fn get_blocks( pub fn get_blocks(
solc_version: semver::Version, solc_version: semver::Version,
code_type: revive_llvm_context::EraVMCodeType, code_type: revive_llvm_context::EraVMCodeType,
-2
View File
@@ -1,6 +1,4 @@
//!
//! The EVM legacy assembly compiling tools. //! The EVM legacy assembly compiling tools.
//!
pub mod assembly; pub mod assembly;
pub mod ethereal_ir; pub mod ethereal_ir;
-14
View File
@@ -1,6 +1,4 @@
//!
//! Solidity to EraVM compiler library. //! Solidity to EraVM compiler library.
//!
pub(crate) mod build; pub(crate) mod build;
pub(crate) mod r#const; pub(crate) mod r#const;
@@ -48,9 +46,7 @@ pub mod tests;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::path::PathBuf; use std::path::PathBuf;
///
/// Runs the Yul mode. /// Runs the Yul mode.
///
pub fn yul( pub fn yul(
input_files: &[PathBuf], input_files: &[PathBuf],
solc: &mut SolcCompiler, solc: &mut SolcCompiler,
@@ -94,9 +90,7 @@ pub fn yul(
Ok(build) Ok(build)
} }
///
/// Runs the LLVM IR mode. /// Runs the LLVM IR mode.
///
pub fn llvm_ir( pub fn llvm_ir(
input_files: &[PathBuf], input_files: &[PathBuf],
optimizer_settings: revive_llvm_context::OptimizerSettings, optimizer_settings: revive_llvm_context::OptimizerSettings,
@@ -126,9 +120,7 @@ pub fn llvm_ir(
Ok(build) Ok(build)
} }
///
/// Runs the EraVM assembly mode. /// Runs the EraVM assembly mode.
///
pub fn zkasm( pub fn zkasm(
input_files: &[PathBuf], input_files: &[PathBuf],
include_metadata_hash: bool, include_metadata_hash: bool,
@@ -157,9 +149,7 @@ pub fn zkasm(
Ok(build) Ok(build)
} }
///
/// Runs the standard output mode. /// Runs the standard output mode.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn standard_output( pub fn standard_output(
input_files: &[PathBuf], input_files: &[PathBuf],
@@ -250,9 +240,7 @@ pub fn standard_output(
Ok(build) Ok(build)
} }
///
/// Runs the standard JSON mode. /// Runs the standard JSON mode.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn standard_json( pub fn standard_json(
solc: &mut SolcCompiler, solc: &mut SolcCompiler,
@@ -332,9 +320,7 @@ pub fn standard_json(
std::process::exit(0); std::process::exit(0);
} }
///
/// Runs the combined JSON mode. /// Runs the combined JSON mode.
///
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn combined_json( pub fn combined_json(
format: String, format: String,
-8
View File
@@ -1,6 +1,4 @@
//!
//! The missing Solidity libraries. //! The missing Solidity libraries.
//!
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::HashSet; use std::collections::HashSet;
@@ -8,25 +6,19 @@ use std::collections::HashSet;
use crate::solc::standard_json::output::Output as StandardJsonOutput; use crate::solc::standard_json::output::Output as StandardJsonOutput;
use crate::solc::version::Version as SolcVersion; use crate::solc::version::Version as SolcVersion;
///
/// The missing Solidity libraries. /// The missing Solidity libraries.
///
pub struct MissingLibraries { pub struct MissingLibraries {
/// The missing libraries. /// The missing libraries.
pub contract_libraries: BTreeMap<String, HashSet<String>>, pub contract_libraries: BTreeMap<String, HashSet<String>>,
} }
impl MissingLibraries { impl MissingLibraries {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(contract_libraries: BTreeMap<String, HashSet<String>>) -> Self { pub fn new(contract_libraries: BTreeMap<String, HashSet<String>>) -> Self {
Self { contract_libraries } Self { contract_libraries }
} }
///
/// Writes the missing libraries to the standard JSON. /// Writes the missing libraries to the standard JSON.
///
pub fn write_to_standard_json( pub fn write_to_standard_json(
mut self, mut self,
standard_json: &mut StandardJsonOutput, standard_json: &mut StandardJsonOutput,
-7
View File
@@ -1,8 +1,5 @@
//!
//! Process for compiling a single compilation unit. //! Process for compiling a single compilation unit.
//!
//! The input data. //! The input data.
//!
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
@@ -10,9 +7,7 @@ use serde::Serialize;
use crate::project::contract::Contract; use crate::project::contract::Contract;
use crate::project::Project; use crate::project::Project;
///
/// The input data. /// The input data.
///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Input { pub struct Input {
/// The contract representation. /// The contract representation.
@@ -32,9 +27,7 @@ pub struct Input {
} }
impl Input { impl Input {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new( pub fn new(
contract: Contract, contract: Contract,
project: Project, project: Project,
-6
View File
@@ -1,6 +1,4 @@
//!
//! Process for compiling a single compilation unit. //! Process for compiling a single compilation unit.
//!
pub mod input; pub mod input;
pub mod output; pub mod output;
@@ -18,9 +16,7 @@ use self::output::Output;
/// The overriden executable name used when the compiler is run as a library. /// The overriden executable name used when the compiler is run as a library.
pub static EXECUTABLE: OnceCell<PathBuf> = OnceCell::new(); pub static EXECUTABLE: OnceCell<PathBuf> = OnceCell::new();
///
/// Read input from `stdin`, compile a contract, and write the output to `stdout`. /// Read input from `stdin`, compile a contract, and write the output to `stdout`.
///
pub fn run() -> anyhow::Result<()> { pub fn run() -> anyhow::Result<()> {
let mut stdin = std::io::stdin(); let mut stdin = std::io::stdin();
let mut stdout = std::io::stdout(); let mut stdout = std::io::stdout();
@@ -60,9 +56,7 @@ pub fn run() -> anyhow::Result<()> {
} }
} }
///
/// Runs this process recursively to compile a single contract. /// Runs this process recursively to compile a single contract.
///
pub fn call(input: Input) -> anyhow::Result<Output> { pub fn call(input: Input) -> anyhow::Result<Output> {
let input_json = serde_json::to_vec(&input).expect("Always valid"); let input_json = serde_json::to_vec(&input).expect("Always valid");
-7
View File
@@ -1,17 +1,12 @@
//!
//! Process for compiling a single compilation unit. //! Process for compiling a single compilation unit.
//!
//! The output data. //! The output data.
//!
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use crate::build::contract::Contract as ContractBuild; use crate::build::contract::Contract as ContractBuild;
///
/// The output data. /// The output data.
///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Output { pub struct Output {
/// The contract build. /// The contract build.
@@ -19,9 +14,7 @@ pub struct Output {
} }
impl Output { impl Output {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(build: ContractBuild) -> Self { pub fn new(build: ContractBuild) -> Self {
Self { build } Self { build }
} }
@@ -1,6 +1,4 @@
//!
//! The contract EVM legacy assembly source code. //! The contract EVM legacy assembly source code.
//!
use std::collections::HashSet; use std::collections::HashSet;
@@ -10,9 +8,7 @@ use serde::Serialize;
use crate::evmla::assembly::Assembly; use crate::evmla::assembly::Assembly;
use crate::solc::standard_json::output::contract::evm::extra_metadata::ExtraMetadata; use crate::solc::standard_json::output::contract::evm::extra_metadata::ExtraMetadata;
///
/// The contract EVM legacy assembly source code. /// The contract EVM legacy assembly source code.
///
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
@@ -22,17 +18,13 @@ pub struct EVMLA {
} }
impl EVMLA { impl EVMLA {
///
/// A shortcut constructor. /// A shortcut constructor.
///
pub fn new(mut assembly: Assembly, extra_metadata: ExtraMetadata) -> Self { pub fn new(mut assembly: Assembly, extra_metadata: ExtraMetadata) -> Self {
assembly.extra_metadata = Some(extra_metadata); assembly.extra_metadata = Some(extra_metadata);
Self { assembly } Self { assembly }
} }
///
/// Get the list of missing deployable libraries. /// Get the list of missing deployable libraries.
///
pub fn get_missing_libraries(&self) -> HashSet<String> { pub fn get_missing_libraries(&self) -> HashSet<String> {
self.assembly.get_missing_libraries() self.assembly.get_missing_libraries()
} }

Some files were not shown because too many files have changed in this diff Show More