mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 19:11:04 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b19981a513 | |||
| 10e50e446b | |||
| 939a8f2f78 | |||
| ed608699af | |||
| 75fc23c810 | |||
| 486c9c28a1 | |||
| 7656c6a8b4 | |||
| 8754d802fa | |||
| 63f0266fff |
@@ -6,6 +6,19 @@ This is a development pre-release.
|
|||||||
|
|
||||||
Supported `polkadot-sdk` rev: `2503.0.1`
|
Supported `polkadot-sdk` rev: `2503.0.1`
|
||||||
|
|
||||||
|
## v0.3.0
|
||||||
|
|
||||||
|
This is a development pre-release.
|
||||||
|
|
||||||
|
Supported `polkadot-sdk` rev: `2503.0.1`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- llvm-context: Bugfix the SAR YUL builtin translation.
|
||||||
|
- runtime-api: Add the missing `memset` builtin.
|
||||||
|
- npm package: Bugfix the exports field defined in the `package.json`.
|
||||||
|
|
||||||
|
|
||||||
## v0.2.0
|
## v0.2.0
|
||||||
|
|
||||||
This is a development pre-release.
|
This is a development pre-release.
|
||||||
|
|||||||
Generated
+7
-7
@@ -8546,7 +8546,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "resolc"
|
name = "resolc"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -8617,7 +8617,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-integration"
|
name = "revive-integration"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-primitives 1.1.2",
|
"alloy-primitives 1.1.2",
|
||||||
"alloy-sol-types 1.1.2",
|
"alloy-sol-types 1.1.2",
|
||||||
@@ -8645,7 +8645,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-llvm-builder"
|
name = "revive-llvm-builder"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
@@ -8667,7 +8667,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-llvm-context"
|
name = "revive-llvm-context"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"hex",
|
"hex",
|
||||||
@@ -8708,7 +8708,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-runtime-api"
|
name = "revive-runtime-api"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"inkwell",
|
"inkwell",
|
||||||
@@ -8730,7 +8730,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-stdlib"
|
name = "revive-stdlib"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"inkwell",
|
"inkwell",
|
||||||
"revive-build-utils",
|
"revive-build-utils",
|
||||||
@@ -8738,7 +8738,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-yul"
|
name = "revive-yul"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"inkwell",
|
"inkwell",
|
||||||
|
|||||||
+6
-6
@@ -14,21 +14,21 @@ repository = "https://github.com/paritytech/revive"
|
|||||||
rust-version = "1.85.0"
|
rust-version = "1.85.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
resolc = { version = "0.2.0", path = "crates/resolc" }
|
resolc = { version = "0.3.0", path = "crates/resolc" }
|
||||||
revive-benchmarks = { version = "0.1.0", path = "crates/benchmarks" }
|
revive-benchmarks = { version = "0.1.0", path = "crates/benchmarks" }
|
||||||
revive-builtins = { version = "0.1.0", path = "crates/builtins" }
|
revive-builtins = { version = "0.1.0", path = "crates/builtins" }
|
||||||
revive-common = { version = "0.1.0", path = "crates/common" }
|
revive-common = { version = "0.1.0", path = "crates/common" }
|
||||||
revive-differential = { version = "0.1.0", path = "crates/differential" }
|
revive-differential = { version = "0.1.0", path = "crates/differential" }
|
||||||
revive-integration = { version = "0.1.0", path = "crates/integration" }
|
revive-integration = { version = "0.1.1", path = "crates/integration" }
|
||||||
revive-linker = { version = "0.1.0", path = "crates/linker" }
|
revive-linker = { version = "0.1.0", path = "crates/linker" }
|
||||||
lld-sys = { version = "0.1.0", path = "crates/lld-sys" }
|
lld-sys = { version = "0.1.0", path = "crates/lld-sys" }
|
||||||
revive-llvm-context = { version = "0.2.0", path = "crates/llvm-context" }
|
revive-llvm-context = { version = "0.3.0", path = "crates/llvm-context" }
|
||||||
revive-runtime-api = { version = "0.1.0", path = "crates/runtime-api" }
|
revive-runtime-api = { version = "0.2.0", path = "crates/runtime-api" }
|
||||||
revive-runner = { version = "0.1.0", path = "crates/runner" }
|
revive-runner = { version = "0.1.0", path = "crates/runner" }
|
||||||
revive-solc-json-interface = { version = "0.2.0", path = "crates/solc-json-interface" }
|
revive-solc-json-interface = { version = "0.2.0", path = "crates/solc-json-interface" }
|
||||||
revive-stdlib = { version = "0.1.0", path = "crates/stdlib" }
|
revive-stdlib = { version = "0.1.1", path = "crates/stdlib" }
|
||||||
revive-build-utils = { version = "0.1.0", path = "crates/build-utils" }
|
revive-build-utils = { version = "0.1.0", path = "crates/build-utils" }
|
||||||
revive-yul = { version = "0.2.0", path = "crates/yul" }
|
revive-yul = { version = "0.2.1", path = "crates/yul" }
|
||||||
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
cc = "1.2"
|
cc = "1.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-integration"
|
name = "revive-integration"
|
||||||
version.workspace = true
|
version = "0.1.1"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8;
|
||||||
|
|
||||||
|
/* runner.json
|
||||||
|
{
|
||||||
|
"differential": true,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"Instantiate": {
|
||||||
|
"code": {
|
||||||
|
"Solidity": {
|
||||||
|
"contract": "SAR"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
contract SAR {
|
||||||
|
constructor() payable {
|
||||||
|
assert(sar(0x03, 0x01) == 0x01);
|
||||||
|
assert(
|
||||||
|
sar(
|
||||||
|
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
|
||||||
|
0x01
|
||||||
|
) == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
sar(
|
||||||
|
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
|
||||||
|
0xff
|
||||||
|
) == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
sar(
|
||||||
|
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff,
|
||||||
|
0x100
|
||||||
|
) == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sar(uint256 a, uint256 b) public pure returns (uint256 c) {
|
||||||
|
assembly {
|
||||||
|
c := sar(b, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,6 +60,7 @@ test_spec!(mload, "MLoad", "MLoad.sol");
|
|||||||
test_spec!(delegate_no_contract, "DelegateCaller", "DelegateCaller.sol");
|
test_spec!(delegate_no_contract, "DelegateCaller", "DelegateCaller.sol");
|
||||||
test_spec!(function_type, "FunctionType", "FunctionType.sol");
|
test_spec!(function_type, "FunctionType", "FunctionType.sol");
|
||||||
test_spec!(layout_at, "LayoutAt", "LayoutAt.sol");
|
test_spec!(layout_at, "LayoutAt", "LayoutAt.sol");
|
||||||
|
test_spec!(shift_arithmetic_right, "SAR", "SAR.sol");
|
||||||
|
|
||||||
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
||||||
vec![Instantiate {
|
vec![Instantiate {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ authors = [
|
|||||||
"Anton Baliasnikov <aba@matterlabs.dev>",
|
"Anton Baliasnikov <aba@matterlabs.dev>",
|
||||||
"Cyrill Leutwiler <cyrill@parity.io>",
|
"Cyrill Leutwiler <cyrill@parity.io>",
|
||||||
]
|
]
|
||||||
version.workspace = true
|
version = "0.2.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ impl std::str::FromStr for BuildType {
|
|||||||
"Release" => Ok(Self::Release),
|
"Release" => Ok(Self::Release),
|
||||||
"RelWithDebInfo" => Ok(Self::RelWithDebInfo),
|
"RelWithDebInfo" => Ok(Self::RelWithDebInfo),
|
||||||
"MinSizeRel" => Ok(Self::MinSizeRel),
|
"MinSizeRel" => Ok(Self::MinSizeRel),
|
||||||
value => Err(format!("Unsupported build type: `{}`", value)),
|
value => Err(format!("Unsupported build type: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ impl std::str::FromStr for CcacheVariant {
|
|||||||
match value {
|
match value {
|
||||||
"ccache" => Ok(Self::Ccache),
|
"ccache" => Ok(Self::Ccache),
|
||||||
"sccache" => Ok(Self::Sccache),
|
"sccache" => Ok(Self::Sccache),
|
||||||
value => Err(format!("Unsupported ccache variant: `{}`", value)),
|
value => Err(format!("Unsupported ccache variant: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,23 +127,22 @@ pub fn build(
|
|||||||
sanitizer: Option<sanitizer::Sanitizer>,
|
sanitizer: Option<sanitizer::Sanitizer>,
|
||||||
enable_valgrind: bool,
|
enable_valgrind: bool,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
log::trace!("build type: {:?}", build_type);
|
log::trace!("build type: {build_type:?}");
|
||||||
log::trace!("target env: {:?}", target_env);
|
log::trace!("target env: {target_env:?}");
|
||||||
log::trace!("targets: {:?}", targets);
|
log::trace!("targets: {targets:?}");
|
||||||
log::trace!("llvm projects: {:?}", llvm_projects);
|
log::trace!("llvm projects: {llvm_projects:?}");
|
||||||
log::trace!("enable rtti: {:?}", enable_rtti);
|
log::trace!("enable rtti: {enable_rtti:?}");
|
||||||
log::trace!("default target: {:?}", default_target);
|
log::trace!("default target: {default_target:?}");
|
||||||
log::trace!("eneable tests: {:?}", enable_tests);
|
log::trace!("eneable tests: {enable_tests:?}");
|
||||||
log::trace!("enable_coverage: {:?}", enable_coverage);
|
log::trace!("enable_coverage: {enable_coverage:?}");
|
||||||
log::trace!("extra args: {:?}", extra_args);
|
log::trace!("extra args: {extra_args:?}");
|
||||||
log::trace!("sanitzer: {:?}", sanitizer);
|
log::trace!("sanitzer: {sanitizer:?}");
|
||||||
log::trace!("enable valgrind: {:?}", enable_valgrind);
|
log::trace!("enable valgrind: {enable_valgrind:?}");
|
||||||
|
|
||||||
if !PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE).exists() {
|
if !PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE).exists() {
|
||||||
log::error!(
|
log::error!(
|
||||||
"LLVM project source directory {} does not exist (run `revive-llvm --target-env {} clone`)",
|
"LLVM project source directory {} does not exist (run `revive-llvm --target-env {target_env} clone`)",
|
||||||
LLVMPath::DIRECTORY_LLVM_SOURCE,
|
LLVMPath::DIRECTORY_LLVM_SOURCE
|
||||||
target_env
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ impl std::str::FromStr for LLVMProject {
|
|||||||
"lld" => Ok(Self::LLD),
|
"lld" => Ok(Self::LLD),
|
||||||
"lldb" => Ok(Self::LLDB),
|
"lldb" => Ok(Self::LLDB),
|
||||||
"mlir" => Ok(Self::MLIR),
|
"mlir" => Ok(Self::MLIR),
|
||||||
value => Err(format!("Unsupported LLVM project to enable: `{}`", value)),
|
value => Err(format!("Unsupported LLVM project to enable: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl TryFrom<&PathBuf> for Lock {
|
|||||||
fn try_from(path: &PathBuf) -> Result<Self, Self::Error> {
|
fn try_from(path: &PathBuf) -> Result<Self, Self::Error> {
|
||||||
let mut config_str = String::new();
|
let mut config_str = String::new();
|
||||||
let mut config_file =
|
let mut config_file =
|
||||||
File::open(path).with_context(|| format!("Error opening {:?} file", path))?;
|
File::open(path).with_context(|| format!("Error opening {path:?} file"))?;
|
||||||
config_file.read_to_string(&mut config_str)?;
|
config_file.read_to_string(&mut config_str)?;
|
||||||
Ok(toml::from_str(&config_str)?)
|
Ok(toml::from_str(&config_str)?)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl FromStr for Platform {
|
|||||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||||
match value {
|
match value {
|
||||||
"PolkaVM" => Ok(Self::PolkaVM),
|
"PolkaVM" => Ok(Self::PolkaVM),
|
||||||
value => Err(format!("Unsupported platform: `{}`", value)),
|
value => Err(format!("Unsupported platform: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ fn main_inner() -> anyhow::Result<()> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
log::debug!("extra_args: {:#?}", extra_args);
|
log::debug!("extra_args: {extra_args:#?}");
|
||||||
log::debug!("extra_args_unescaped: {:#?}", extra_args_unescaped);
|
log::debug!("extra_args_unescaped: {extra_args_unescaped:#?}");
|
||||||
|
|
||||||
if let Some(ccache_variant) = ccache_variant {
|
if let Some(ccache_variant) = ccache_variant {
|
||||||
revive_llvm_builder::utils::check_presence(ccache_variant.to_string().as_str())?;
|
revive_llvm_builder::utils::check_presence(ccache_variant.to_string().as_str())?;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl std::str::FromStr for Sanitizer {
|
|||||||
"thread" => Ok(Self::Thread),
|
"thread" => Ok(Self::Thread),
|
||||||
"dataflow" => Ok(Self::DataFlow),
|
"dataflow" => Ok(Self::DataFlow),
|
||||||
"address;undefined" => Ok(Self::AddressUndefined),
|
"address;undefined" => Ok(Self::AddressUndefined),
|
||||||
value => Err(format!("Unsupported sanitizer: `{}`", value)),
|
value => Err(format!("Unsupported sanitizer: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ impl std::str::FromStr for TargetEnv {
|
|||||||
"gnu" => Ok(Self::GNU),
|
"gnu" => Ok(Self::GNU),
|
||||||
"musl" => Ok(Self::MUSL),
|
"musl" => Ok(Self::MUSL),
|
||||||
"emscripten" => Ok(Self::Emscripten),
|
"emscripten" => Ok(Self::Emscripten),
|
||||||
value => Err(format!("Unsupported target environment: `{}`", value)),
|
value => Err(format!("Unsupported target environment: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ impl std::str::FromStr for TargetTriple {
|
|||||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||||
match value {
|
match value {
|
||||||
"polkavm" => Ok(Self::PolkaVM),
|
"polkavm" => Ok(Self::PolkaVM),
|
||||||
value => Err(format!("Unsupported target triple: `{}`", value)),
|
value => Err(format!("Unsupported target triple: `{value}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ pub fn unpack_tar(filename: PathBuf, path: &str) -> anyhow::Result<()> {
|
|||||||
pub fn download_musl(name: &str) -> anyhow::Result<()> {
|
pub fn download_musl(name: &str) -> anyhow::Result<()> {
|
||||||
log::info!("downloading musl {name}");
|
log::info!("downloading musl {name}");
|
||||||
let tar_file_name = format!("{name}.tar.gz");
|
let tar_file_name = format!("{name}.tar.gz");
|
||||||
let url = format!("{}/{tar_file_name}", MUSL_SNAPSHOTS_URL);
|
let url = format!("{MUSL_SNAPSHOTS_URL}/{tar_file_name}");
|
||||||
let target_path = crate::llvm_path::DIRECTORY_LLVM_TARGET
|
let target_path = crate::llvm_path::DIRECTORY_LLVM_TARGET
|
||||||
.get()
|
.get()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -223,6 +223,6 @@ pub fn install_emsdk() -> anyhow::Result<()> {
|
|||||||
/// The LLVM target directory default path.
|
/// The LLVM target directory default path.
|
||||||
pub fn directory_target_llvm(target_env: crate::target_env::TargetEnv) -> PathBuf {
|
pub fn directory_target_llvm(target_env: crate::target_env::TargetEnv) -> PathBuf {
|
||||||
crate::llvm_path::DIRECTORY_LLVM_TARGET
|
crate::llvm_path::DIRECTORY_LLVM_TARGET
|
||||||
.get_or_init(|| PathBuf::from(format!("./target-llvm/{}/", target_env)))
|
.get_or_init(|| PathBuf::from(format!("./target-llvm/{target_env}/")))
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-llvm-context"
|
name = "revive-llvm-context"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
use inkwell::values::BasicValue;
|
use inkwell::values::BasicValue;
|
||||||
|
|
||||||
use crate::polkavm::context::runtime::RuntimeFunction;
|
//use crate::polkavm::context::runtime::RuntimeFunction;
|
||||||
use crate::polkavm::context::Context;
|
use crate::polkavm::context::Context;
|
||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
use crate::PolkaVMDivisionFunction;
|
//use crate::PolkaVMDivisionFunction;
|
||||||
use crate::PolkaVMRemainderFunction;
|
//use crate::PolkaVMRemainderFunction;
|
||||||
use crate::PolkaVMSignedDivisionFunction;
|
//use crate::PolkaVMSignedDivisionFunction;
|
||||||
use crate::PolkaVMSignedRemainderFunction;
|
//use crate::PolkaVMSignedRemainderFunction;
|
||||||
|
|
||||||
/// Translates the arithmetic addition.
|
/// Translates the arithmetic addition.
|
||||||
pub fn addition<'ctx, D>(
|
pub fn addition<'ctx, D>(
|
||||||
@@ -64,11 +64,21 @@ pub fn division<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let name = <PolkaVMDivisionFunction as RuntimeFunction<D>>::NAME;
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "div_result_pointer");
|
||||||
let declaration = <PolkaVMDivisionFunction as RuntimeFunction<D>>::declaration(context);
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
|
||||||
Ok(context
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
|
||||||
.build_call(declaration, &[operand_1.into(), operand_2.into()], "div")
|
|
||||||
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::DIV, arguments);
|
||||||
|
context.build_load(result_pointer, "div_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the arithmetic remainder.
|
/// Translates the arithmetic remainder.
|
||||||
@@ -80,11 +90,21 @@ pub fn remainder<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let name = <PolkaVMRemainderFunction as RuntimeFunction<D>>::NAME;
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "rem_result_pointer");
|
||||||
let declaration = <PolkaVMRemainderFunction as RuntimeFunction<D>>::declaration(context);
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
|
||||||
Ok(context
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
|
||||||
.build_call(declaration, &[operand_1.into(), operand_2.into()], "rem")
|
|
||||||
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::MOD, arguments);
|
||||||
|
context.build_load(result_pointer, "rem_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the signed arithmetic division.
|
/// Translates the signed arithmetic division.
|
||||||
@@ -99,11 +119,21 @@ pub fn division_signed<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let name = <PolkaVMSignedDivisionFunction as RuntimeFunction<D>>::NAME;
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "sdiv_result_pointer");
|
||||||
let declaration = <PolkaVMSignedDivisionFunction as RuntimeFunction<D>>::declaration(context);
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
|
||||||
Ok(context
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
|
||||||
.build_call(declaration, &[operand_1.into(), operand_2.into()], "sdiv")
|
|
||||||
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::SDIV, arguments);
|
||||||
|
context.build_load(result_pointer, "sdiv_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the signed arithmetic remainder.
|
/// Translates the signed arithmetic remainder.
|
||||||
@@ -115,9 +145,19 @@ pub fn remainder_signed<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let name = <PolkaVMSignedRemainderFunction as RuntimeFunction<D>>::NAME;
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "srem_result_pointer");
|
||||||
let declaration = <PolkaVMSignedRemainderFunction as RuntimeFunction<D>>::declaration(context);
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "operand_1_pointer");
|
||||||
Ok(context
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "operand_2_pointer");
|
||||||
.build_call(declaration, &[operand_1.into(), operand_2.into()], "srem")
|
|
||||||
.unwrap_or_else(|| panic!("revive runtime function {name} should return a value",)))
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::SMOD, arguments);
|
||||||
|
context.build_load(result_pointer, "rsem_result")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ where
|
|||||||
&context.word_type().const_all_ones(),
|
&context.word_type().const_all_ones(),
|
||||||
overflow_negative_block,
|
overflow_negative_block,
|
||||||
),
|
),
|
||||||
(&context.word_const(0), overflow_block),
|
(&context.word_const(0), overflow_positive_block),
|
||||||
]);
|
]);
|
||||||
Ok(result.as_basic_value())
|
Ok(result.as_basic_value())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
//! Translates the mathematical operations.
|
//! Translates the mathematical operations.
|
||||||
|
|
||||||
use inkwell::values::BasicValue;
|
|
||||||
|
|
||||||
use crate::polkavm::context::Context;
|
use crate::polkavm::context::Context;
|
||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
|
|
||||||
@@ -15,17 +13,26 @@ pub fn add_mod<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "addmod_result_pointer");
|
||||||
context.llvm_runtime().add_mod,
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_1");
|
||||||
&[
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_2");
|
||||||
operand_1.as_basic_value_enum(),
|
let modulo_pointer =
|
||||||
operand_2.as_basic_value_enum(),
|
context.build_alloca_at_entry(context.word_type(), "addmod_modulo_operand");
|
||||||
modulo.as_basic_value_enum(),
|
|
||||||
],
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
"add_mod_call",
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
)
|
context.build_store(modulo_pointer, modulo)?;
|
||||||
.expect("Always exists"))
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
modulo_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::ADDMOD, arguments);
|
||||||
|
context.build_load(result_pointer, "addmod_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `mulmod` instruction.
|
/// Translates the `mulmod` instruction.
|
||||||
@@ -38,17 +45,26 @@ pub fn mul_mod<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "mulmod_result_pointer");
|
||||||
context.llvm_runtime().mul_mod,
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_1");
|
||||||
&[
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_2");
|
||||||
operand_1.as_basic_value_enum(),
|
let modulo_pointer =
|
||||||
operand_2.as_basic_value_enum(),
|
context.build_alloca_at_entry(context.word_type(), "mulmod_modulo_operand");
|
||||||
modulo.as_basic_value_enum(),
|
|
||||||
],
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
"mul_mod_call",
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
)
|
context.build_store(modulo_pointer, modulo)?;
|
||||||
.expect("Always exists"))
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
modulo_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::MULMOD, arguments);
|
||||||
|
context.build_load(result_pointer, "addmod_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `exp` instruction.
|
/// Translates the `exp` instruction.
|
||||||
@@ -60,13 +76,22 @@ pub fn exponent<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "exp_result_pointer");
|
||||||
.build_call(
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "exp_value_pointer");
|
||||||
context.llvm_runtime().exp,
|
let exponent_pointer =
|
||||||
&[value.as_basic_value_enum(), exponent.as_basic_value_enum()],
|
context.build_alloca_at_entry(context.word_type(), "exp_exponent_pointer");
|
||||||
"exp_call",
|
|
||||||
)
|
context.build_store(value_pointer, value)?;
|
||||||
.expect("Always exists"))
|
context.build_store(exponent_pointer, exponent)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
value_pointer.to_int(context).into(),
|
||||||
|
exponent_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
|
||||||
|
context.build_load(result_pointer, "exponent_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `signextend` instruction.
|
/// Translates the `signextend` instruction.
|
||||||
@@ -78,11 +103,20 @@ pub fn sign_extend<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "signext_result_pointer");
|
||||||
context.llvm_runtime().sign_extend,
|
let bytes_pointer = context.build_alloca_at_entry(context.word_type(), "bytes_pointer");
|
||||||
&[bytes.as_basic_value_enum(), value.as_basic_value_enum()],
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "signext_value_pointer");
|
||||||
"sign_extend_call",
|
|
||||||
)
|
context.build_store(bytes_pointer, bytes)?;
|
||||||
.expect("Always exists"))
|
context.build_store(value_pointer, value)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
bytes_pointer.to_int(context).into(),
|
||||||
|
value_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
|
||||||
|
context.build_load(result_pointer, "signext_mod_result")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub fn build_assembly_text(
|
|||||||
let mut disassembled_code = Vec::new();
|
let mut disassembled_code = Vec::new();
|
||||||
disassembler
|
disassembler
|
||||||
.disassemble_into(&mut disassembled_code)
|
.disassemble_into(&mut disassembled_code)
|
||||||
.with_context(|| format!("Failed to disassemble contract: {}", contract_path))?;
|
.with_context(|| format!("Failed to disassemble contract: {contract_path}"))?;
|
||||||
|
|
||||||
let assembly_text = String::from_utf8(disassembled_code).with_context(|| {
|
let assembly_text = String::from_utf8(disassembled_code).with_context(|| {
|
||||||
format!("Failed to convert disassembled code to string for contract: {contract_path}")
|
format!("Failed to convert disassembled code to string for contract: {contract_path}")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "resolc"
|
name = "resolc"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -155,8 +155,8 @@ impl Project {
|
|||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(file, names)| {
|
.flat_map(|(file, names)| {
|
||||||
names
|
names
|
||||||
.iter()
|
.keys()
|
||||||
.map(|(name, _address)| format!("{file}:{name}"))
|
.map(|name| format!("{file}:{name}"))
|
||||||
.collect::<HashSet<String>>()
|
.collect::<HashSet<String>>()
|
||||||
})
|
})
|
||||||
.collect::<HashSet<String>>();
|
.collect::<HashSet<String>>();
|
||||||
|
|||||||
@@ -240,9 +240,7 @@ fn main_inner() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
std::io::stdout(),
|
std::io::stdout(),
|
||||||
"Contract `{}` assembly:\n\n{}",
|
"Contract `{path}` assembly:\n\n{assembly_text}"
|
||||||
path,
|
|
||||||
assembly_text
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if arguments.output_binary {
|
if arguments.output_binary {
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ fn compile_evm(
|
|||||||
.expect("source should compile");
|
.expect("source should compile");
|
||||||
let object = &contracts
|
let object = &contracts
|
||||||
.get(contract_name)
|
.get(contract_name)
|
||||||
.unwrap_or_else(|| panic!("contract '{}' didn't produce bin-runtime", contract_name));
|
.unwrap_or_else(|| panic!("contract '{contract_name}' didn't produce bin-runtime"));
|
||||||
let code = if runtime {
|
let code = if runtime {
|
||||||
object.1.object.as_str()
|
object.1.object.as_str()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
object "Test" {
|
||||||
|
code {
|
||||||
|
function allocate(size) -> ptr {
|
||||||
|
ptr := mload(0x40)
|
||||||
|
if iszero(ptr) { ptr := 0x60 }
|
||||||
|
mstore(0x40, add(ptr, size))
|
||||||
|
}
|
||||||
|
let size := datasize("Test_deployed")
|
||||||
|
let offset := allocate(size)
|
||||||
|
datacopy(offset, dataoffset("Test_deployed"), size)
|
||||||
|
return(offset, size)
|
||||||
|
}
|
||||||
|
object "Test_deployed" {
|
||||||
|
code {
|
||||||
|
{
|
||||||
|
let test:=0x5
|
||||||
|
mstore(2,signextend(0x8,0x0))
|
||||||
|
mstore(8,lt(0xc,test))
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0, 65536)
|
||||||
|
}}}
|
||||||
@@ -15,6 +15,11 @@ const pathToBasicYulContract = path.join(
|
|||||||
'yul',
|
'yul',
|
||||||
contractYulFilename
|
contractYulFilename
|
||||||
)
|
)
|
||||||
|
const pathToMemsetYulContract = path.join(
|
||||||
|
pathToContracts,
|
||||||
|
'yul',
|
||||||
|
'memset.yul'
|
||||||
|
)
|
||||||
const pathToBasicSolContract = path.join(
|
const pathToBasicSolContract = path.join(
|
||||||
pathToContracts,
|
pathToContracts,
|
||||||
'solidity',
|
'solidity',
|
||||||
@@ -42,6 +47,7 @@ export const paths = {
|
|||||||
pathToContracts: pathToContracts,
|
pathToContracts: pathToContracts,
|
||||||
pathToBasicSolContract: pathToBasicSolContract,
|
pathToBasicSolContract: pathToBasicSolContract,
|
||||||
pathToBasicYulContract: pathToBasicYulContract,
|
pathToBasicYulContract: pathToBasicYulContract,
|
||||||
|
pathToMemsetYulContract: pathToMemsetYulContract,
|
||||||
pathToSolBinOutputFile: pathToSolBinOutputFile,
|
pathToSolBinOutputFile: pathToSolBinOutputFile,
|
||||||
pathToSolAsmOutputFile: pathToSolAsmOutputFile,
|
pathToSolAsmOutputFile: pathToSolAsmOutputFile,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { executeCommand } from '../src/helper'
|
||||||
|
import { paths } from '../src/entities'
|
||||||
|
|
||||||
|
describe('tests for the memset builtin to be present', () => {
|
||||||
|
// -O3 is required to reproduce.
|
||||||
|
const command = `resolc ${paths.pathToMemsetYulContract} --yul -O3`
|
||||||
|
const result = executeCommand(command)
|
||||||
|
|
||||||
|
it('Valid command exit code = 0', () => {
|
||||||
|
expect(result.exitCode).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('--yul output is presented', () => {
|
||||||
|
expect(result.output).toMatch(/(Compiler run successful)/i)
|
||||||
|
expect(result.output).toMatch(/(No output requested)/i)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
@@ -121,10 +121,10 @@ fn optimizer() {
|
|||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
size_when_optimized_for_cycles < size_when_unoptimized,
|
size_when_optimized_for_cycles < size_when_unoptimized,
|
||||||
"Expected the cycles-optimized bytecode to be smaller than the unoptimized. Optimized: {}B, Unoptimized: {}B", size_when_optimized_for_cycles, size_when_unoptimized,
|
"Expected the cycles-optimized bytecode to be smaller than the unoptimized. Optimized: {size_when_optimized_for_cycles}B, Unoptimized: {size_when_unoptimized}B",
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
size_when_optimized_for_size < size_when_unoptimized,
|
size_when_optimized_for_size < size_when_unoptimized,
|
||||||
"Expected the size-optimized bytecode to be smaller than the unoptimized. Optimized: {}B, Unoptimized: {}B", size_when_optimized_for_size, size_when_unoptimized,
|
"Expected the size-optimized bytecode to be smaller than the unoptimized. Optimized: {size_when_optimized_for_size}B, Unoptimized: {size_when_unoptimized}B",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-runtime-api"
|
name = "revive-runtime-api"
|
||||||
version.workspace = true
|
version = "0.2.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -37,12 +37,11 @@ fn compile(source_path: &str, bitcode_path: &str) {
|
|||||||
source_path,
|
source_path,
|
||||||
])
|
])
|
||||||
.output()
|
.output()
|
||||||
.unwrap_or_else(|error| panic!("failed to execute clang: {}", error));
|
.unwrap_or_else(|error| panic!("failed to execute clang: {error}"));
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"failed to compile the PolkaVM C API: {:?}",
|
"failed to compile the PolkaVM C API: {output:?}"
|
||||||
output
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ void * memmove(void *dst, const void *src, size_t n) {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void * memset(void *b, int c, size_t len) {
|
||||||
|
uint8_t *dest = b;
|
||||||
|
uint8_t val = (uint8_t)c;
|
||||||
|
while (len-- > 0) *dest++ = val;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
// Imports
|
// Imports
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, address, uint32_t)
|
POLKAVM_IMPORT(void, address, uint32_t)
|
||||||
@@ -97,3 +104,19 @@ POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, ui
|
|||||||
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
|
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, div, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, sdiv, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, addmod, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, mulmod, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, mod, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, smod, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, exp, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, signext, uint32_t, uint32_t, uint32_t);
|
||||||
|
|||||||
@@ -68,9 +68,27 @@ pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
|||||||
|
|
||||||
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
|
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
|
||||||
|
|
||||||
|
pub static DIV: &str = "div";
|
||||||
|
pub static SDIV: &str = "sdiv";
|
||||||
|
pub static ADDMOD: &str = "addmod";
|
||||||
|
pub static MULMOD: &str = "mulmod";
|
||||||
|
pub static MOD: &str = "mod";
|
||||||
|
pub static SMOD: &str = "smod";
|
||||||
|
pub static EXP: &str = "exp";
|
||||||
|
pub static SIGNEXT: &str = "signext";
|
||||||
|
|
||||||
/// All imported runtime API symbols.
|
/// All imported runtime API symbols.
|
||||||
/// Useful for configuring common attributes and linkage.
|
/// Useful for configuring common attributes and linkage.
|
||||||
pub static IMPORTS: [&str; 33] = [
|
pub static IMPORTS: [&str; 41] = [
|
||||||
|
DIV,
|
||||||
|
SDIV,
|
||||||
|
ADDMOD,
|
||||||
|
MULMOD,
|
||||||
|
MOD,
|
||||||
|
SMOD,
|
||||||
|
EXP,
|
||||||
|
SIGNEXT,
|
||||||
|
//
|
||||||
ADDRESS,
|
ADDRESS,
|
||||||
BALANCE,
|
BALANCE,
|
||||||
BALANCE_OF,
|
BALANCE_OF,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-stdlib"
|
name = "revive-stdlib"
|
||||||
version.workspace = true
|
version = "0.1.1"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ fn main() {
|
|||||||
"stdlib.ll",
|
"stdlib.ll",
|
||||||
])
|
])
|
||||||
.output()
|
.output()
|
||||||
.unwrap_or_else(|error| panic!("failed to execute llvm-as: {}", error));
|
.unwrap_or_else(|error| panic!("failed to execute llvm-as: {error}"));
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
"failed to assemble the stdlib: {:?}",
|
"failed to assemble the stdlib: {output:?}"
|
||||||
output
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let bitcode = fs::read(bitcode_path).expect("bitcode should have been built");
|
let bitcode = fs::read(bitcode_path).expect("bitcode should have been built");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revive-yul"
|
name = "revive-yul"
|
||||||
description = "The revive YUL parser library."
|
description = "The revive YUL parser library."
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ impl Literal {
|
|||||||
unicode_char.encode_utf8(&mut unicode_bytes);
|
unicode_char.encode_utf8(&mut unicode_bytes);
|
||||||
|
|
||||||
for byte in unicode_bytes.into_iter() {
|
for byte in unicode_bytes.into_iter() {
|
||||||
hex_string.push_str(format!("{:02x}", byte).as_str());
|
hex_string.push_str(format!("{byte:02x}").as_str());
|
||||||
}
|
}
|
||||||
index += 5;
|
index += 5;
|
||||||
} else if string[index..].starts_with('t') {
|
} else if string[index..].starts_with('t') {
|
||||||
|
|||||||
@@ -204,10 +204,10 @@ where
|
|||||||
revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?;
|
||||||
|
|
||||||
revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
|
//revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
|
//revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMRemainderFunction.declare(context)?;
|
//revive_llvm_context::PolkaVMRemainderFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedRemainderFunction.declare(context)?;
|
//revive_llvm_context::PolkaVMSignedRemainderFunction.declare(context)?;
|
||||||
|
|
||||||
revive_llvm_context::PolkaVMSbrkFunction.declare(context)?;
|
revive_llvm_context::PolkaVMSbrkFunction.declare(context)?;
|
||||||
|
|
||||||
@@ -258,10 +258,10 @@ where
|
|||||||
revive_llvm_context::PolkaVMEventLogFunction::<3>.into_llvm(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<3>.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMEventLogFunction::<4>.into_llvm(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<4>.into_llvm(context)?;
|
||||||
|
|
||||||
revive_llvm_context::PolkaVMDivisionFunction.into_llvm(context)?;
|
//revive_llvm_context::PolkaVMDivisionFunction.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
|
//revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
|
//revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedRemainderFunction.into_llvm(context)?;
|
//revive_llvm_context::PolkaVMSignedRemainderFunction.into_llvm(context)?;
|
||||||
|
|
||||||
revive_llvm_context::PolkaVMSbrkFunction.into_llvm(context)?;
|
revive_llvm_context::PolkaVMSbrkFunction.into_llvm(context)?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@parity/resolc",
|
"name": "@parity/resolc",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Parity <admin@parity.io> (https://parity.io)",
|
"author": "Parity <admin@parity.io> (https://parity.io)",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@openzeppelin/contracts": "5.1.0",
|
"@openzeppelin/contracts": "5.1.0",
|
||||||
|
"@redstone-finance/evm-connector": "^0.8.0",
|
||||||
"globals": "^15.12.0",
|
"globals": "^15.12.0",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.6.3"
|
||||||
},
|
},
|
||||||
|
|||||||
+53
-8
@@ -6,6 +6,7 @@ import * as os from 'os'
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as resolc from '.'
|
import * as resolc from '.'
|
||||||
import { SolcInput } from '.'
|
import { SolcInput } from '.'
|
||||||
|
import { execSync } from 'child_process'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// hold on to any exception handlers that existed prior to this script running, we'll be adding them back at the end
|
// hold on to any exception handlers that existed prior to this script running, we'll be adding them back at the end
|
||||||
@@ -17,11 +18,15 @@ async function main() {
|
|||||||
|
|
||||||
const program = new commander.Command()
|
const program = new commander.Command()
|
||||||
|
|
||||||
program.name('solcjs')
|
program.name('resolcjs')
|
||||||
program.version(resolc.version())
|
program.version(resolc.version())
|
||||||
program
|
program
|
||||||
.option('--bin', 'Binary of the contracts in hex.')
|
.option('--bin', 'Binary of the contracts in hex.')
|
||||||
.option('--abi', 'ABI of the contracts.')
|
.option('--abi', 'ABI of the contracts.')
|
||||||
|
.option(
|
||||||
|
'--diff-stats',
|
||||||
|
'Print statistics about Resolc vs Solc compilation.'
|
||||||
|
)
|
||||||
.option(
|
.option(
|
||||||
'--base-path <path>',
|
'--base-path <path>',
|
||||||
'Root of the project source tree. ' +
|
'Root of the project source tree. ' +
|
||||||
@@ -49,8 +54,20 @@ async function main() {
|
|||||||
outputDir?: string
|
outputDir?: string
|
||||||
prettyJson: boolean
|
prettyJson: boolean
|
||||||
basePath?: string
|
basePath?: string
|
||||||
|
diffStats: boolean
|
||||||
includePath?: string[]
|
includePath?: string[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
// when using --stats option, we want to run solc as well to compare outputs size
|
||||||
|
if (options.diffStats) {
|
||||||
|
const args = process.argv.filter((arg) => !arg.startsWith('--diff-stats'))
|
||||||
|
try {
|
||||||
|
execSync(`npx --yes solc@latest ${args.slice(2).join(' ')}`)
|
||||||
|
} catch (err) {
|
||||||
|
abort(`Failed to run solc: ${err}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const files: string[] = program.args
|
const files: string[] = program.args
|
||||||
const destination = options.outputDir ?? '.'
|
const destination = options.outputDir ?? '.'
|
||||||
|
|
||||||
@@ -137,7 +154,7 @@ async function main() {
|
|||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
abort('No output from compiler')
|
abort('No output from compiler')
|
||||||
} else if (output.errors) {
|
} else if (output.errors && !options.diffStats) {
|
||||||
for (const error in output.errors) {
|
for (const error in output.errors) {
|
||||||
const message = output.errors[error]
|
const message = output.errors[error]
|
||||||
if (message.severity === 'warning') {
|
if (message.severity === 'warning') {
|
||||||
@@ -160,19 +177,41 @@ async function main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contractStats = []
|
||||||
|
|
||||||
for (const fileName in output.contracts) {
|
for (const fileName in output.contracts) {
|
||||||
for (const contractName in output.contracts[fileName]) {
|
for (const contractName in output.contracts[fileName]) {
|
||||||
let contractFileName = fileName + ':' + contractName
|
let contractFileName = fileName + ':' + contractName
|
||||||
contractFileName = contractFileName.replace(/[:./\\]/g, '_')
|
contractFileName = contractFileName.replace(/[:./\\]/g, '_')
|
||||||
|
let polkavmSize = 0
|
||||||
if (options.bin) {
|
let binSize = 0
|
||||||
writeFile(
|
if (
|
||||||
contractFileName + '.polkavm',
|
options.bin &&
|
||||||
Buffer.from(
|
output.contracts?.[fileName]?.[contractName]?.evm?.bytecode?.object
|
||||||
|
) {
|
||||||
|
const pvmData = Buffer.from(
|
||||||
output.contracts[fileName][contractName].evm.bytecode.object,
|
output.contracts[fileName][contractName].evm.bytecode.object,
|
||||||
'hex'
|
'hex'
|
||||||
)
|
)
|
||||||
)
|
writeFile(contractFileName + '.polkavm', pvmData)
|
||||||
|
polkavmSize = pvmData.length
|
||||||
|
|
||||||
|
const binOutPath = path.join(destination, `${contractFileName}.bin`)
|
||||||
|
if (fs.existsSync(binOutPath)) {
|
||||||
|
try {
|
||||||
|
binSize = fs.statSync(binOutPath).size || 0
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
contractStats.push({
|
||||||
|
file: fileName,
|
||||||
|
contract: contractName,
|
||||||
|
['resolc (kB)']: Number((polkavmSize / 1024).toFixed(2)),
|
||||||
|
['solc (kB)']: Number((binSize / 1024).toFixed(2)),
|
||||||
|
['diff (%)']:
|
||||||
|
binSize > 0
|
||||||
|
? Number(((polkavmSize / binSize - 1) * 100).toFixed(2))
|
||||||
|
: Number.NaN,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.abi) {
|
if (options.abi) {
|
||||||
@@ -184,6 +223,12 @@ async function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.diffStats && contractStats.length > 0) {
|
||||||
|
console.table(
|
||||||
|
contractStats.sort((a, b) => b['resolc (kB)'] - a['resolc (kB)'])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Put back original exception handlers.
|
// Put back original exception handlers.
|
||||||
originalUncaughtExceptionListeners.forEach(function (listener) {
|
originalUncaughtExceptionListeners.forEach(function (listener) {
|
||||||
process.addListener('uncaughtException', listener)
|
process.addListener('uncaughtException', listener)
|
||||||
|
|||||||
@@ -68,6 +68,16 @@ test('resolve import', () => {
|
|||||||
file: './fixtures/storage.sol',
|
file: './fixtures/storage.sol',
|
||||||
expected: resolve('fixtures/storage.sol'),
|
expected: resolve('fixtures/storage.sol'),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// package with exports
|
||||||
|
{
|
||||||
|
file: '@redstone-finance/evm-connector/contracts/data-services/PrimaryProdDataServiceConsumerBase.sol',
|
||||||
|
expected: resolve(
|
||||||
|
__dirname,
|
||||||
|
'../../..',
|
||||||
|
'node_modules/@redstone-finance/evm-connector/contracts/data-services/PrimaryProdDataServiceConsumerBase.sol'
|
||||||
|
),
|
||||||
|
},
|
||||||
// scopped module with version
|
// scopped module with version
|
||||||
{
|
{
|
||||||
file: '@openzeppelin/contracts@5.1.0/token/ERC20/ERC20.sol',
|
file: '@openzeppelin/contracts@5.1.0/token/ERC20/ERC20.sol',
|
||||||
@@ -100,16 +110,19 @@ test('resolve import', () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
for (const { file, expected } of cases) {
|
for (const { file, expected } of cases) {
|
||||||
|
let resolved
|
||||||
try {
|
try {
|
||||||
const resolved = tryResolveImport(file)
|
resolved = tryResolveImport(file)
|
||||||
assert(
|
|
||||||
resolved === expected,
|
|
||||||
`\nGot:\n${resolved}\nExpected:\n${expected}`
|
|
||||||
)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
assert(
|
assert(
|
||||||
String(error) == expected,
|
String(error) == expected,
|
||||||
`\nGot:\n${String(error)}\nExpected:\n${expected}`
|
`\nExpected:\n${expected}\nGot:\n${String(error)}\n`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (resolved) {
|
||||||
|
assert(
|
||||||
|
resolved === expected,
|
||||||
|
`\nExpected:\n${expected}\nGot:\n${resolved}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-7
@@ -50,11 +50,7 @@ export function resolveInputs(sources: SolcInput): SolcInput {
|
|||||||
language: 'Solidity',
|
language: 'Solidity',
|
||||||
sources,
|
sources,
|
||||||
settings: {
|
settings: {
|
||||||
outputSelection: {
|
outputSelection: {}, // no outputs requested, only resolves imports
|
||||||
'*': {
|
|
||||||
'*': ['evm.bytecode.object'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +102,7 @@ export async function compile(
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
runs: 200,
|
runs: 200,
|
||||||
},
|
},
|
||||||
bin,
|
bin = process.env.RESOLC_BIN,
|
||||||
} = option
|
} = option
|
||||||
|
|
||||||
const input = JSON.stringify({
|
const input = JSON.stringify({
|
||||||
@@ -129,6 +125,26 @@ export async function compile(
|
|||||||
return resolc(input)
|
return resolc(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve the package root
|
||||||
|
* use resolve-pkg to find the package root, and fallback to using require.resolve if the package defines an exports field
|
||||||
|
* see https://github.com/sindresorhus/resolve-pkg/issues/9
|
||||||
|
**/
|
||||||
|
function resolvePkgRoot(basePackage: string) {
|
||||||
|
const packageRoot = resolvePkg(basePackage)
|
||||||
|
if (packageRoot) {
|
||||||
|
return packageRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const packageExport = require.resolve(basePackage)
|
||||||
|
const endIndex = packageExport.indexOf(basePackage) + basePackage.length
|
||||||
|
return packageExport.substring(0, endIndex)
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve an import path to a file path.
|
* Resolve an import path to a file path.
|
||||||
* @param importPath - The import path to resolve.
|
* @param importPath - The import path to resolve.
|
||||||
@@ -150,7 +166,7 @@ export function tryResolveImport(importPath: string) {
|
|||||||
const specifiedVersion = match[2] // "1.2.3" (optional)
|
const specifiedVersion = match[2] // "1.2.3" (optional)
|
||||||
const relativePath = match[3] // "/path/to/file.sol"
|
const relativePath = match[3] // "/path/to/file.sol"
|
||||||
|
|
||||||
const packageRoot = resolvePkg(basePackage)
|
const packageRoot = resolvePkgRoot(basePackage)
|
||||||
if (!packageRoot) {
|
if (!packageRoot) {
|
||||||
throw new Error(`Package ${basePackage} not found.`)
|
throw new Error(`Package ${basePackage} not found.`)
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1349
-1
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user