From 1ba806be1fe2b3eb50097ece0264a2440ee1e46f Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Sat, 1 Jun 2024 20:48:20 +0200 Subject: [PATCH] Contract calls (#19) --- Cargo.lock | 50 ++-- crates/integration/contracts/Call.sol | 20 ++ crates/integration/src/cases.rs | 49 ++++ crates/integration/src/mock_runtime.rs | 182 +++++++++++-- crates/integration/src/tests.rs | 31 +++ .../src/polkavm/const/runtime_api.rs | 83 +++--- .../polkavm/context/function/llvm_runtime.rs | 237 ----------------- .../context/function/runtime/default_call.rs | 244 ------------------ .../polkavm/context/function/runtime/entry.rs | 12 +- .../polkavm/context/function/runtime/mod.rs | 43 --- .../llvm-context/src/polkavm/context/mod.rs | 119 +-------- crates/llvm-context/src/polkavm/evm/call.rs | 160 +++++++----- .../llvm-context/src/polkavm/evm/context.rs | 8 +- crates/llvm-context/src/polkavm/evm/create.rs | 19 +- crates/llvm-context/src/polkavm/evm/crypto.rs | 2 +- .../llvm-context/src/polkavm/evm/ether_gas.rs | 2 +- crates/llvm-context/src/polkavm/evm/event.rs | 2 +- .../llvm-context/src/polkavm/evm/ext_code.rs | 7 +- .../src/polkavm/evm/return_data.rs | 57 +--- crates/llvm-context/src/polkavm/utils.rs | 18 -- .../src/calling_convention.rs | 36 ++- .../src/polkavm_guest.c | 2 + crates/solidity/src/evmla/assembly/mod.rs | 7 - .../src/evmla/ethereal_ir/entry_link.rs | 2 +- .../ethereal_ir/function/block/element/mod.rs | 30 +-- .../statement/expression/function_call/mod.rs | 32 +-- .../src/yul/parser/statement/object.rs | 17 +- 27 files changed, 541 insertions(+), 930 deletions(-) create mode 100644 crates/integration/contracts/Call.sol delete mode 100644 crates/llvm-context/src/polkavm/context/function/runtime/default_call.rs diff --git a/Cargo.lock b/Cargo.lock index 55b25920..5638ea5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" dependencies = [ "arrayvec", "bytes", @@ -68,7 +68,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", "syn-solidity", "tiny-keccak", ] @@ -284,7 +284,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -473,7 +473,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -500,9 +500,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.4" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if", "cpufeatures", @@ -1047,7 +1047,7 @@ source = "git+https://github.com/TheDan64/inkwell.git?rev=6c0fb56b3554e939f9ca61 dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -1519,9 +1519,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -2013,22 +2013,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -2200,9 +2200,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.65" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -2218,7 +2218,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -2265,7 +2265,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] @@ -2416,7 +2416,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -2438,7 +2438,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2677,14 +2677,14 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -2697,7 +2697,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn 2.0.66", ] [[package]] diff --git a/crates/integration/contracts/Call.sol b/crates/integration/contracts/Call.sol new file mode 100644 index 00000000..05bfcd1d --- /dev/null +++ b/crates/integration/contracts/Call.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8; + +contract Call { + function value_transfer(address payable destination) public payable { + destination.transfer(msg.value); + } + + function echo(bytes memory payload) public pure returns (bytes memory) { + return payload; + } + + function call( + address callee, + bytes memory payload + ) public pure returns (bytes memory) { + return Call(callee).echo(payload); + } +} diff --git a/crates/integration/src/cases.rs b/crates/integration/src/cases.rs index 911d2e49..e7b7f51b 100644 --- a/crates/integration/src/cases.rs +++ b/crates/integration/src/cases.rs @@ -135,6 +135,19 @@ sol!( } ); +sol!( + contract Call { + function value_transfer(address payable destination) public payable; + + function echo(bytes memory payload) public payable returns (bytes memory); + + function call( + address callee, + bytes memory payload + ) public payable returns (bytes memory); + } +); + impl Contract { /// Execute the contract. /// @@ -441,6 +454,42 @@ impl Contract { calldata: MCopy::memcpyCall::new((payload,)).abi_encode(), } } + + pub fn call_value_transfer(destination: Address) -> Self { + let code = include_str!("../contracts/Call.sol"); + let name = "Call"; + + Self { + name, + evm_runtime: crate::compile_evm_bin_runtime(name, code), + pvm_runtime: crate::compile_blob(name, code), + calldata: Call::value_transferCall::new((destination,)).abi_encode(), + } + } + + pub fn call_call(callee: Address, payload: Vec) -> Self { + let code = include_str!("../contracts/Call.sol"); + let name = "Call"; + + Self { + name, + evm_runtime: crate::compile_evm_bin_runtime(name, code), + pvm_runtime: crate::compile_blob(name, code), + calldata: Call::callCall::new((callee, payload)).abi_encode(), + } + } + + pub fn call_constructor() -> Self { + let code = include_str!("../contracts/Call.sol"); + let name = "Call"; + + Self { + name, + evm_runtime: crate::compile_evm_bin_runtime(name, code), + pvm_runtime: crate::compile_blob(name, code), + calldata: Default::default(), + } + } } #[cfg(test)] diff --git a/crates/integration/src/mock_runtime.rs b/crates/integration/src/mock_runtime.rs index e29828f7..17e27f47 100644 --- a/crates/integration/src/mock_runtime.rs +++ b/crates/integration/src/mock_runtime.rs @@ -82,6 +82,8 @@ struct Frame { output: CallOutput, /// The export to call. export: Export, + /// The returndata from the last contract call. + returndata: Vec, } impl Default for Frame { @@ -93,6 +95,7 @@ impl Default for Frame { input: Default::default(), output: Default::default(), export: Default::default(), + returndata: Default::default(), } } } @@ -224,8 +227,8 @@ impl TransactionBuilder { .unwrap_or_else(|| panic!("contract code not found: {blob_hash}")); let (mut instance, _) = prepare(code, None); let export = match self.context.top_frame().export { - Export::Call => runtime_api::CALL, - Export::Deploy(_) => runtime_api::DEPLOY, + Export::Call => runtime_api::exports::CALL, + Export::Deploy(_) => runtime_api::exports::DEPLOY, }; let export = instance.module().lookup_export(export).unwrap(); self.call_on(&mut instance, export) @@ -354,7 +357,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::INPUT, + runtime_api::imports::INPUT, |caller: Caller, out_ptr: u32, out_len_ptr: u32| -> Result<(), Trap> { let (mut caller, transaction) = caller.split(); @@ -371,7 +374,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::RETURN, + runtime_api::imports::RETURN, |caller: Caller, flags: u32, data_ptr: u32, @@ -390,7 +393,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::VALUE_TRANSFERRED, + runtime_api::imports::VALUE_TRANSFERRED, |caller: Caller, out_ptr: u32, out_len_ptr: u32| -> Result<(), Trap> { let (mut caller, transaction) = caller.split(); @@ -426,7 +429,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::SET_STORAGE, + runtime_api::imports::SET_STORAGE, |caller: Caller, key_ptr: u32, key_len: u32, @@ -461,7 +464,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::GET_STORAGE, + runtime_api::imports::GET_STORAGE, |caller: Caller, key_ptr: u32, key_len: u32, @@ -495,7 +498,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::HASH_KECCAK_256, + runtime_api::imports::HASH_KECCAK_256, |caller: Caller, input_ptr: u32, input_len: u32, @@ -516,7 +519,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::NOW, + runtime_api::imports::NOW, |caller: Caller, out_ptr: u32, out_len_ptr: u32| { let (mut caller, _) = caller.split(); @@ -537,7 +540,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::BLOCK_NUMBER, + runtime_api::imports::BLOCK_NUMBER, |caller: Caller, out_ptr: u32, out_len_ptr: u32| { let (mut caller, _) = caller.split(); @@ -558,7 +561,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::ADDRESS, + runtime_api::imports::ADDRESS, |caller: Caller, out_ptr: u32, out_len_ptr: u32| { let (mut caller, transaction) = caller.split(); @@ -580,7 +583,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::CALLER, + runtime_api::imports::CALLER, |caller: Caller, out_ptr: u32, out_len_ptr: u32| { let (mut caller, transaction) = caller.split(); @@ -602,7 +605,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::DEPOSIT_EVENT, + runtime_api::imports::DEPOSIT_EVENT, |caller: Caller, topics_ptr: u32, topics_len: u32, @@ -639,7 +642,7 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::INSTANTIATE, + runtime_api::imports::INSTANTIATE, |caller: Caller, argument_ptr: u32| { let (mut caller, transaction) = caller.split(); @@ -732,7 +735,122 @@ fn link_host_functions(engine: &Engine) -> Linker { linker .func_wrap( - runtime_api::CODE_SIZE, + runtime_api::imports::CALL, + |caller: Caller, argument_ptr: u32| -> Result { + let (mut caller, transaction) = caller.split(); + + #[derive(Debug)] + #[repr(packed)] + struct Arguments { + _flags: u32, + address_ptr: u32, + _ref_time_limit: u64, + proof_size_limit: u64, + deposit_ptr: u32, + value_ptr: u32, + input_data_ptr: u32, + input_data_len: u32, + output_ptr: u32, + output_len_ptr: u32, + } + let mut buffer = [0; std::mem::size_of::()]; + caller.read_memory_into_slice(argument_ptr, &mut buffer)?; + let arguments: Arguments = unsafe { std::mem::transmute(buffer) }; + + assert_eq!({ arguments.proof_size_limit }, 0); + assert_eq!({ arguments.deposit_ptr }, u32::MAX); + + let amount = if arguments.value_ptr != u32::MAX { + let value = caller.read_memory_into_vec(arguments.value_ptr, 32)?; + U256::from_le_slice(&value) + } else { + U256::ZERO + }; + + match transaction.top_account_mut().value.checked_sub(amount) { + Some(deducted) => transaction.top_account_mut().value = deducted, + None => { + log::info!("call failed: insufficient balance {amount}"); + return Ok(1); + } + } + + let bytes = caller.read_memory_into_vec(arguments.address_ptr, 32)?; + let word = U256::from_le_slice(&bytes); + let address = Address::from_word(word.into()); + log::info!("call {address}"); + + if !transaction.state.accounts.contains_key(&address) { + log::info!( + "balance transfer {amount} from {} to {address}", + transaction.top_frame().callee + ); + + transaction + .state + .accounts + .entry(address) + .or_insert_with(|| Account { + value: amount, + contract: None, + storage: Default::default(), + }); + + return Ok(0); + } + + if transaction.stack.len() >= Transaction::CALL_STACK_SIZE { + log::info!("deployment faild: maximum stack depth reached"); + return Ok(1); + } + + let calldata = caller + .read_memory_into_vec(arguments.input_data_ptr, arguments.input_data_len)?; + + let (state, output) = transaction + .state + .clone() + .transaction() + .callee(address) + .callvalue(amount) + .calldata(calldata) + .call(); + + let bytes_to_copy = caller.read_u32(arguments.output_len_ptr)? as usize; + let output_size = output.data.len(); + assert!( + bytes_to_copy <= output_size, + "output buffer of {bytes_to_copy}b too small for {output_size}b" + ); + + transaction.top_frame_mut().returndata = output.data.to_vec(); + caller.write_memory( + arguments.output_ptr, + &transaction.top_frame().returndata[..bytes_to_copy], + )?; + caller.write_memory(arguments.output_len_ptr, &output.data.len().to_le_bytes())?; + assert_eq!( + transaction.top_frame().returndata.len(), + caller.read_u32(arguments.output_len_ptr)? as usize + ); + + let success = if output.flags == ReturnFlags::Success { + log::info!("call succeeded"); + transaction.state = state; + 0 + } else { + log::info!("call failed: callee reverted {:?}", output.flags); + 1 + }; + + Ok(success) + }, + ) + .unwrap(); + + linker + .func_wrap( + runtime_api::imports::CODE_SIZE, |caller: Caller, address_ptr: u32| { let (caller, transaction) = caller.split(); @@ -754,6 +872,36 @@ fn link_host_functions(engine: &Engine) -> Linker { ) .unwrap(); + linker + .func_wrap( + runtime_api::imports::RETURNDATACOPY, + |caller: Caller, + destination_ptr: u32, + offset: u32, + size: u32| + -> Result<(), Trap> { + let (mut caller, transaction) = caller.split(); + + let offset = offset as usize; + let slice_end = offset + .checked_add(size as usize) + .expect("offset + size overflows"); + + assert!( + slice_end <= transaction.top_frame().returndata.len(), + "offset + size is larger than RETURNDATASIZE" + ); + + caller.write_memory( + destination_ptr, + &transaction.top_frame().returndata[offset..slice_end], + )?; + + Ok(()) + }, + ) + .unwrap(); + linker } @@ -772,7 +920,7 @@ pub fn instantiate_module( module: &Module, engine: &Engine, ) -> (Instance, ExportIndex) { - let export = module.lookup_export(runtime_api::CALL).unwrap(); + let export = module.lookup_export(runtime_api::imports::CALL).unwrap(); let func = link_host_functions(engine).instantiate_pre(module).unwrap(); let instance = func.instantiate().unwrap(); @@ -789,7 +937,7 @@ pub fn prepare(code: &[u8], config: Option) -> (Instance, E module_config.set_gas_metering(Some(GasMeteringKind::Sync)); let module = Module::from_blob(&engine, &module_config, blob).unwrap(); - let export = module.lookup_export(runtime_api::CALL).unwrap(); + let export = module.lookup_export(runtime_api::exports::CALL).unwrap(); let func = link_host_functions(&engine) .instantiate_pre(&module) .unwrap(); diff --git a/crates/integration/src/tests.rs b/crates/integration/src/tests.rs index d8d91f5f..8f9390fd 100644 --- a/crates/integration/src/tests.rs +++ b/crates/integration/src/tests.rs @@ -523,6 +523,36 @@ fn ext_code_size() { assert_eq!(received, expected); } +#[test] +fn value_transfer() { + // Succeeds in remix (shanghai) but traps the interpreter + let (state, _) = assert_success(&Contract::call_value_transfer(Default::default()), false); + + assert_eq!(state.accounts().len(), 2); + assert!(state.accounts().get(&Address::default()).is_some()); +} + +#[test] +fn echo() { + let (state, address) = State::new_deployed(Contract::call_constructor()); + + let expected = vec![1, 2, 3, 4, 5]; + let contract = Contract::call_call(address, expected.clone()); + let (_, output) = state + .transaction() + .with_default_account(&contract.pvm_runtime) + .calldata(contract.calldata) + .call(); + + assert_eq!(output.flags, ReturnFlags::Success); + + let received = alloy_primitives::Bytes::abi_decode(&output.data, true) + .unwrap() + .to_vec(); + + assert_eq!(expected, received); +} + #[test] fn mcopy() { let expected = vec![1, 2, 3]; @@ -532,5 +562,6 @@ fn mcopy() { let received = alloy_primitives::Bytes::abi_decode(&output.data, true) .unwrap() .to_vec(); + assert_eq!(expected, received); } diff --git a/crates/llvm-context/src/polkavm/const/runtime_api.rs b/crates/llvm-context/src/polkavm/const/runtime_api.rs index c4c4b610..4b5ae89c 100644 --- a/crates/llvm-context/src/polkavm/const/runtime_api.rs +++ b/crates/llvm-context/src/polkavm/const/runtime_api.rs @@ -1,57 +1,68 @@ //! Runtime API import and export symbols. -/// The contract deploy export. -pub static CALL: &str = "call"; +pub mod exports { + /// The contract deploy export. + pub static CALL: &str = "call"; -/// The contract call export. -pub static DEPLOY: &str = "deploy"; + /// The contract call export. + pub static DEPLOY: &str = "deploy"; -/// All exported symbols. -/// Useful for configuring common attributes and linkage. -pub static EXPORTS: [&str; 2] = [CALL, DEPLOY]; + /// All exported symbols. + /// Useful for configuring common attributes and linkage. + pub static EXPORTS: [&str; 2] = [CALL, DEPLOY]; +} -pub static ADDRESS: &str = "address"; +pub mod imports { + pub static ADDRESS: &str = "address"; -pub static BLOCK_NUMBER: &str = "block_number"; + pub static BLOCK_NUMBER: &str = "block_number"; -pub static CALLER: &str = "caller"; + pub static CALL: &str = "seal_call"; -pub static CODE_SIZE: &str = "code_size"; + pub static CALLER: &str = "caller"; -pub static DEPOSIT_EVENT: &str = "deposit_event"; + pub static CODE_SIZE: &str = "code_size"; -pub static GET_STORAGE: &str = "get_storage"; + pub static DEPOSIT_EVENT: &str = "deposit_event"; -pub static HASH_KECCAK_256: &str = "hash_keccak_256"; + pub static GET_STORAGE: &str = "get_storage"; -pub static INPUT: &str = "input"; + pub static HASH_KECCAK_256: &str = "hash_keccak_256"; -pub static INSTANTIATE: &str = "instantiate"; + pub static INPUT: &str = "input"; -pub static NOW: &str = "now"; + pub static INSTANTIATE: &str = "instantiate"; -pub static RETURN: &str = "seal_return"; + pub static NOW: &str = "now"; -pub static SET_STORAGE: &str = "set_storage"; + pub static RETURN: &str = "seal_return"; -pub static VALUE_TRANSFERRED: &str = "value_transferred"; + pub static RETURNDATACOPY: &str = "returndatacopy"; -/// All imported runtime API symbols.. -/// Useful for configuring common attributes and linkage. -pub static IMPORTS: [&str; 12] = [ - ADDRESS, - BLOCK_NUMBER, - CALLER, - DEPOSIT_EVENT, - GET_STORAGE, - HASH_KECCAK_256, - INPUT, - INSTANTIATE, - NOW, - RETURN, - SET_STORAGE, - VALUE_TRANSFERRED, -]; + pub static SET_STORAGE: &str = "set_storage"; + + pub static VALUE_TRANSFERRED: &str = "value_transferred"; + + /// All imported runtime API symbols. + /// Useful for configuring common attributes and linkage. + pub static IMPORTS: [&str; 15] = [ + ADDRESS, + BLOCK_NUMBER, + CALL, + CALLER, + CODE_SIZE, + DEPOSIT_EVENT, + GET_STORAGE, + HASH_KECCAK_256, + INPUT, + INSTANTIATE, + NOW, + RETURN, + RETURNDATACOPY, + SET_STORAGE, + VALUE_TRANSFERRED, + ]; +} /// PolkaVM __sbrk API symbol to extend the heap memory. pub static SBRK: &str = "__sbrk"; diff --git a/crates/llvm-context/src/polkavm/context/function/llvm_runtime.rs b/crates/llvm-context/src/polkavm/context/function/llvm_runtime.rs index aecb76f2..8f26288b 100644 --- a/crates/llvm-context/src/polkavm/context/function/llvm_runtime.rs +++ b/crates/llvm-context/src/polkavm/context/function/llvm_runtime.rs @@ -11,11 +11,6 @@ use crate::polkavm::context::function::Function; /// The functions are automatically linked to the LLVM implementations if the signatures match. #[derive(Debug)] pub struct LLVMRuntime<'ctx> { - /// The LLVM personality function, used for exception handling. - pub personality: FunctionDeclaration<'ctx>, - /// The LLVM exception throwing function. - pub cxa_throw: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. pub shl: FunctionDeclaration<'ctx>, /// The corresponding LLVM runtime function. @@ -37,29 +32,6 @@ pub struct LLVMRuntime<'ctx> { /// The corresponding LLVM runtime function. pub sha3: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. - pub system_request: FunctionDeclaration<'ctx>, - - /// The corresponding LLVM runtime function. - //pub far_call: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. - pub far_call_byref: FunctionDeclaration<'ctx>, - - /// The corresponding LLVM runtime function. - pub static_call: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. - pub static_call_byref: FunctionDeclaration<'ctx>, - - /// The corresponding LLVM runtime function. - pub delegate_call: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. - pub delegate_call_byref: FunctionDeclaration<'ctx>, - - /// The corresponding LLVM runtime function. - pub mimic_call: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. - pub mimic_call_byref: FunctionDeclaration<'ctx>, - /// The corresponding LLVM runtime function. pub r#return: FunctionDeclaration<'ctx>, /// The corresponding LLVM runtime function. @@ -139,30 +111,6 @@ impl<'ctx> LLVMRuntime<'ctx> { module: &inkwell::module::Module<'ctx>, optimizer: &Optimizer, ) -> Self { - let personality = Self::declare( - module, - Self::FUNCTION_PERSONALITY, - llvm.i32_type().fn_type(&[], false), - None, - ); - - let cxa_throw = Self::declare( - module, - Self::FUNCTION_CXA_THROW, - llvm.void_type().fn_type( - vec![ - llvm.ptr_type(AddressSpace::Stack.into()) - .as_basic_type_enum() - .into(); - 3 - ] - .as_slice(), - false, - ), - Some(inkwell::module::Linkage::External), - ); - Function::set_cxa_throw_attributes(llvm, cxa_throw); - let shl = Self::declare( module, Self::FUNCTION_SHL, @@ -288,138 +236,6 @@ impl<'ctx> LLVMRuntime<'ctx> { false, ); - let system_request = Self::declare( - module, - Self::FUNCTION_SYSTEM_REQUEST, - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .fn_type( - vec![ - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - llvm.ptr_type(AddressSpace::Stack.into()) - .as_basic_type_enum() - .into(), - ] - .as_slice(), - false, - ), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, system_request, optimizer); - - let external_call_arguments: Vec = vec![ - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(); - crate::polkavm::context::function::runtime::entry::Entry::MANDATORY_ARGUMENTS_COUNT - + crate::polkavm::EXTRA_ABI_DATA_SIZE - ]; - let mut mimic_call_arguments = external_call_arguments.clone(); - mimic_call_arguments.push( - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - ); - - let mut external_call_arguments_by_ref: Vec = vec![ - llvm.ptr_type(AddressSpace::Generic.into()) - .as_basic_type_enum() - .into(), - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - ]; - external_call_arguments_by_ref.extend::>(vec![ - llvm.custom_width_int_type( - revive_common::BIT_LENGTH_WORD as u32 - ) - .as_basic_type_enum() - .into(); - crate::polkavm::EXTRA_ABI_DATA_SIZE - ]); - let mut mimic_call_arguments_by_ref = external_call_arguments_by_ref.clone(); - mimic_call_arguments_by_ref.push( - llvm.custom_width_int_type(revive_common::BIT_LENGTH_WORD as u32) - .as_basic_type_enum() - .into(), - ); - - let external_call_result_type = llvm - .struct_type( - &[ - llvm.ptr_type(AddressSpace::Generic.into()) - .as_basic_type_enum(), - llvm.bool_type().as_basic_type_enum(), - ], - false, - ) - .as_basic_type_enum(); - - //let far_call = Self::declare( - // module, - // Self::FUNCTION_FARCALL, - // external_call_result_type.fn_type(external_call_arguments.as_slice(), false), - // Some(inkwell::module::Linkage::External), - //); - //Function::set_default_attributes(llvm, far_call, optimizer); - let static_call = Self::declare( - module, - Self::FUNCTION_STATICCALL, - external_call_result_type.fn_type(external_call_arguments.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, static_call, optimizer); - let delegate_call = Self::declare( - module, - Self::FUNCTION_DELEGATECALL, - external_call_result_type.fn_type(external_call_arguments.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, delegate_call, optimizer); - let mimic_call = Self::declare( - module, - Self::FUNCTION_MIMICCALL, - external_call_result_type.fn_type(mimic_call_arguments.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, mimic_call, optimizer); - - let far_call_byref = Self::declare( - module, - Self::FUNCTION_FARCALL_BYREF, - external_call_result_type.fn_type(external_call_arguments_by_ref.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, far_call_byref, optimizer); - let static_call_byref = Self::declare( - module, - Self::FUNCTION_STATICCALL_BYREF, - external_call_result_type.fn_type(external_call_arguments_by_ref.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, static_call_byref, optimizer); - let delegate_call_byref = Self::declare( - module, - Self::FUNCTION_DELEGATECALL_BYREF, - external_call_result_type.fn_type(external_call_arguments_by_ref.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, delegate_call_byref, optimizer); - let mimic_call_byref = Self::declare( - module, - Self::FUNCTION_MIMICCALL_BYREF, - external_call_result_type.fn_type(mimic_call_arguments_by_ref.as_slice(), false), - Some(inkwell::module::Linkage::External), - ); - Function::set_default_attributes(llvm, mimic_call_byref, optimizer); - let r#return = Self::declare( module, Self::FUNCTION_RETURN, @@ -454,9 +270,6 @@ impl<'ctx> LLVMRuntime<'ctx> { Function::set_default_attributes(llvm, revert, optimizer); Self { - personality, - cxa_throw, - shl, shr, sar, @@ -469,18 +282,6 @@ impl<'ctx> LLVMRuntime<'ctx> { sha3, - system_request, - - //far_call, - static_call, - delegate_call, - mimic_call, - - far_call_byref, - static_call_byref, - delegate_call_byref, - mimic_call_byref, - r#return, revert, } @@ -506,42 +307,4 @@ impl<'ctx> LLVMRuntime<'ctx> { value.set_linkage(inkwell::module::Linkage::External); FunctionDeclaration::new(value.get_type(), value).into() } - - /// Modifies the external call function with `is_byref` and `is_system` modifiers. - pub fn modify( - &self, - function: FunctionDeclaration<'ctx>, - is_byref: bool, - ) -> anyhow::Result> { - let modified = if - /*function == self.far_call { - match is_byref { - false => self.far_call, - true => self.far_call_byref, - } - } else if */ - function == self.static_call { - match is_byref { - false => self.static_call, - true => self.static_call_byref, - } - } else if function == self.delegate_call { - match is_byref { - false => self.delegate_call, - true => self.delegate_call_byref, - } - } else if function == self.mimic_call { - match is_byref { - false => self.mimic_call, - true => self.mimic_call_byref, - } - } else { - anyhow::bail!( - "Cannot modify an external call function `{}`", - function.value.get_name().to_string_lossy() - ); - }; - - Ok(modified) - } } diff --git a/crates/llvm-context/src/polkavm/context/function/runtime/default_call.rs b/crates/llvm-context/src/polkavm/context/function/runtime/default_call.rs deleted file mode 100644 index c9cd8bb9..00000000 --- a/crates/llvm-context/src/polkavm/context/function/runtime/default_call.rs +++ /dev/null @@ -1,244 +0,0 @@ -//! The `default_call` function. - -use inkwell::types::BasicType; - -use crate::polkavm::context::function::declaration::Declaration as FunctionDeclaration; -use crate::polkavm::context::function::llvm_runtime::LLVMRuntime; -use crate::polkavm::context::function::Function; -use crate::polkavm::context::Context; -use crate::polkavm::Dependency; -use crate::polkavm::WriteLLVM; - -/// The `default_call` function. -/// Generates a default contract call, if the `msg.value` is zero. -#[derive(Debug)] -pub struct DefaultCall { - /// The name of the inner function used for the low-level call. - inner_name: String, - /// The function name with the low-level function name as an element. - name: String, -} - -#[allow(unused)] -impl DefaultCall { - /// The gas argument index. - pub const ARGUMENT_INDEX_GAS: usize = 0; - - /// The address argument index. - pub const ARGUMENT_INDEX_ADDRESS: usize = 1; - - /// The input offset argument index. - pub const ARGUMENT_INDEX_INPUT_OFFSET: usize = 2; - - /// The input length argument index. - pub const ARGUMENT_INDEX_INPUT_LENGTH: usize = 3; - - /// The output offset argument index. - pub const ARGUMENT_INDEX_OUTPUT_OFFSET: usize = 4; - - /// The output length argument index. - pub const ARGUMENT_INDEX_OUTPUT_LENGTH: usize = 5; - - /// A shortcut constructor. - pub fn new(call_function: FunctionDeclaration) -> Self { - let inner_name = call_function.value.get_name().to_string_lossy().to_string(); - let name = Self::name(call_function); - - Self { inner_name, name } - } - - /// Returns the function name. - pub fn name(call_function: FunctionDeclaration) -> String { - let suffix = match call_function.value.get_name().to_string_lossy() { - name if name == LLVMRuntime::FUNCTION_FARCALL => "far", - name if name == LLVMRuntime::FUNCTION_STATICCALL => "static", - name if name == LLVMRuntime::FUNCTION_DELEGATECALL => "delegate", - name => panic!("Invalid low-level call inner function `{name}`"), - }; - format!("__default_{suffix}_call") - } - - /// Returns the low-level call function. - fn inner_function<'ctx, D>(&self, context: &Context<'ctx, D>) -> FunctionDeclaration<'ctx> - where - D: Dependency + Clone, - { - match self.inner_name.as_str() { - //name if name == LLVMRuntime::FUNCTION_FARCALL => context.llvm_runtime().far_call, - name if name == LLVMRuntime::FUNCTION_STATICCALL => context.llvm_runtime().static_call, - name if name == LLVMRuntime::FUNCTION_DELEGATECALL => { - context.llvm_runtime().delegate_call - } - name => panic!("Invalid low-level call inner function `{name}`"), - } - } -} - -impl WriteLLVM for DefaultCall -where - D: Dependency + Clone, -{ - fn declare(&mut self, context: &mut Context) -> anyhow::Result<()> { - let function_type = context.function_type( - vec![ - context.word_type().as_basic_type_enum(), - context.word_type().as_basic_type_enum(), - context.word_type().as_basic_type_enum(), - context.word_type().as_basic_type_enum(), - context.word_type().as_basic_type_enum(), - context.word_type().as_basic_type_enum(), - ], - 1, - false, - ); - let function = context.add_function( - self.name.as_str(), - function_type, - 1, - Some(inkwell::module::Linkage::Private), - )?; - Function::set_frontend_runtime_attributes( - context.llvm, - function.borrow().declaration(), - &context.optimizer, - ); - - Ok(()) - } - - fn into_llvm(self, context: &mut Context) -> anyhow::Result<()> { - context.set_current_function(self.name.as_str())?; - - /* - let gas = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_GAS) - .into_int_value(); - let address = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_ADDRESS) - .into_int_value(); - let input_offset = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_INPUT_OFFSET) - .into_int_value(); - let input_length = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_INPUT_LENGTH) - .into_int_value(); - let output_offset = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_OUTPUT_OFFSET) - .into_int_value(); - let output_length = context - .current_function() - .borrow() - .get_nth_param(Self::ARGUMENT_INDEX_OUTPUT_LENGTH) - .into_int_value(); - */ - context.set_basic_block(context.current_function().borrow().entry_block()); - - let status_code_result_pointer = context.build_alloca( - context.word_type(), - "contract_call_result_status_code_pointer", - ); - /* - context.build_store(status_code_result_pointer, context.field_const(0)); - - let abi_data = crate::polkavm::utils::abi_data( - context, - input_offset, - input_length, - Some(gas), - AddressSpace::Heap, - false, - )? - .into_int_value(); - - let result = context - .build_call( - self.inner_function(context), - crate::polkavm::utils::external_call_arguments( - context, - abi_data.as_basic_value_enum(), - address, - vec![], - None, - ) - .as_slice(), - "contract_call_external", - ) - .expect("IntrinsicFunction always returns a flag"); - - let result_abi_data = context - .builder() - .build_extract_value( - result.into_struct_value(), - 0, - "contract_call_external_result_abi_data", - ) - .expect("Always exists"); - let result_abi_data_pointer = Pointer::new( - context.byte_type(), - AddressSpace::Generic, - result_abi_data.into_pointer_value(), - ); - let result_abi_data_casted = result_abi_data_pointer.cast(context.field_type()); - - let result_status_code_boolean = context - .builder() - .build_extract_value( - result.into_struct_value(), - 1, - "contract_call_external_result_status_code_boolean", - ) - .expect("Always exists"); - let result_status_code = context.builder().build_int_z_extend_or_bit_cast( - result_status_code_boolean.into_int_value(), - context.field_type(), - "contract_call_external_result_status_code", - )?; - context.build_store(status_code_result_pointer, result_status_code); - - let source = result_abi_data_casted; - - let destination = Pointer::new_with_offset( - context, - AddressSpace::Heap, - context.byte_type(), - output_offset, - "contract_call_destination", - ); - - context.build_memcpy_return_data( - context.intrinsics().memory_copy_from_generic, - destination, - source, - output_length, - "contract_call_memcpy_from_child", - ); - - context.write_abi_pointer( - result_abi_data_pointer, - crate::polkavm::GLOBAL_RETURN_DATA_POINTER, - ); - context.write_abi_data_size( - result_abi_data_pointer, - crate::polkavm::GLOBAL_RETURN_DATA_SIZE, - ); - */ - context.build_unconditional_branch(context.current_function().borrow().return_block()); - - context.set_basic_block(context.current_function().borrow().return_block()); - let status_code_result = - context.build_load(status_code_result_pointer, "contract_call_status_code")?; - context.build_return(Some(&status_code_result)); - - Ok(()) - } -} diff --git a/crates/llvm-context/src/polkavm/context/function/runtime/entry.rs b/crates/llvm-context/src/polkavm/context/function/runtime/entry.rs index 1721cbe1..2f876898 100644 --- a/crates/llvm-context/src/polkavm/context/function/runtime/entry.rs +++ b/crates/llvm-context/src/polkavm/context/function/runtime/entry.rs @@ -153,7 +153,7 @@ impl Entry { context.integer_const(crate::polkavm::XLEN, Self::MAX_CALLDATA_SIZE as u64), )?; context.build_runtime_call( - runtime_api::INPUT, + runtime_api::imports::INPUT, &[input_pointer_casted.into(), length_pointer_casted.into()], ); @@ -215,11 +215,11 @@ impl Entry { .ok_or_else(|| anyhow::anyhow!("Contract runtime code not found"))?; context.set_basic_block(deploy_code_call_block); - context.build_invoke(deploy_code.borrow().declaration, &[], "deploy_code_call"); + context.build_call(deploy_code.borrow().declaration, &[], "deploy_code_call"); context.build_unconditional_branch(context.current_function().borrow().return_block()); context.set_basic_block(runtime_code_call_block); - context.build_invoke(runtime_code.borrow().declaration, &[], "runtime_code_call"); + context.build_call(runtime_code.borrow().declaration, &[], "runtime_code_call"); context.build_unconditional_branch(context.current_function().borrow().return_block()); Ok(()) @@ -235,7 +235,7 @@ where let entry_function_type = context.function_type(entry_arguments, 0, false); context.add_function(Runtime::FUNCTION_ENTRY, entry_function_type, 0, None)?; - for symbol in runtime_api::EXPORTS { + for symbol in runtime_api::exports::EXPORTS { context.declare_extern_function(symbol)?; } @@ -258,7 +258,7 @@ where true, ); - context.set_current_function(runtime_api::DEPLOY)?; + context.set_current_function(runtime_api::exports::DEPLOY)?; context.set_basic_block(context.current_function().borrow().entry_block()); assert!(context @@ -268,7 +268,7 @@ where context.set_basic_block(context.current_function().borrow().return_block); context.build_unreachable(); - context.set_current_function(runtime_api::CALL)?; + context.set_current_function(runtime_api::exports::CALL)?; context.set_basic_block(context.current_function().borrow().entry_block()); assert!(context diff --git a/crates/llvm-context/src/polkavm/context/function/runtime/mod.rs b/crates/llvm-context/src/polkavm/context/function/runtime/mod.rs index fee5a23d..90505a94 100644 --- a/crates/llvm-context/src/polkavm/context/function/runtime/mod.rs +++ b/crates/llvm-context/src/polkavm/context/function/runtime/mod.rs @@ -1,17 +1,10 @@ //! The front-end runtime functions. -pub mod default_call; pub mod deploy_code; pub mod entry; pub mod runtime_code; use crate::polkavm::context::address_space::AddressSpace; -use crate::polkavm::context::function::declaration::Declaration as FunctionDeclaration; -use crate::polkavm::context::Context; -use crate::polkavm::Dependency; -use crate::polkavm::WriteLLVM; - -use self::default_call::DefaultCall; /// The front-end runtime functions. #[derive(Debug, Clone)] @@ -35,40 +28,4 @@ impl Runtime { pub fn new(_address_space: AddressSpace) -> Self { Self { _address_space } } - - /// Returns the corresponding runtime function. - pub fn default_call<'ctx, D>( - context: &Context<'ctx, D>, - call_function: FunctionDeclaration<'ctx>, - ) -> FunctionDeclaration<'ctx> - where - D: Dependency + Clone, - { - context - .get_function(DefaultCall::name(call_function).as_str()) - .expect("Always exists") - .borrow() - .declaration() - } -} - -impl WriteLLVM for Runtime -where - D: Dependency + Clone, -{ - fn declare(&mut self, context: &mut Context) -> anyhow::Result<()> { - //DefaultCall::new(context.llvm_runtime().far_call).declare(context)?; - DefaultCall::new(context.llvm_runtime().static_call).declare(context)?; - DefaultCall::new(context.llvm_runtime().delegate_call).declare(context)?; - - Ok(()) - } - - fn into_llvm(self, context: &mut Context) -> anyhow::Result<()> { - //DefaultCall::new(context.llvm_runtime().far_call).into_llvm(context)?; - DefaultCall::new(context.llvm_runtime().static_call).into_llvm(context)?; - DefaultCall::new(context.llvm_runtime().delegate_call).into_llvm(context)?; - - Ok(()) - } } diff --git a/crates/llvm-context/src/polkavm/context/mod.rs b/crates/llvm-context/src/polkavm/context/mod.rs index a5af6a67..b4aaacc9 100644 --- a/crates/llvm-context/src/polkavm/context/mod.rs +++ b/crates/llvm-context/src/polkavm/context/mod.rs @@ -141,7 +141,7 @@ where ) .expect("the PolkaVM guest API module should be linkable"); - for export in runtime_api::EXPORTS { + for export in runtime_api::exports::EXPORTS { module .get_function(export) .expect("should be declared") @@ -151,7 +151,7 @@ where ); } - for import in runtime_api::IMPORTS { + for import in runtime_api::imports::IMPORTS { module .get_function(import) .expect("should be declared") @@ -433,8 +433,6 @@ where let entry_block = self.llvm.append_basic_block(value, "entry"); let return_block = self.llvm.append_basic_block(value, "return"); - value.set_personality_function(self.llvm_runtime.personality.value); - let r#return = match return_values_length { 0 => FunctionReturn::none(), 1 => { @@ -705,7 +703,7 @@ where .build_stack_parameter(revive_common::BIT_LENGTH_WORD, "storage_value_pointer"); self.build_runtime_call( - runtime_api::GET_STORAGE, + runtime_api::imports::GET_STORAGE, &[ storage_key_pointer_casted.into(), self.integer_const(crate::polkavm::XLEN, 32).into(), @@ -809,7 +807,7 @@ where .build_store(storage_value_pointer.value, storage_value_value)?; self.build_runtime_call( - runtime_api::SET_STORAGE, + runtime_api::imports::SET_STORAGE, &[ storage_key_pointer_casted.into(), self.integer_const(crate::polkavm::XLEN, 32).into(), @@ -957,106 +955,6 @@ where call_site_value.try_as_basic_value().left() } - /// Builds an invoke. - /// Is defaulted to a call if there is no global exception handler. - pub fn build_invoke( - &self, - function: FunctionDeclaration<'ctx>, - arguments: &[inkwell::values::BasicValueEnum<'ctx>], - name: &str, - ) -> Option> { - if !self - .functions - .contains_key(Function::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER) - { - return self.build_call(function, arguments, name); - } - - let return_pointer = if let Some(r#type) = function.r#type.get_return_type() { - let pointer = self.build_alloca(r#type, "invoke_return_pointer"); - self.build_store(pointer, r#type.const_zero()).unwrap(); - Some(pointer) - } else { - None - }; - - let success_block = self.append_basic_block("invoke_success_block"); - let catch_block = self.append_basic_block("invoke_catch_block"); - let current_block = self.basic_block(); - - self.set_basic_block(catch_block); - let landing_pad_type = self.structure_type(&[ - self.llvm() - .ptr_type(AddressSpace::Stack.into()) - .as_basic_type_enum(), - self.integer_type(revive_common::BIT_LENGTH_X32) - .as_basic_type_enum(), - ]); - self.builder - .build_landing_pad( - landing_pad_type, - self.llvm_runtime.personality.value, - &[self - .llvm() - .ptr_type(AddressSpace::Stack.into()) - .const_zero() - .as_basic_value_enum()], - false, - "invoke_catch_landing", - ) - .unwrap(); - crate::polkavm::utils::throw(self); - - self.set_basic_block(current_block); - let call_site_value = self - .builder - .build_indirect_invoke( - function.r#type, - function.value.as_global_value().as_pointer_value(), - arguments, - success_block, - catch_block, - name, - ) - .unwrap(); - self.modify_call_site_value(arguments, call_site_value, function); - - self.set_basic_block(success_block); - if let (Some(return_pointer), Some(mut return_value)) = - (return_pointer, call_site_value.try_as_basic_value().left()) - { - if let Some(return_type) = function.r#type.get_return_type() { - if return_type.is_pointer_type() { - return_value = self - .builder() - .build_int_to_ptr( - return_value.into_int_value(), - return_type.into_pointer_type(), - format!("{name}_invoke_return_pointer_casted").as_str(), - ) - .unwrap() - .as_basic_value_enum(); - } - } - self.build_store(return_pointer, return_value).unwrap(); - } - return_pointer.map(|pointer| self.build_load(pointer, "invoke_result").unwrap()) - } - - /// Builds an invoke of local call covered with an exception handler. - /// Yul does not the exception handling, so the user can declare a special handling function - /// called (see constant `ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER`. If the enclosed function - /// panics, the control flow will be transferred to the exception handler. - pub fn build_invoke_near_call_abi( - &self, - _function: FunctionDeclaration<'ctx>, - _arguments: Vec>, - _name: &str, - ) -> Option> { - unimplemented!() - } - - /// Builds a memory copy call. /// Sets the alignment to `1`, since all non-stack memory pages have such alignment. pub fn build_memcpy( &self, @@ -1132,7 +1030,7 @@ where )?; self.build_runtime_call( - runtime_api::RETURN, + runtime_api::imports::RETURN, &[flags.into(), offset_pointer.into(), length_pointer.into()], ); self.build_unreachable(); @@ -1396,6 +1294,13 @@ where self.llvm.custom_width_int_type(crate::polkavm::XLEN as u32) } + /// Returns the register witdh sized type. + pub fn sentinel_pointer(&self) -> inkwell::values::PointerValue<'ctx> { + self.xlen_type() + .const_all_ones() + .const_to_pointer(self.llvm().ptr_type(Default::default())) + } + /// Returns the runtime value width sized type. pub fn value_type(&self) -> inkwell::types::IntType<'ctx> { self.llvm diff --git a/crates/llvm-context/src/polkavm/evm/call.rs b/crates/llvm-context/src/polkavm/evm/call.rs index 878dd4f3..f7153242 100644 --- a/crates/llvm-context/src/polkavm/evm/call.rs +++ b/crates/llvm-context/src/polkavm/evm/call.rs @@ -3,17 +3,104 @@ use inkwell::values::BasicValue; use crate::polkavm::context::argument::Argument; -use crate::polkavm::context::function::declaration::Declaration as FunctionDeclaration; use crate::polkavm::context::Context; use crate::polkavm::Dependency; +use crate::polkavm_const::runtime_api; + +static STATIC_CALL_FLAG: u32 = 0b0001_0000; /// Translates a contract call. -/// If the `simulation_address` is specified, the call is substituted with another instruction -/// according to the specification. +/// +/// If the `simulation_address` is specified, the call is +/// substituted with another instruction according to the specification. #[allow(clippy::too_many_arguments)] -pub fn default<'ctx, D>( +pub fn call<'ctx, D>( + context: &mut Context<'ctx, D>, + gas: inkwell::values::IntValue<'ctx>, + address: inkwell::values::IntValue<'ctx>, + value: Option>, + input_offset: inkwell::values::IntValue<'ctx>, + input_length: inkwell::values::IntValue<'ctx>, + output_offset: inkwell::values::IntValue<'ctx>, + output_length: inkwell::values::IntValue<'ctx>, + _constants: Vec>, + static_call: bool, +) -> anyhow::Result> +where + D: Dependency + Clone, +{ + let address_pointer = context.build_alloca(context.word_type(), "address_ptr"); + context.build_store(address_pointer, address)?; + + let value_pointer = if let Some(value) = value { + let value_pointer = context.build_alloca(context.value_type(), "value"); + context.build_store(value_pointer, value)?; + value_pointer.value + } else { + context.sentinel_pointer() + }; + + let input_offset = context.safe_truncate_int_to_xlen(input_offset)?; + let input_length = context.safe_truncate_int_to_xlen(input_length)?; + let output_offset = context.safe_truncate_int_to_xlen(output_offset)?; + let output_length = context.safe_truncate_int_to_xlen(output_length)?; + + let gas = context + .builder() + .build_int_truncate(gas, context.integer_type(64), "gas")?; + + let flags = if static_call { STATIC_CALL_FLAG } else { 0 }; + + let input_pointer = context.build_heap_gep(input_offset, input_length)?; + let output_pointer = context.build_heap_gep(output_offset, output_length)?; + + let output_length_pointer = context.get_global(crate::polkavm::GLOBAL_RETURN_DATA_SIZE)?; + context.build_store(output_length_pointer.into(), output_length)?; + + let argument_pointer = pallet_contracts_pvm_llapi::calling_convention::Spill::new( + context.builder(), + pallet_contracts_pvm_llapi::calling_convention::call(context.llvm()), + "call_arguments", + )? + .next(context.xlen_type().const_int(flags as u64, false))? + .next(address_pointer.value)? + .next(gas)? + .skip() + .next(context.sentinel_pointer())? + .next(value_pointer)? + .next(input_pointer.value)? + .next(input_length)? + .next(output_pointer.value)? + .next(output_length_pointer.value)? + .done(); + + let name = runtime_api::imports::CALL; + let arguments = context.builder().build_ptr_to_int( + argument_pointer, + context.xlen_type(), + "argument_pointer", + )?; + let success = context + .build_runtime_call(name, &[arguments.into()]) + .unwrap_or_else(|| panic!("{name} should return a value")) + .into_int_value(); + + let is_success = context.builder().build_int_compare( + inkwell::IntPredicate::EQ, + success, + context.xlen_type().const_zero(), + "is_success", + )?; + + Ok(context + .builder() + .build_int_z_extend(is_success, context.word_type(), "success")? + .as_basic_value_enum()) +} + +#[allow(clippy::too_many_arguments)] +pub fn delegate_call<'ctx, D>( _context: &mut Context<'ctx, D>, - _function: FunctionDeclaration<'ctx>, _gas: inkwell::values::IntValue<'ctx>, _address: inkwell::values::IntValue<'ctx>, _value: Option>, @@ -26,68 +113,7 @@ pub fn default<'ctx, D>( where D: Dependency + Clone, { - todo!(); - - /* - let ordinary_block = context.append_basic_block("contract_call_ordinary_block"); - let join_block = context.append_basic_block("contract_call_join_block"); - - let result_pointer = context.build_alloca(context.field_type(), "contract_call_result_pointer"); - context.build_store(result_pointer, context.field_const(0)); - - context.builder().build_switch( - address, - ordinary_block, - &[( - context.field_const(zkevm_opcode_defs::ADDRESS_IDENTITY.into()), - identity_block, - )], - )?; - - { - context.set_basic_block(identity_block); - let result = identity(context, output_offset, input_offset, output_length)?; - context.build_store(result_pointer, result); - context.build_unconditional_branch(join_block); - } - - context.set_basic_block(ordinary_block); - let result = if let Some(value) = value { - default_wrapped( - context, - function, - gas, - value, - address, - input_offset, - input_length, - output_offset, - output_length, - )? - } else { - let function = Runtime::default_call(context, function); - context - .build_call( - function, - &[ - gas.as_basic_value_enum(), - address.as_basic_value_enum(), - input_offset.as_basic_value_enum(), - input_length.as_basic_value_enum(), - output_offset.as_basic_value_enum(), - output_length.as_basic_value_enum(), - ], - "default_call", - ) - .expect("Always exists") - }; - context.build_store(result_pointer, result); - context.build_unconditional_branch(join_block); - - context.set_basic_block(join_block); - let result = context.build_load(result_pointer, "contract_call_result"); - Ok(result) - */ + todo!() } /// Translates the Yul `linkersymbol` instruction. diff --git a/crates/llvm-context/src/polkavm/evm/context.rs b/crates/llvm-context/src/polkavm/evm/context.rs index c1a0acc8..e270da46 100644 --- a/crates/llvm-context/src/polkavm/evm/context.rs +++ b/crates/llvm-context/src/polkavm/evm/context.rs @@ -58,7 +58,7 @@ where "block_timestamp_output", ); context.build_runtime_call( - runtime_api::BLOCK_NUMBER, + runtime_api::imports::BLOCK_NUMBER, &[ output_pointer.to_int(context).into(), output_length_pointer.to_int(context).into(), @@ -83,7 +83,7 @@ where "block_timestamp_output", ); context.build_runtime_call( - runtime_api::NOW, + runtime_api::imports::NOW, &[ output_pointer.to_int(context).into(), output_length_pointer.to_int(context).into(), @@ -174,7 +174,7 @@ where let (output_pointer, output_length_pointer) = context.build_stack_parameter(revive_common::BIT_LENGTH_ETH_ADDRESS, "address_output"); context.build_runtime_call( - runtime_api::ADDRESS, + runtime_api::imports::ADDRESS, &[ output_pointer.to_int(context).into(), output_length_pointer.to_int(context).into(), @@ -197,7 +197,7 @@ where let (output_pointer, output_length_pointer) = context.build_stack_parameter(revive_common::BIT_LENGTH_ETH_ADDRESS, "caller_output"); context.build_runtime_call( - runtime_api::CALLER, + runtime_api::imports::CALLER, &[ output_pointer.to_int(context).into(), output_length_pointer.to_int(context).into(), diff --git a/crates/llvm-context/src/polkavm/evm/create.rs b/crates/llvm-context/src/polkavm/evm/create.rs index 5a52b000..8508e04b 100644 --- a/crates/llvm-context/src/polkavm/evm/create.rs +++ b/crates/llvm-context/src/polkavm/evm/create.rs @@ -56,11 +56,7 @@ where let (address_pointer, address_length_pointer) = context.build_stack_parameter(revive_common::BIT_LENGTH_ETH_ADDRESS, "address_pointer"); - - let sentinel = context - .xlen_type() - .const_all_ones() - .const_to_pointer(context.llvm().ptr_type(Default::default())); + context.build_store(address_pointer, context.word_const(0))?; let argument_pointer = pallet_contracts_pvm_llapi::calling_convention::Spill::new( context.builder(), @@ -70,14 +66,14 @@ where .next(code_hash_pointer.value)? .skip() .skip() - .next(sentinel)? + .next(context.sentinel_pointer())? .next(value_pointer.value)? .next(input_data_pointer.value)? .next(input_length)? .next(address_pointer.value)? .next(address_length_pointer.value)? - .next(sentinel)? - .next(sentinel)? + .next(context.sentinel_pointer())? + .next(context.sentinel_pointer())? .next(salt_pointer.value)? .next( context @@ -86,14 +82,13 @@ where )? .done(); - context.builder().build_direct_call( - context.runtime_api_method(runtime_api::INSTANTIATE), + context.build_runtime_call( + runtime_api::imports::INSTANTIATE, &[context .builder() .build_ptr_to_int(argument_pointer, context.xlen_type(), "argument_pointer")? .into()], - "create2", - )?; + ); context.build_load_word( address_pointer, diff --git a/crates/llvm-context/src/polkavm/evm/crypto.rs b/crates/llvm-context/src/polkavm/evm/crypto.rs index bb1d797b..3e83ea68 100644 --- a/crates/llvm-context/src/polkavm/evm/crypto.rs +++ b/crates/llvm-context/src/polkavm/evm/crypto.rs @@ -19,7 +19,7 @@ where let output_pointer = context.build_alloca(context.word_type(), "output_pointer"); context.build_runtime_call( - runtime_api::HASH_KECCAK_256, + runtime_api::imports::HASH_KECCAK_256, &[ input_pointer.to_int(context).into(), length_casted.into(), diff --git a/crates/llvm-context/src/polkavm/evm/ether_gas.rs b/crates/llvm-context/src/polkavm/evm/ether_gas.rs index 96d9c4d0..6949cbf7 100644 --- a/crates/llvm-context/src/polkavm/evm/ether_gas.rs +++ b/crates/llvm-context/src/polkavm/evm/ether_gas.rs @@ -26,7 +26,7 @@ where let (output_pointer, output_length_pointer) = context.build_stack_parameter(revive_common::BIT_LENGTH_VALUE, "value_transferred_output"); context.build_runtime_call( - runtime_api::VALUE_TRANSFERRED, + runtime_api::imports::VALUE_TRANSFERRED, &[ output_pointer.to_int(context).into(), output_length_pointer.to_int(context).into(), diff --git a/crates/llvm-context/src/polkavm/evm/event.rs b/crates/llvm-context/src/polkavm/evm/event.rs index 30e68b03..37ef12ff 100644 --- a/crates/llvm-context/src/polkavm/evm/event.rs +++ b/crates/llvm-context/src/polkavm/evm/event.rs @@ -75,7 +75,7 @@ where ] }; - let _ = context.build_runtime_call(runtime_api::DEPOSIT_EVENT, &arguments); + let _ = context.build_runtime_call(runtime_api::imports::DEPOSIT_EVENT, &arguments); Ok(()) } diff --git a/crates/llvm-context/src/polkavm/evm/ext_code.rs b/crates/llvm-context/src/polkavm/evm/ext_code.rs index ae619abb..3a8d251d 100644 --- a/crates/llvm-context/src/polkavm/evm/ext_code.rs +++ b/crates/llvm-context/src/polkavm/evm/ext_code.rs @@ -23,8 +23,11 @@ where "address_pointer", )?; let value = context - .build_runtime_call(runtime_api::CODE_SIZE, &[address_pointer_casted.into()]) - .unwrap_or_else(|| panic!("{} should return a value", runtime_api::CODE_SIZE)) + .build_runtime_call( + runtime_api::imports::CODE_SIZE, + &[address_pointer_casted.into()], + ) + .unwrap_or_else(|| panic!("{} should return a value", runtime_api::imports::CODE_SIZE)) .into_int_value(); Ok(context diff --git a/crates/llvm-context/src/polkavm/evm/return_data.rs b/crates/llvm-context/src/polkavm/evm/return_data.rs index 3090bb8c..7c7f97ce 100644 --- a/crates/llvm-context/src/polkavm/evm/return_data.rs +++ b/crates/llvm-context/src/polkavm/evm/return_data.rs @@ -4,6 +4,7 @@ use inkwell::values::BasicValue; use crate::polkavm::context::Context; use crate::polkavm::Dependency; +use crate::polkavm_const::runtime_api; /// Translates the return data size. pub fn size<'ctx, D>( @@ -38,54 +39,16 @@ where let destination_offset = context.safe_truncate_int_to_xlen(destination_offset)?; let size = context.safe_truncate_int_to_xlen(size)?; - let block_copy = context.append_basic_block("copy_block"); - let block_trap = context.append_basic_block("trap_block"); - let block_check_out_of_bounds = context.append_basic_block("check_out_of_bounds_block"); - let is_overflow = context.builder().build_int_compare( - inkwell::IntPredicate::UGT, - source_offset, - context.builder().build_int_sub( - context.xlen_type().const_all_ones(), - size, - "offset_plus_size_max_value", - )?, - "is_returndata_size_out_of_bounds", + let destination_offset = context.builder().build_ptr_to_int( + context.build_heap_gep(destination_offset, size)?.value, + context.xlen_type(), + "destination_offset", )?; - context.build_conditional_branch(is_overflow, block_trap, block_check_out_of_bounds)?; - context.set_basic_block(block_check_out_of_bounds); - let is_out_of_bounds = context.builder().build_int_compare( - inkwell::IntPredicate::UGT, - context.builder().build_int_add( - source_offset, - context - .get_global_value(crate::polkavm::GLOBAL_RETURN_DATA_SIZE)? - .into_int_value(), - "returndata_end_pointer", - )?, - context - .xlen_type() - .const_int(crate::PolkaVMEntryFunction::MAX_CALLDATA_SIZE as u64, false), - "is_return_data_copy_overflow", - )?; - context.build_conditional_branch(is_out_of_bounds, block_trap, block_copy)?; - - context.set_basic_block(block_trap); - context.build_call(context.intrinsics().trap, &[], "invalid_returndata_copy"); - context.build_unreachable(); + context.build_runtime_call( + runtime_api::imports::RETURNDATACOPY, + &[destination_offset.into(), source_offset.into(), size.into()], + ); - context.set_basic_block(block_copy); - context.build_memcpy( - context.build_heap_gep(destination_offset, size)?, - context.build_gep( - context - .get_global(crate::polkavm::GLOBAL_RETURN_DATA_POINTER)? - .into(), - &[context.xlen_type().const_zero(), source_offset], - context.byte_type(), - "source_offset_gep", - ), - size, - "return_data_copy_memcpy_from_return_data", - ) + Ok(()) } diff --git a/crates/llvm-context/src/polkavm/utils.rs b/crates/llvm-context/src/polkavm/utils.rs index 108951e2..94f98397 100644 --- a/crates/llvm-context/src/polkavm/utils.rs +++ b/crates/llvm-context/src/polkavm/utils.rs @@ -3,7 +3,6 @@ use inkwell::values::BasicValue; use crate::polkavm::context::address_space::AddressSpace; -use crate::polkavm::context::function::llvm_runtime::LLVMRuntime; use crate::polkavm::context::Context; use crate::polkavm::Dependency; @@ -40,23 +39,6 @@ where Ok(result.into_int_value()) } -/// Generates an exception. -pub fn throw(context: &Context) -where - D: Dependency + Clone, -{ - context.build_call( - context.llvm_runtime().cxa_throw, - &[context - .llvm() - .ptr_type(AddressSpace::Stack.into()) - .get_undef() - .as_basic_value_enum(); 3], - LLVMRuntime::FUNCTION_CXA_THROW, - ); - context.build_unreachable(); -} - /// Returns the full list of arguments for an external call. /// Performs the extra ABI data padding and adds the mimic call extra argument. pub fn external_call_arguments<'ctx, D>( diff --git a/crates/pallet-contracts-pvm-llapi/src/calling_convention.rs b/crates/pallet-contracts-pvm-llapi/src/calling_convention.rs index b73ffc41..df3472a0 100644 --- a/crates/pallet-contracts-pvm-llapi/src/calling_convention.rs +++ b/crates/pallet-contracts-pvm-llapi/src/calling_convention.rs @@ -5,16 +5,16 @@ use inkwell::{ values::{BasicValue, PointerValue}, }; -pub struct Spill<'ctx> { +pub struct Spill<'a, 'ctx> { pointer: PointerValue<'ctx>, - builder: &'ctx Builder<'ctx>, + builder: &'a Builder<'ctx>, r#type: StructType<'ctx>, current_field: u32, } -impl<'ctx> Spill<'ctx> { +impl<'a, 'ctx> Spill<'a, 'ctx> { pub fn new( - builder: &'ctx Builder<'ctx>, + builder: &'a Builder<'ctx>, r#type: StructType<'ctx>, name: &str, ) -> anyhow::Result { @@ -88,3 +88,31 @@ pub fn instantiate(context: &Context) -> StructType { true, ) } + +pub fn call(context: &Context) -> StructType { + context.struct_type( + &[ + // flags: u32, + context.i32_type().as_basic_type_enum(), + // address_ptr: + context.ptr_type(Default::default()).as_basic_type_enum(), + // ref_time_limit: u64, + context.i64_type().as_basic_type_enum(), + // proof_size_limit: u64, + context.i64_type().as_basic_type_enum(), + // deposit_ptr: u32, + context.ptr_type(Default::default()).as_basic_type_enum(), + // value_ptr: u32, + context.ptr_type(Default::default()).as_basic_type_enum(), + // input_data_ptr: u32, + context.ptr_type(Default::default()).as_basic_type_enum(), + // input_data_len: u32, + context.i32_type().as_basic_type_enum(), + // output_ptr: u32, + context.ptr_type(Default::default()).as_basic_type_enum(), + // output_len_ptr: u32, + context.ptr_type(Default::default()).as_basic_type_enum(), + ], + true, + ) +} diff --git a/crates/pallet-contracts-pvm-llapi/src/polkavm_guest.c b/crates/pallet-contracts-pvm-llapi/src/polkavm_guest.c index 1ce3b01c..f0c0f08b 100644 --- a/crates/pallet-contracts-pvm-llapi/src/polkavm_guest.c +++ b/crates/pallet-contracts-pvm-llapi/src/polkavm_guest.c @@ -63,6 +63,8 @@ POLKAVM_IMPORT(void, input, uint32_t, uint32_t) POLKAVM_IMPORT(void, seal_return, uint32_t, uint32_t, uint32_t) +POLKAVM_IMPORT(void, returndatacopy, uint32_t, uint32_t, uint32_t) + POLKAVM_IMPORT(void, value_transferred, uint32_t, uint32_t) POLKAVM_IMPORT(uint32_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t) diff --git a/crates/solidity/src/evmla/assembly/mod.rs b/crates/solidity/src/evmla/assembly/mod.rs index b614d01b..b13deb2d 100644 --- a/crates/solidity/src/evmla/assembly/mod.rs +++ b/crates/solidity/src/evmla/assembly/mod.rs @@ -191,11 +191,6 @@ where let mut entry = revive_llvm_context::PolkaVMEntryFunction::default(); entry.declare(context)?; - let mut runtime = revive_llvm_context::PolkaVMRuntime::new( - revive_llvm_context::PolkaVMAddressSpace::Heap, - ); - runtime.declare(context)?; - revive_llvm_context::PolkaVMDeployCodeFunction::new( revive_llvm_context::PolkaVMDummyLLVMWritable::default(), ) @@ -207,8 +202,6 @@ where entry.into_llvm(context)?; - runtime.into_llvm(context)?; - Ok(()) } diff --git a/crates/solidity/src/evmla/ethereal_ir/entry_link.rs b/crates/solidity/src/evmla/ethereal_ir/entry_link.rs index ecafd254..075148d4 100644 --- a/crates/solidity/src/evmla/ethereal_ir/entry_link.rs +++ b/crates/solidity/src/evmla/ethereal_ir/entry_link.rs @@ -37,7 +37,7 @@ where .integer_type(revive_common::BIT_LENGTH_BOOLEAN) .const_int(0, false), }; - context.build_invoke( + context.build_call( target, &[is_deploy_code.as_basic_value_enum()], format!("call_link_{}", EtherealIR::DEFAULT_ENTRY_FUNCTION_NAME).as_str(), diff --git a/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs b/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs index 297eca4e..917eb765 100644 --- a/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs +++ b/crates/solidity/src/evmla/ethereal_ir/function/block/element/mod.rs @@ -1026,19 +1026,16 @@ where InstructionName::CALL => { let mut arguments = self.pop_arguments_llvm(context); - let _gas = arguments.remove(0).into_int_value(); - let _address = arguments.remove(0).into_int_value(); - let _value = arguments.remove(0).into_int_value(); - let _input_offset = arguments.remove(0).into_int_value(); - let _input_size = arguments.remove(0).into_int_value(); - let _output_offset = arguments.remove(0).into_int_value(); - let _output_size = arguments.remove(0).into_int_value(); - - todo!() - /* - revive_llvm_context::polkavm_evm_call::default( + let gas = arguments.remove(0).into_int_value(); + let address = arguments.remove(0).into_int_value(); + let value = arguments.remove(0).into_int_value(); + let input_offset = arguments.remove(0).into_int_value(); + let input_size = arguments.remove(0).into_int_value(); + let output_offset = arguments.remove(0).into_int_value(); + let output_size = arguments.remove(0).into_int_value(); + + revive_llvm_context::polkavm_evm_call::call( context, - context.llvm_runtime().far_call, gas, address, Some(value), @@ -1047,9 +1044,9 @@ where output_offset, output_size, vec![], + false, ) .map(Some) - */ } InstructionName::STATICCALL => { let mut arguments = self.pop_arguments_llvm(context); @@ -1061,9 +1058,8 @@ where let output_offset = arguments.remove(0).into_int_value(); let output_size = arguments.remove(0).into_int_value(); - revive_llvm_context::polkavm_evm_call::default( + revive_llvm_context::polkavm_evm_call::call( context, - context.llvm_runtime().static_call, gas, address, None, @@ -1072,6 +1068,7 @@ where output_offset, output_size, vec![], + true, ) .map(Some) } @@ -1085,9 +1082,8 @@ where let output_offset = arguments.remove(0).into_int_value(); let output_size = arguments.remove(0).into_int_value(); - revive_llvm_context::polkavm_evm_call::default( + revive_llvm_context::polkavm_evm_call::delegate_call( context, - context.llvm_runtime().delegate_call, gas, address, None, diff --git a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs index 19583c4d..772e10d8 100644 --- a/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs +++ b/crates/solidity/src/yul/parser/statement/expression/function_call/mod.rs @@ -155,7 +155,7 @@ impl FunctionCall { ); } - let return_value = context.build_invoke( + let return_value = context.build_call( function.borrow().declaration(), values.as_slice(), format!("{name}_call").as_str(), @@ -731,24 +731,21 @@ impl FunctionCall { Name::Call => { let arguments = self.pop_arguments::(context)?; - let _gas = arguments[0].value.into_int_value(); - let _address = arguments[1].value.into_int_value(); - let _value = arguments[2].value.into_int_value(); - let _input_offset = arguments[3].value.into_int_value(); - let _input_size = arguments[4].value.into_int_value(); - let _output_offset = arguments[5].value.into_int_value(); - let _output_size = arguments[6].value.into_int_value(); + let gas = arguments[0].value.into_int_value(); + let address = arguments[1].value.into_int_value(); + let value = arguments[2].value.into_int_value(); + let input_offset = arguments[3].value.into_int_value(); + let input_size = arguments[4].value.into_int_value(); + let output_offset = arguments[5].value.into_int_value(); + let output_size = arguments[6].value.into_int_value(); - let _simulation_address: Vec> = arguments + let simulation_address: Vec> = arguments .into_iter() .map(|mut argument| argument.constant.take()) .collect(); - todo!() - /* - revive_llvm_context::polkavm_evm_call::default( + revive_llvm_context::polkavm_evm_call::call( context, - context.llvm_runtime().far_call, gas, address, Some(value), @@ -757,9 +754,9 @@ impl FunctionCall { output_offset, output_size, simulation_address, + false, ) .map(Some) - */ } Name::StaticCall => { let arguments = self.pop_arguments::(context)?; @@ -776,9 +773,8 @@ impl FunctionCall { .map(|mut argument| argument.constant.take()) .collect(); - revive_llvm_context::polkavm_evm_call::default( + revive_llvm_context::polkavm_evm_call::call( context, - context.llvm_runtime().static_call, gas, address, None, @@ -787,6 +783,7 @@ impl FunctionCall { output_offset, output_size, simulation_address, + true, ) .map(Some) } @@ -805,9 +802,8 @@ impl FunctionCall { .map(|mut argument| argument.constant.take()) .collect(); - revive_llvm_context::polkavm_evm_call::default( + revive_llvm_context::polkavm_evm_call::delegate_call( context, - context.llvm_runtime().delegate_call, gas, address, None, diff --git a/crates/solidity/src/yul/parser/statement/object.rs b/crates/solidity/src/yul/parser/statement/object.rs index f0ff91b7..e49c98ee 100644 --- a/crates/solidity/src/yul/parser/statement/object.rs +++ b/crates/solidity/src/yul/parser/statement/object.rs @@ -186,11 +186,6 @@ where let mut entry = revive_llvm_context::PolkaVMEntryFunction::default(); entry.declare(context)?; - let mut runtime = revive_llvm_context::PolkaVMRuntime::new( - revive_llvm_context::PolkaVMAddressSpace::Heap, - ); - runtime.declare(context)?; - revive_llvm_context::PolkaVMDeployCodeFunction::new( revive_llvm_context::PolkaVMDummyLLVMWritable::default(), ) @@ -226,16 +221,8 @@ where revive_llvm_context::PolkaVMDeployCodeFunction::new(self.code).into_llvm(context)?; } - match self.inner_object { - Some(object) => { - object.into_llvm(context)?; - } - None => { - let runtime = revive_llvm_context::PolkaVMRuntime::new( - revive_llvm_context::PolkaVMAddressSpace::Heap, - ); - runtime.into_llvm(context)?; - } + if let Some(object) = self.inner_object { + object.into_llvm(context)?; } Ok(())