Compare commits

...

16 Commits

Author SHA1 Message Date
DavidK 3184397c43 cargo fmt 2025-01-06 16:29:59 +02:00
DavidK 9c44eeac06 Adds import callback resolution to resolc compiler 2025-01-06 16:09:53 +02:00
Cyrill Leutwiler f49d145e9a update the minium supported rust version to 1.81 (#144)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-21 09:10:14 +01:00
Cyrill Leutwiler 952c5cc894 resolc-0.1.0-dev.7 (#143)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-20 14:33:08 +01:00
Cyrill Leutwiler d8752ec6b5 the basefee opcode (#142)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-19 18:59:10 +01:00
Cyrill Leutwiler 6ad846a285 the base fee opcode (#141)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-19 12:44:15 +01:00
Cyrill Leutwiler 3f9771f838 update and fix the linker (#140) 2024-12-18 23:11:06 +01:00
Cyrill Leutwiler 22070a824d the gas limit opcode (#139)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-18 20:31:42 +01:00
Cyrill Leutwiler d299dd1a19 change getters to register version (#138) 2024-12-18 17:56:37 +01:00
Cyrill Leutwiler 14a598e840 implement the gas opcode (#136) 2024-12-18 17:19:32 +01:00
Cyrill Leutwiler 55ec0988e8 fix the CI runner version (#137)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-18 17:03:29 +01:00
Cyrill Leutwiler 909de515c4 Allow arbitrary call data size (#135)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-18 14:04:46 +01:00
Sebastian Miasojed afe44ad21b JS: Fix encoding conversion from utf16 to utf8 (#131) 2024-12-11 09:23:02 +01:00
Cyrill Leutwiler 2cb8f82266 calls: supply max ref_time and proof_size limits (#133)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-10 16:31:44 +01:00
Cyrill Leutwiler 6f2f158ef1 fix new clippy lint (#132)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2024-12-10 15:24:25 +01:00
Cyrill Leutwiler 4e5482bad2 fix the commit sha in the version (#129)
Signed-off-by: xermicus <cyrill@parity.io>
2024-12-03 12:34:17 +01:00
42 changed files with 1377 additions and 1858 deletions
+2 -2
View File
@@ -9,12 +9,12 @@ env:
DEBIAN_CONTAINER_RUNNER: run-debian-builder.sh DEBIAN_CONTAINER_RUNNER: run-debian-builder.sh
REVIVE_DEBIAN_INSTALL: ${{ github.workspace }}/target/release REVIVE_DEBIAN_INSTALL: ${{ github.workspace }}/target/release
REVIVE_DEBIAN_BINARY: resolc REVIVE_DEBIAN_BINARY: resolc
RUST_VERSION: "1.80" RUST_VERSION: "1.81"
jobs: jobs:
build-revive-debian-x86: build-revive-debian-x86:
name: debian-container-x86 name: debian-container-x86
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
+1 -1
View File
@@ -13,7 +13,7 @@ env:
jobs: jobs:
build-revive-wasm: build-revive-wasm:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
defaults: defaults:
run: run:
shell: bash shell: bash
+1 -1
View File
@@ -11,7 +11,7 @@ env:
jobs: jobs:
build-ubuntu-x86: build-ubuntu-x86:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
+1
View File
@@ -15,3 +15,4 @@ tmp
package-lock.json package-lock.json
/*.html /*.html
/build /build
soljson.js
+20
View File
@@ -2,6 +2,26 @@
## Unreleased ## Unreleased
## v0.1.0-dev.7
This is a development pre-release.
### Added
- Implement the `GASPRICE` opcode.
- Implement the `BASEFEE` opcode.
- Implement the `GASLIMIT` opcode.
### Changed
- The `GAS` opcode now returns the remaining `ref_time`.
- Contracts can now be supplied call data input of arbitrary size.
- Some syscalls now return the value in a register, slightly improving emitted contract code.
- Calls forward maximum weight limits instead of 0, anticipating a change in polkadot-sdk where weight limits of 0 no longer interprets as uncapped limit.
### Fixed
- A linker bug which was preventing certain contracts from linking with the PVM linker.
- JS: Fix encoding conversion from JS string (UTF-16) to UTF-8.
- The git commit hash slug is always displayed in the version string.
## v0.1.0-dev.6 ## v0.1.0-dev.6
This is a development pre-release. This is a development pre-release.
Generated
+990 -1590
View File
File diff suppressed because it is too large Load Diff
+20 -19
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/*"] members = ["crates/*"]
[workspace.package] [workspace.package]
version = "0.1.0-dev.6" version = "0.1.0-dev.7"
authors = [ authors = [
"Cyrill Leutwiler <cyrill@parity.io>", "Cyrill Leutwiler <cyrill@parity.io>",
"Parity Technologies <admin@parity.io>", "Parity Technologies <admin@parity.io>",
@@ -11,21 +11,21 @@ authors = [
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
edition = "2021" edition = "2021"
repository = "https://github.com/paritytech/revive" repository = "https://github.com/paritytech/revive"
rust-version = "1.80.0" rust-version = "1.81.0"
[workspace.dependencies] [workspace.dependencies]
revive-benchmarks = { version = "0.1.0-dev.6", path = "crates/benchmarks" } revive-benchmarks = { version = "0.1.0-dev.7", path = "crates/benchmarks" }
revive-builtins = { version = "0.1.0-dev.6", path = "crates/builtins" } revive-builtins = { version = "0.1.0-dev.7", path = "crates/builtins" }
revive-common = { version = "0.1.0-dev.6", path = "crates/common" } revive-common = { version = "0.1.0-dev.7", path = "crates/common" }
revive-differential = { version = "0.1.0-dev.6", path = "crates/differential" } revive-differential = { version = "0.1.0-dev.7", path = "crates/differential" }
revive-integration = { version = "0.1.0-dev.6", path = "crates/integration" } revive-integration = { version = "0.1.0-dev.7", path = "crates/integration" }
revive-linker = { version = "0.1.0-dev.6", path = "crates/linker" } revive-linker = { version = "0.1.0-dev.7", path = "crates/linker" }
lld-sys = { version = "0.1.0-dev.6", path = "crates/lld-sys" } lld-sys = { version = "0.1.0-dev.7", path = "crates/lld-sys" }
revive-llvm-context = { version = "0.1.0-dev.6", path = "crates/llvm-context" } revive-llvm-context = { version = "0.1.0-dev.7", path = "crates/llvm-context" }
revive-runtime-api = { version = "0.1.0-dev.6", path = "crates/runtime-api" } revive-runtime-api = { version = "0.1.0-dev.7", path = "crates/runtime-api" }
revive-runner = { version = "0.1.0-dev.6", path = "crates/runner" } revive-runner = { version = "0.1.0-dev.7", path = "crates/runner" }
revive-solidity = { version = "0.1.0-dev.6", path = "crates/solidity" } revive-solidity = { version = "0.1.0-dev.7", path = "crates/solidity" }
revive-stdlib = { version = "0.1.0-dev.6", path = "crates/stdlib" } revive-stdlib = { version = "0.1.0-dev.7", path = "crates/stdlib" }
hex = "0.4" hex = "0.4"
petgraph = "0.6" petgraph = "0.6"
@@ -51,10 +51,10 @@ path-slash = "0.2"
rayon = "1.8" rayon = "1.8"
clap = { version = "4", default-features = false, features = ["derive"] } clap = { version = "4", default-features = false, features = ["derive"] }
rand = "0.8" rand = "0.8"
polkavm-common = "0.17" polkavm-common = "0.18"
polkavm-linker = "0.17" polkavm-linker = "0.18"
polkavm-disassembler = "0.17" polkavm-disassembler = "0.18"
polkavm = "0.17" polkavm = "0.18"
alloy-primitives = { version = "0.8", features = ["serde"] } alloy-primitives = { version = "0.8", features = ["serde"] }
alloy-sol-types = "0.8" alloy-sol-types = "0.8"
alloy-genesis = "0.3" alloy-genesis = "0.3"
@@ -63,11 +63,12 @@ env_logger = { version = "0.10.0", default-features = false }
serde_stacker = "0.1" serde_stacker = "0.1"
criterion = { version = "0.5", features = ["html_reports"] } criterion = { version = "0.5", features = ["html_reports"] }
log = { version = "0.4" } log = { version = "0.4" }
git2 = "0.19.0"
# polkadot-sdk and friends # polkadot-sdk and friends
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" } codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.1", default-features = false } scale-info = { version = "2.11.1", default-features = false }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "447902eff4a574e66894ad60cb41999b05bf5e84" } polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "243b751abbb94369bbd92c83d8ab159ddfc3c556" }
# llvm # llvm
[workspace.dependencies.inkwell] [workspace.dependencies.inkwell]
+15 -12
View File
@@ -1,18 +1,21 @@
.PHONY: install format test test-solidity test-cli test-integration test-workspace clean docs docs-build .PHONY: install format test test-solidity test-cli test-integration test-workspace clean docs docs-build
RUSTFLAGS_EMSCRIPTEN := \ RUSTFLAGS_EMSCRIPTEN := \
-Clink-arg=-sEXPORTED_FUNCTIONS=_main,_free,_malloc \ -C link-arg=-sEXPORTED_FUNCTIONS=_main,_free,_malloc \
-Clink-arg=-sNO_INVOKE_RUN \ -C link-arg=-sNO_INVOKE_RUN=1 \
-Clink-arg=-sEXIT_RUNTIME \ -C link-arg=-sEXIT_RUNTIME=1 \
-Clink-arg=-sINITIAL_MEMORY=64MB \ -C link-arg=-sALLOW_MEMORY_GROWTH=1 \
-Clink-arg=-sTOTAL_MEMORY=3GB \ -C link-arg=-sEXPORTED_RUNTIME_METHODS=FS,callMain,stringToNewUTF8 \
-Clink-arg=-sALLOW_MEMORY_GROWTH \ -C link-arg=-sMODULARIZE=1 \
-Clink-arg=-sEXPORTED_RUNTIME_METHODS=FS,callMain,stringToNewUTF8,cwrap \ -C link-arg=-sEXPORT_NAME=createRevive \
-Clink-arg=-sMODULARIZE \ -C link-arg=-sWASM_ASYNC_COMPILATION=0 \
-Clink-arg=-sEXPORT_NAME=createRevive \ -C link-arg=-sDYNAMIC_EXECUTION=0 \
-Clink-arg=-sWASM_ASYNC_COMPILATION=0 \ -C link-arg=-sALLOW_TABLE_GROWTH=1 \
-Clink-arg=--js-library=js/embed/soljson_interface.js \ -C link-arg=--js-library=js/embed/soljson_interface.js \
-Clink-arg=--pre-js=js/embed/pre.js -C link-arg=--pre-js=js/embed/pre.js \
-C link-arg=-sNODEJS_CATCH_EXIT=0 \
-C link-arg=-sDISABLE_EXCEPTION_CATCHING=0 \
-C opt-level=3
install: install-bin install-npm install: install-bin install-npm
+8 -5
View File
@@ -17,6 +17,14 @@ Discussion around the development is hosted on the [Polkadot Forum](https://foru
`resolc` depends on the [solc](https://github.com/ethereum/solidity) binary installed on your system. `resolc` depends on the [solc](https://github.com/ethereum/solidity) binary installed on your system.
Building from source requires a compatible LLVM build.
### LLVM
`revive` requires a build of LLVM 18.1.4 or later with the RISC-V _embedded_ target, including `compiler-rt`. Use the provided [build-llvm.sh](build-llvm.sh) build script to compile a compatible LLVM build locally in `$PWD/llvm18.0` (don't forget to add that to `$PATH` afterwards).
### The `resolc` Solidity frontend
To install the `resolc` Solidity frontend executable: To install the `resolc` Solidity frontend executable:
```bash ```bash
@@ -25,11 +33,6 @@ export PATH=${PWD}/llvm18.0/bin:$PATH
make install-bin make install-bin
resolc --version resolc --version
``` ```
### LLVM
`revive` requires a build of LLVM 18.1.4 or later including `compiler-rt`. Use the provided [build-llvm.sh](build-llvm.sh) build script to compile a compatible LLVM build locally in `$PWD/llvm18.0` (don't forget to add that to `$PATH` afterwards).
### Cross-compilation to WASM ### Cross-compilation to WASM
Cross-compiles the Revive compiler to WASM for running it in a Node.js or browser environment. Cross-compiles the Revive compiler to WASM for running it in a Node.js or browser environment.
+2 -1
View File
@@ -8,4 +8,5 @@ To create a new pre-release:
2. Push a release tag to `main` 2. Push a release tag to `main`
3. Manually trigger the `Build revive-debian` action 3. Manually trigger the `Build revive-debian` action
4. Create a __pre-release__ from the tag and manually upload the build artifact generated by the action 4. Create a __pre-release__ from the tag and manually upload the build artifact generated by the action
5. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly 5. Manually upload `resolc.js` and `resolc.wasm` from the `build-revive-wasm` action artifacts.
6. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
+1 -1
View File
@@ -46,7 +46,7 @@ fn group<'error, M>(c: &'error mut Criterion<M>, group_name: &str) -> BenchmarkG
where where
M: Measurement, M: Measurement,
{ {
return c.benchmark_group(group_name); c.benchmark_group(group_name)
} }
fn bench_baseline(c: &mut Criterion) { fn bench_baseline(c: &mut Criterion) {
+8 -8
View File
@@ -1,10 +1,10 @@
{ {
"Baseline": 1073, "Baseline": 1110,
"Computation": 2469, "Computation": 2389,
"DivisionArithmetics": 15041, "DivisionArithmetics": 14822,
"ERC20": 23282, "ERC20": 23973,
"Events": 1615, "Events": 1605,
"FibonacciIterative": 1676, "FibonacciIterative": 2023,
"Flipper": 2378, "Flipper": 1989,
"SHA1": 17076 "SHA1": 17026
} }
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "BaseFee"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract BaseFee {
constructor() payable {
assert(block.basefee == 0);
}
}
+32
View File
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "GasLeft"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract GasLeft {
constructor() payable {
assert(gasleft() > gasleft());
assert(gasleft() > 0 && gasleft() < 0xffffffffffffffff);
}
}
+31
View File
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "GasLimit"
}
}
}
},
{
"VerifyCall": {
"success": true
}
}
]
}
*/
contract GasLimit {
constructor() payable {
assert(block.gaslimit == 2000000000000);
}
}
+3
View File
@@ -47,6 +47,9 @@ test_spec!(transaction, "Transaction", "Transaction.sol");
test_spec!(block_hash, "BlockHash", "BlockHash.sol"); test_spec!(block_hash, "BlockHash", "BlockHash.sol");
test_spec!(delegate, "Delegate", "Delegate.sol"); test_spec!(delegate, "Delegate", "Delegate.sol");
test_spec!(gas_price, "GasPrice", "GasPrice.sol"); test_spec!(gas_price, "GasPrice", "GasPrice.sol");
test_spec!(gas_left, "GasLeft", "GasLeft.sol");
test_spec!(gas_limit, "GasLimit", "GasLimit.sol");
test_spec!(base_fee, "BaseFee", "BaseFee.sol");
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> { fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
vec![Instantiate { vec![Instantiate {
+1
View File
@@ -57,6 +57,7 @@ pub fn link<T: AsRef<[u8]>>(input: T) -> anyhow::Result<Vec<u8>> {
"--relocatable", "--relocatable",
"--emit-relocs", "--emit-relocs",
"--no-relax", "--no-relax",
"--unique",
"--gc-sections", "--gc-sections",
"--library-path", "--library-path",
dir.path().to_str().expect("should be utf8"), dir.path().to_str().expect("should be utf8"),
@@ -9,9 +9,6 @@ pub static XLEN: usize = revive_common::BIT_LENGTH_X32;
/// The heap memory pointer pointer global variable name. /// The heap memory pointer pointer global variable name.
pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer"; pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer";
/// The calldata pointer global variable name.
pub static GLOBAL_CALLDATA_POINTER: &str = "ptr_calldata";
/// The calldata size global variable name. /// The calldata size global variable name.
pub static GLOBAL_CALLDATA_SIZE: &str = "calldatasize"; pub static GLOBAL_CALLDATA_SIZE: &str = "calldatasize";
@@ -13,7 +13,7 @@ pub struct EVMLAData<'ctx> {
pub stack: Vec<Argument<'ctx>>, pub stack: Vec<Argument<'ctx>>,
} }
impl<'ctx> EVMLAData<'ctx> { impl EVMLAData<'_> {
/// The default stack size. /// The default stack size.
pub const DEFAULT_STACK_SIZE: usize = 64; pub const DEFAULT_STACK_SIZE: usize = 64;
@@ -18,23 +18,12 @@ impl Entry {
/// The call flags argument index. /// The call flags argument index.
pub const ARGUMENT_INDEX_CALL_FLAGS: usize = 0; pub const ARGUMENT_INDEX_CALL_FLAGS: usize = 0;
/// Reserve 1kb for calldata.
pub const MAX_CALLDATA_SIZE: usize = 1024;
/// Initializes the global variables. /// Initializes the global variables.
/// The pointers are not initialized, because it's not possible to create a null pointer. /// The pointers are not initialized, because it's not possible to create a null pointer.
pub fn initialize_globals<D>(context: &mut Context<D>) -> anyhow::Result<()> pub fn initialize_globals<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let calldata_type = context.array_type(context.byte_type(), Self::MAX_CALLDATA_SIZE);
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_POINTER,
calldata_type,
AddressSpace::Stack,
calldata_type.get_undef(),
);
context.set_global( context.set_global(
crate::polkavm::GLOBAL_HEAP_MEMORY_POINTER, crate::polkavm::GLOBAL_HEAP_MEMORY_POINTER,
context.llvm().ptr_type(AddressSpace::Heap.into()), context.llvm().ptr_type(AddressSpace::Heap.into()),
@@ -53,9 +42,9 @@ impl Entry {
context.set_global( context.set_global(
crate::polkavm::GLOBAL_CALLDATA_SIZE, crate::polkavm::GLOBAL_CALLDATA_SIZE,
context.word_type(), context.xlen_type(),
AddressSpace::Stack, AddressSpace::Stack,
context.word_undef(), context.xlen_type().get_undef(),
); );
context.set_global( context.set_global(
@@ -68,53 +57,22 @@ impl Entry {
Ok(()) Ok(())
} }
/// Load the calldata via seal `input` and initialize the calldata end /// Populate the calldata size global value.
/// and calldata size globals. pub fn load_calldata_size<D>(context: &mut Context<D>) -> anyhow::Result<()>
pub fn load_calldata<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let input_pointer = context let call_data_size_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? .get_global(crate::polkavm::GLOBAL_CALLDATA_SIZE)?
.value .value
.as_pointer_value(); .as_pointer_value();
let input_pointer_casted = context.builder.build_ptr_to_int( let call_data_size_value = context
input_pointer, .build_runtime_call(revive_runtime_api::polkavm_imports::CALL_DATA_SIZE, &[])
context.xlen_type(), .expect("the call_data_size syscall method should return a value")
"input_pointer_casted",
)?;
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "len_ptr");
let length_pointer_casted = context.builder.build_ptr_to_int(
length_pointer.value,
context.xlen_type(),
"length_pointer_casted",
)?;
context.build_store(
length_pointer,
context.integer_const(crate::polkavm::XLEN, Self::MAX_CALLDATA_SIZE as u64),
)?;
context.build_runtime_call(
revive_runtime_api::polkavm_imports::INPUT,
&[input_pointer_casted.into(), length_pointer_casted.into()],
);
// Store the calldata size
let calldata_size = context
.build_load(length_pointer, "input_size")?
.into_int_value(); .into_int_value();
let calldata_size_casted = context.builder().build_int_z_extend( context
calldata_size, .builder()
context.word_type(), .build_store(call_data_size_pointer, call_data_size_value)?;
"zext_input_len",
)?;
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_SIZE,
context.word_type(),
AddressSpace::Stack,
calldata_size_casted,
);
Ok(()) Ok(())
} }
@@ -220,7 +178,7 @@ where
context.set_basic_block(context.current_function().borrow().entry_block()); context.set_basic_block(context.current_function().borrow().entry_block());
Self::initialize_globals(context)?; Self::initialize_globals(context)?;
Self::load_calldata(context)?; Self::load_calldata_size(context)?;
Self::leave_entry(context)?; Self::leave_entry(context)?;
context.build_unconditional_branch(context.current_function().borrow().return_block()); context.build_unconditional_branch(context.current_function().borrow().return_block());
@@ -27,7 +27,7 @@ where
runtime::FUNCTION_LOAD_IMMUTABLE_DATA, runtime::FUNCTION_LOAD_IMMUTABLE_DATA,
context.void_type().fn_type(Default::default(), false), context.void_type().fn_type(Default::default(), false),
0, 0,
Some(inkwell::module::Linkage::Private), Some(inkwell::module::Linkage::External),
)?; )?;
Ok(()) Ok(())
@@ -37,7 +37,7 @@ impl<'ctx> Global<'ctx> {
.add_global(r#type, Some(address_space.into()), name); .add_global(r#type, Some(address_space.into()), name);
let global = Self { r#type, value }; let global = Self { r#type, value };
global.value.set_linkage(inkwell::module::Linkage::Private); global.value.set_linkage(inkwell::module::Linkage::External);
global global
.value .value
.set_visibility(inkwell::GlobalVisibility::Default); .set_visibility(inkwell::GlobalVisibility::Default);
+4 -4
View File
@@ -60,8 +60,8 @@ where
let arguments = &[ let arguments = &[
flags.as_basic_value_enum(), flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(), address_pointer.value.as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(), context.integer_const(64, u64::MAX).as_basic_value_enum(),
context.integer_const(64, 0).as_basic_value_enum(), context.integer_const(64, u64::MAX).as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(), context.sentinel_pointer().value.as_basic_value_enum(),
value_pointer.value.as_basic_value_enum(), value_pointer.value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(), input_pointer.value.as_basic_value_enum(),
@@ -140,10 +140,10 @@ where
flags.as_basic_value_enum(), flags.as_basic_value_enum(),
address_pointer.value.as_basic_value_enum(), address_pointer.value.as_basic_value_enum(),
context context
.integer_const(revive_common::BIT_LENGTH_X64, 0) .integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(), .as_basic_value_enum(),
context context
.integer_const(revive_common::BIT_LENGTH_X64, 0) .integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
.as_basic_value_enum(), .as_basic_value_enum(),
context.sentinel_pointer().value.as_basic_value_enum(), context.sentinel_pointer().value.as_basic_value_enum(),
input_pointer.value.as_basic_value_enum(), input_pointer.value.as_basic_value_enum(),
+27 -29
View File
@@ -1,10 +1,7 @@
//! Translates the calldata instructions. //! Translates the calldata instructions.
use crate::polkavm::context::address_space::AddressSpace;
use crate::polkavm::context::pointer::Pointer;
use crate::polkavm::context::Context; use crate::polkavm::context::Context;
use crate::polkavm::Dependency; use crate::polkavm::Dependency;
use inkwell::types::BasicType;
/// Translates the calldata load. /// Translates the calldata load.
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
@@ -14,19 +11,15 @@ pub fn load<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let calldata_pointer = context let output_pointer = context.build_alloca_at_entry(context.word_type(), "call_data_output");
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? let offset = context.safe_truncate_int_to_xlen(offset)?;
.value
.as_pointer_value(); context.build_runtime_call(
let offset = context.build_gep( revive_runtime_api::polkavm_imports::CALL_DATA_LOAD,
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer), &[output_pointer.to_int(context).into(), offset.into()],
&[offset],
context.word_type().as_basic_type_enum(),
"calldata_pointer_with_offset",
); );
context
.build_load(offset, "calldata_value") context.build_load(output_pointer, "call_data_load_value")
.and_then(|value| context.build_byte_swap(value))
} }
/// Translates the calldata size. /// Translates the calldata size.
@@ -37,8 +30,14 @@ where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let value = context.get_global_value(crate::polkavm::GLOBAL_CALLDATA_SIZE)?; let value = context.get_global_value(crate::polkavm::GLOBAL_CALLDATA_SIZE)?;
Ok(context
Ok(value) .builder()
.build_int_z_extend(
value.into_int_value(),
context.word_type(),
"call_data_size_value",
)?
.into())
} }
/// Translates the calldata copy. /// Translates the calldata copy.
@@ -51,20 +50,19 @@ pub fn copy<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let offset = context.safe_truncate_int_to_xlen(destination_offset)?; let source_offset = context.safe_truncate_int_to_xlen(source_offset)?;
let size = context.safe_truncate_int_to_xlen(size)?; let size = context.safe_truncate_int_to_xlen(size)?;
let destination = context.build_heap_gep(offset, size)?; let destination_offset = context.safe_truncate_int_to_xlen(destination_offset)?;
let output_pointer = context.build_heap_gep(destination_offset, size)?;
let calldata_pointer = context context.build_runtime_call(
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? revive_runtime_api::polkavm_imports::CALL_DATA_COPY,
.value &[
.as_pointer_value(); output_pointer.to_int(context).into(),
let source = context.build_gep( size.into(),
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer), source_offset.into(),
&[context.safe_truncate_int_to_xlen(source_offset)?], ],
context.byte_type(),
"calldata_pointer_with_offset",
); );
context.build_memcpy(destination, source, size, "calldata_copy_memcpy_from_child") Ok(())
} }
+20 -4
View File
@@ -7,12 +7,20 @@ use crate::polkavm::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>>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
todo!() let gas_limit_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::GAS_LIMIT, &[])
.expect("the gas_limit syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(gas_limit_value, context.word_type(), "gas_limit")?
.into())
} }
/// Translates the `gas_price` instruction. /// Translates the `gas_price` instruction.
@@ -22,7 +30,15 @@ pub fn gas_price<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
Ok(context.word_const(1).as_basic_value_enum()) let gas_price_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::GAS_PRICE, &[])
.expect("the gas_price syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(gas_price_value, context.word_type(), "gas_price")?
.into())
} }
/// Translates the `tx.origin` instruction. /// Translates the `tx.origin` instruction.
@@ -121,7 +137,7 @@ pub fn basefee<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
Ok(context.word_const(0).as_basic_value_enum()) context.build_runtime_call_to_getter(revive_runtime_api::polkavm_imports::BASE_FEE)
} }
/// Translates the `address` instruction. /// Translates the `address` instruction.
@@ -1,7 +1,5 @@
//! Translates the value and balance operations. //! Translates the value and balance operations.
use inkwell::values::BasicValue;
use crate::polkavm::context::Context; use crate::polkavm::context::Context;
use crate::polkavm::Dependency; use crate::polkavm::Dependency;
@@ -12,7 +10,15 @@ pub fn gas<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
Ok(context.integer_const(256, 0).as_basic_value_enum()) let ref_time_left_value = context
.build_runtime_call(revive_runtime_api::polkavm_imports::REF_TIME_LEFT, &[])
.expect("the ref_time_left syscall method should return a value")
.into_int_value();
Ok(context
.builder()
.build_int_z_extend(ref_time_left_value, context.word_type(), "gas_left")?
.into())
} }
/// Translates the `value` instruction. /// Translates the `value` instruction.
+11 -10
View File
@@ -16,19 +16,20 @@ where
Some(address) => address, Some(address) => address,
None => super::context::address(context)?.into_int_value(), None => super::context::address(context)?.into_int_value(),
}; };
let address_pointer = context.build_address_argument_store(address)?; let address_pointer = context.build_address_argument_store(address)?;
let output_pointer = context.build_alloca_at_entry(context.word_type(), "output_pointer");
context.build_runtime_call( let code_size_value = context
revive_runtime_api::polkavm_imports::CODE_SIZE, .build_runtime_call(
&[ revive_runtime_api::polkavm_imports::CODE_SIZE,
address_pointer.to_int(context).into(), &[address_pointer.to_int(context).into()],
output_pointer.to_int(context).into(), )
], .expect("the code_size syscall method should return a value")
); .into_int_value();
context.build_load(output_pointer, "code_size") Ok(context
.builder()
.build_int_z_extend(code_size_value, context.word_type(), "code_size")?
.into())
} }
/// Translates the `extcodehash` instruction. /// Translates the `extcodehash` instruction.
@@ -10,17 +10,19 @@ pub fn size<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let output_pointer = context.build_alloca_at_entry(context.word_type(), "return_data_size"); let return_data_size_value = context
let output_pointer_parameter = context.builder().build_ptr_to_int( .build_runtime_call(revive_runtime_api::polkavm_imports::RETURNDATASIZE, &[])
output_pointer.value, .expect("the return_data_size syscall method should return a value")
context.xlen_type(), .into_int_value();
"return_data_copy_output_pointer",
)?; Ok(context
context.build_runtime_call( .builder()
revive_runtime_api::polkavm_imports::RETURNDATASIZE, .build_int_z_extend(
&[output_pointer_parameter.into()], return_data_size_value,
); context.word_type(),
context.build_load(output_pointer, "return_data_size_load") "return_data_size",
)?
.into())
} }
/// Translates the return data copy, trapping if /// Translates the return data copy, trapping if
Binary file not shown.
+6 -1
View File
@@ -1,4 +1,4 @@
use frame_support::runtime; use frame_support::{runtime, weights::constants::WEIGHT_REF_TIME_PER_SECOND};
use pallet_revive::AccountId32Mapper; use pallet_revive::AccountId32Mapper;
use polkadot_sdk::*; use polkadot_sdk::*;
@@ -46,6 +46,7 @@ mod runtime {
#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)] #[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
impl frame_system::Config for Runtime { impl frame_system::Config for Runtime {
type Block = Block; type Block = Block;
type BlockWeights = BlockWeights;
type AccountId = AccountId32; type AccountId = AccountId32;
type AccountData = pallet_balances::AccountData<<Runtime as pallet_balances::Config>::Balance>; type AccountData = pallet_balances::AccountData<<Runtime as pallet_balances::Config>::Balance>;
} }
@@ -65,6 +66,10 @@ parameter_types! {
pub const DepositPerByte: Balance = 1; pub const DepositPerByte: Balance = 1;
pub const DepositPerItem: Balance = 2; pub const DepositPerItem: Balance = 2;
pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(
Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX),
);
} }
#[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)] #[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)]
+2 -2
View File
@@ -421,7 +421,7 @@ impl Specs {
origin, origin,
value, value,
gas_limit.unwrap_or(GAS_LIMIT), gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT), storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
code, code,
data, data,
salt.0, salt.0,
@@ -461,7 +461,7 @@ impl Specs {
dest.to_eth_addr(&results), dest.to_eth_addr(&results),
value, value,
gas_limit.unwrap_or(GAS_LIMIT), gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT), storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
data, data,
DebugInfo::Skip, DebugInfo::Skip,
CollectEvents::Skip, CollectEvents::Skip,
+18 -6
View File
@@ -70,32 +70,42 @@ POLKAVM_IMPORT(void, balance, uint32_t)
POLKAVM_IMPORT(void, balance_of, uint32_t, uint32_t) POLKAVM_IMPORT(void, balance_of, uint32_t, uint32_t)
POLKAVM_IMPORT(void, base_fee, uint32_t)
POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t) POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(void, block_number, uint32_t) POLKAVM_IMPORT(void, block_number, uint32_t)
POLKAVM_IMPORT(uint64_t, call, uint32_t) POLKAVM_IMPORT(uint64_t, call, uint32_t)
POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t) POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_load, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_size)
POLKAVM_IMPORT(void, caller, uint32_t) POLKAVM_IMPORT(void, caller, uint32_t)
POLKAVM_IMPORT(void, chain_id, uint32_t) POLKAVM_IMPORT(void, chain_id, uint32_t)
POLKAVM_IMPORT(void, code_size, uint32_t, uint32_t) POLKAVM_IMPORT(uint64_t, code_size, uint32_t)
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t) POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t)
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, gas_limit);
POLKAVM_IMPORT(uint64_t, gas_price);
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t); POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, input, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, instantiate, uint32_t) POLKAVM_IMPORT(uint64_t, instantiate, uint32_t)
POLKAVM_IMPORT(void, now, uint32_t) POLKAVM_IMPORT(void, now, uint32_t)
@@ -104,14 +114,16 @@ POLKAVM_IMPORT(void, origin, uint32_t)
POLKAVM_IMPORT(void, seal_return, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, seal_return, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(uint64_t, ref_time_left)
POLKAVM_IMPORT(void, return_data_copy, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, return_data_copy, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, return_data_size, uint32_t) POLKAVM_IMPORT(uint64_t, return_data_size)
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t); POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
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);
+26 -8
View File
@@ -20,13 +20,19 @@ pub static BALANCE: &str = "balance";
pub static BALANCE_OF: &str = "balance_of"; pub static BALANCE_OF: &str = "balance_of";
pub static BASE_FEE: &str = "base_fee";
pub static BLOCK_HASH: &str = "block_hash"; pub static BLOCK_HASH: &str = "block_hash";
pub static BLOCK_NUMBER: &str = "block_number"; pub static BLOCK_NUMBER: &str = "block_number";
pub static CALL: &str = "call"; pub static CALL: &str = "call";
pub static DELEGATE_CALL: &str = "delegate_call"; pub static CALL_DATA_COPY: &str = "call_data_copy";
pub static CALL_DATA_LOAD: &str = "call_data_load";
pub static CALL_DATA_SIZE: &str = "call_data_size";
pub static CALLER: &str = "caller"; pub static CALLER: &str = "caller";
@@ -36,25 +42,29 @@ pub static CODE_SIZE: &str = "code_size";
pub static CODE_HASH: &str = "code_hash"; pub static CODE_HASH: &str = "code_hash";
pub static DELEGATE_CALL: &str = "delegate_call";
pub static DEPOSIT_EVENT: &str = "deposit_event"; pub static DEPOSIT_EVENT: &str = "deposit_event";
pub static GAS_LIMIT: &str = "gas_limit";
pub static GAS_PRICE: &str = "gas_price";
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data"; pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
pub static GET_STORAGE: &str = "get_storage"; pub static GET_STORAGE: &str = "get_storage";
pub static HASH_KECCAK_256: &str = "hash_keccak_256"; pub static HASH_KECCAK_256: &str = "hash_keccak_256";
pub static INPUT: &str = "input";
pub static INSTANTIATE: &str = "instantiate"; pub static INSTANTIATE: &str = "instantiate";
pub static NOW: &str = "now"; pub static NOW: &str = "now";
pub static ORIGIN: &str = "origin"; pub static ORIGIN: &str = "origin";
pub static RETURN: &str = "seal_return"; pub static REF_TIME_LEFT: &str = "ref_time_left";
pub static SET_STORAGE: &str = "set_storage"; pub static RETURN: &str = "seal_return";
pub static RETURNDATACOPY: &str = "return_data_copy"; pub static RETURNDATACOPY: &str = "return_data_copy";
@@ -62,34 +72,42 @@ pub static RETURNDATASIZE: &str = "return_data_size";
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data"; pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
pub static SET_STORAGE: &str = "set_storage";
pub static VALUE_TRANSFERRED: &str = "value_transferred"; 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";
/// 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; 28] = [ pub static IMPORTS: [&str; 34] = [
SBRK, SBRK,
MEMORY_SIZE, MEMORY_SIZE,
ADDRESS, ADDRESS,
BALANCE, BALANCE,
BALANCE_OF, BALANCE_OF,
BASE_FEE,
BLOCK_HASH, BLOCK_HASH,
BLOCK_NUMBER, BLOCK_NUMBER,
CALL, CALL,
DELEGATE_CALL, CALL_DATA_COPY,
CALL_DATA_LOAD,
CALL_DATA_SIZE,
CALLER, CALLER,
CHAIN_ID, CHAIN_ID,
CODE_SIZE, CODE_SIZE,
CODE_HASH, CODE_HASH,
DELEGATE_CALL,
DEPOSIT_EVENT, DEPOSIT_EVENT,
GAS_LIMIT,
GAS_PRICE,
GET_IMMUTABLE_DATA, GET_IMMUTABLE_DATA,
GET_STORAGE, GET_STORAGE,
HASH_KECCAK_256, HASH_KECCAK_256,
INPUT,
INSTANTIATE, INSTANTIATE,
NOW, NOW,
ORIGIN, ORIGIN,
REF_TIME_LEFT,
RETURN, RETURN,
RETURNDATACOPY, RETURNDATACOPY,
RETURNDATASIZE, RETURNDATASIZE,
+3
View File
@@ -48,6 +48,9 @@ mimalloc = { version = "*", default-features = false }
libc = { workspace = true } libc = { workspace = true }
inkwell = { workspace = true, features = ["target-riscv", "llvm18-0-no-llvm-linking"]} inkwell = { workspace = true, features = ["target-riscv", "llvm18-0-no-llvm-linking"]}
[build-dependencies]
git2 = { workspace = true }
[features] [features]
parallel = ["rayon"] parallel = ["rayon"]
default = ["parallel"] default = ["parallel"]
+5 -7
View File
@@ -1,9 +1,7 @@
fn main() { fn main() {
let git_rev = std::process::Command::new("git") let repo = git2::Repository::open("../..").expect("should be a repository");
.args(["rev-parse", "--short", "HEAD"]) let head = repo.head().expect("should have head");
.output() let commit = head.peel_to_commit().expect("should have commit");
.map(|out| String::from_utf8(out.stdout).unwrap_or_default()) let id = &commit.id().to_string()[..7];
.unwrap_or("unknown".to_owned()); println!("cargo:rustc-env=GIT_COMMIT_HASH={id}");
println!("cargo:rustc-env=GIT_COMMIT_HASH={}", git_rev.trim());
} }
@@ -1163,7 +1163,7 @@ where
self.name.as_str(), self.name.as_str(),
function_type, function_type,
output_size, output_size,
Some(inkwell::module::Linkage::Private), Some(inkwell::module::Linkage::External),
)?; )?;
function function
.borrow_mut() .borrow_mut()
+14 -2
View File
@@ -52,7 +52,7 @@ pub use self::warning::Warning;
pub mod test_utils; pub mod test_utils;
pub mod tests; pub mod tests;
use std::collections::BTreeSet; use std::collections::{BTreeMap, BTreeSet};
use std::path::PathBuf; use std::path::PathBuf;
/// Runs the Yul mode. /// Runs the Yul mode.
@@ -149,7 +149,7 @@ pub fn standard_output<T: Compiler>(
suppressed_warnings, suppressed_warnings,
)?; )?;
let source_code_files = solc_input let mut source_code_files: BTreeMap<String, String> = solc_input
.sources .sources
.iter() .iter()
.map(|(path, source)| (path.to_owned(), source.content.to_owned())) .map(|(path, source)| (path.to_owned(), source.content.to_owned()))
@@ -180,6 +180,18 @@ pub fn standard_output<T: Compiler>(
} }
} }
// load import callbacks unspecified in input
if let Some(sources) = &solc_output.sources {
for source_path in sources.keys() {
if !source_code_files.contains_key(source_path) {
let source = std::fs::read_to_string(source_path).map_err(|e| {
anyhow::anyhow!("Can't read source file at `{}`: {}", source_path, e)
})?;
let _ = source_code_files.insert(source_path.clone(), source);
}
}
}
let project = solc_output.try_to_project( let project = solc_output.try_to_project(
source_code_files, source_code_files,
libraries, libraries,
@@ -211,7 +211,7 @@ where
self.identifier.as_str(), self.identifier.as_str(),
function_type, function_type,
self.result.len(), self.result.len(),
Some(inkwell::module::Linkage::Private), Some(inkwell::module::Linkage::External),
)?; )?;
revive_llvm_context::PolkaVMFunction::set_attributes( revive_llvm_context::PolkaVMFunction::set_attributes(
context.llvm(), context.llvm(),
+26 -21
View File
@@ -1,47 +1,52 @@
var Module = { var Module = {
stdinData: "", stdinData: null,
stdoutCallback: null, stdinDataPosition: 0,
stderrCallback: null, stdoutData: [],
stderrData: [],
// Function to set a callback for stdout // Function to read and return all collected stdout data as a string
setStdoutCallback: function(callback) { readFromStdout: function() {
this.stdoutCallback = callback; if (!this.stdoutData.length) return "";
const decoder = new TextDecoder('utf-8');
const data = decoder.decode(new Uint8Array(this.stdoutData));
this.stdoutData = [];
return data;
}, },
// Function to set a callback for stderr // Function to read and return all collected stderr data as a string
setStderrCallback: function(callback) { readFromStderr: function() {
this.stderrCallback = callback; if (!this.stderrData.length) return "";
const decoder = new TextDecoder('utf-8');
const data = decoder.decode(new Uint8Array(this.stderrData));
this.stderrData = [];
return data;
}, },
// Function to set input data for stdin // Function to set input data for stdin
setStdinData: function(data) { writeToStdin: function(data) {
this.stdinData = data; const encoder = new TextEncoder();
this.stdinData = encoder.encode(data);
this.stdinDataPosition = 0;
}, },
// `preRun` is called before the program starts running // `preRun` is called before the program starts running
preRun: function() { preRun: function() {
// Define a custom stdin function // Define a custom stdin function
function customStdin() { function customStdin() {
if (Module.stdinData.length === 0) { if (!Module.stdinData || Module.stdinDataPosition >= Module.stdinData.length) {
return null; // End of input (EOF) return null; // End of input (EOF)
} }
const char = Module.stdinData.charCodeAt(0); return Module.stdinData[Module.stdinDataPosition++];
Module.stdinData = Module.stdinData.slice(1); // Remove the character from input
return char;
} }
// Define a custom stdout function // Define a custom stdout function
function customStdout(char) { function customStdout(char) {
if (Module.stdoutCallback) { Module.stdoutData.push(char);
Module.stdoutCallback(String.fromCharCode(char));
}
} }
// Define a custom stderr function // Define a custom stderr function
function customStderr(char) { function customStderr(char) {
if (Module.stderrCallback) { Module.stderrData.push(char);
Module.stderrCallback(String.fromCharCode(char));
}
} }
FS.init(customStdin, customStdout, customStderr); FS.init(customStdin, customStdout, customStderr);
+3 -14
View File
@@ -24,28 +24,17 @@ mergeInto(LibraryManager.library, {
} else { } else {
throw new Error('Unknown environment: Unable to load resolc.js'); throw new Error('Unknown environment: Unable to load resolc.js');
} }
revive.setStdinData(inputJson); revive.writeToStdin(inputJson);
let stdoutString = "";
revive.setStdoutCallback(function(char) {
if (char.charCodeAt(0) === '\n') {
exit;
}
stdoutString += char;
});
let stderrString = "";
revive.setStderrCallback(function(char) {
stderrString += char;
});
// Call main on the new instance // Call main on the new instance
const result = revive.callMain(['--recursive-process']); const result = revive.callMain(['--recursive-process']);
if (result) { if (result) {
const stderrString = revive.readFromStderr();
const error = JSON.stringify({ type: 'error', message: stderrString || "Unknown error" }); const error = JSON.stringify({ type: 'error', message: stderrString || "Unknown error" });
return stringToNewUTF8(error); return stringToNewUTF8(error);
} else { } else {
const stdoutString = revive.readFromStdout();
const json = JSON.stringify({ type: 'success', data: stdoutString }); const json = JSON.stringify({ type: 'success', data: stdoutString });
return stringToNewUTF8(json); return stringToNewUTF8(json);
} }
+3 -17
View File
@@ -34,26 +34,12 @@ async function runCompiler() {
m.soljson = soljson; m.soljson = soljson;
// Set input data for stdin // Set input data for stdin
m.setStdinData(JSON.stringify(compilerStandardJsonInput)); m.writeToStdin(JSON.stringify(compilerStandardJsonInput));
var stdoutString = "";
m.setStdoutCallback(function(char) {
if (char.charCodeAt(0) === '\n') {
console.log("new line")
exit
}
stdoutString += char;
});
var stderrString = "";
m.setStderrCallback(function(char) {
stderrString += char;
});
// Compile the Solidity source code // Compile the Solidity source code
let x = m.callMain(['--standard-json']); let x = m.callMain(['--standard-json']);
console.log("Stdout: " + stdoutString); console.log("Stdout: " + m.readFromStdout());
console.error("Stderr: " + stderrString); console.error("Stderr: " + m.readFromStderr());
} }
runCompiler().catch(err => { runCompiler().catch(err => {
+2 -16
View File
@@ -29,24 +29,10 @@ onmessage = async function (e) {
m.soljson = Module; m.soljson = Module;
// Set input data for stdin // Set input data for stdin
m.setStdinData(JSON.stringify(sourceCode)); m.writeToStdin(JSON.stringify(sourceCode));
var stdoutString = "";
m.setStdoutCallback(function(char) {
if (char.charCodeAt(0) === '\n') {
console.log("new line")
exit
}
stdoutString += char;
});
var stderrString = "";
m.setStderrCallback(function(char) {
stderrString += char;
});
// Compile the Solidity source code // Compile the Solidity source code
m.callMain(['--standard-json']); m.callMain(['--standard-json']);
postMessage({output: stdoutString || stderrString}); postMessage({output: m.readFromStdout() || m.readFromStderr()});
}; };