mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-15 19:41:06 +00:00
add simulated evm math opcode syscalls
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
@@ -46,7 +46,6 @@ use self::code_type::CodeType;
|
|||||||
use self::debug_info::DebugInfo;
|
use self::debug_info::DebugInfo;
|
||||||
use self::function::declaration::Declaration as FunctionDeclaration;
|
use self::function::declaration::Declaration as FunctionDeclaration;
|
||||||
use self::function::intrinsics::Intrinsics;
|
use self::function::intrinsics::Intrinsics;
|
||||||
use self::function::llvm_runtime::LLVMRuntime;
|
|
||||||
use self::function::r#return::Return as FunctionReturn;
|
use self::function::r#return::Return as FunctionReturn;
|
||||||
use self::function::runtime::revive::Exit;
|
use self::function::runtime::revive::Exit;
|
||||||
use self::function::runtime::revive::WordToPointer;
|
use self::function::runtime::revive::WordToPointer;
|
||||||
@@ -79,8 +78,6 @@ where
|
|||||||
globals: HashMap<String, Global<'ctx>>,
|
globals: HashMap<String, Global<'ctx>>,
|
||||||
/// The LLVM intrinsic functions, defined on the LLVM side.
|
/// The LLVM intrinsic functions, defined on the LLVM side.
|
||||||
intrinsics: Intrinsics<'ctx>,
|
intrinsics: Intrinsics<'ctx>,
|
||||||
/// The LLVM runtime functions, defined on the LLVM side.
|
|
||||||
llvm_runtime: LLVMRuntime<'ctx>,
|
|
||||||
/// The declared functions.
|
/// The declared functions.
|
||||||
functions: HashMap<String, Rc<RefCell<Function<'ctx>>>>,
|
functions: HashMap<String, Rc<RefCell<Function<'ctx>>>>,
|
||||||
/// The current active function.
|
/// The current active function.
|
||||||
@@ -122,16 +119,6 @@ where
|
|||||||
/// The loop stack default capacity.
|
/// The loop stack default capacity.
|
||||||
const LOOP_STACK_INITIAL_CAPACITY: usize = 16;
|
const LOOP_STACK_INITIAL_CAPACITY: usize = 16;
|
||||||
|
|
||||||
/// Link in the stdlib module.
|
|
||||||
fn link_stdlib_module(
|
|
||||||
llvm: &'ctx inkwell::context::Context,
|
|
||||||
module: &inkwell::module::Module<'ctx>,
|
|
||||||
) {
|
|
||||||
module
|
|
||||||
.link_in_module(revive_stdlib::module(llvm, "revive_stdlib").unwrap())
|
|
||||||
.expect("the stdlib module should be linkable");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Link in the PolkaVM imports module, containing imported functions,
|
/// Link in the PolkaVM imports module, containing imported functions,
|
||||||
/// and marking them as external (they need to be relocatable as too).
|
/// and marking them as external (they need to be relocatable as too).
|
||||||
fn link_polkavm_imports(
|
fn link_polkavm_imports(
|
||||||
@@ -215,7 +202,8 @@ where
|
|||||||
llvm: &'ctx inkwell::context::Context,
|
llvm: &'ctx inkwell::context::Context,
|
||||||
module: &inkwell::module::Module<'ctx>,
|
module: &inkwell::module::Module<'ctx>,
|
||||||
) {
|
) {
|
||||||
let source_module = revive_stdlib::module(llvm, "revive_stdlib").unwrap();
|
let source_module =
|
||||||
|
revive_runtime_api::polkavm_imports::module(llvm, "revive_runtime").unwrap();
|
||||||
let data_layout = source_module.get_data_layout();
|
let data_layout = source_module.get_data_layout();
|
||||||
module.set_data_layout(&data_layout);
|
module.set_data_layout(&data_layout);
|
||||||
}
|
}
|
||||||
@@ -233,7 +221,6 @@ where
|
|||||||
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
memory_config: SolcStandardJsonInputSettingsPolkaVMMemory,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::set_data_layout(llvm, &module);
|
Self::set_data_layout(llvm, &module);
|
||||||
Self::link_stdlib_module(llvm, &module);
|
|
||||||
Self::link_polkavm_imports(llvm, &module);
|
Self::link_polkavm_imports(llvm, &module);
|
||||||
Self::set_polkavm_stack_size(
|
Self::set_polkavm_stack_size(
|
||||||
llvm,
|
llvm,
|
||||||
@@ -245,7 +232,6 @@ where
|
|||||||
Self::set_module_flags(llvm, &module);
|
Self::set_module_flags(llvm, &module);
|
||||||
|
|
||||||
let intrinsics = Intrinsics::new(llvm, &module);
|
let intrinsics = Intrinsics::new(llvm, &module);
|
||||||
let llvm_runtime = LLVMRuntime::new(llvm, &module, &optimizer);
|
|
||||||
let debug_info = debug_config.emit_debug_info.then(|| {
|
let debug_info = debug_config.emit_debug_info.then(|| {
|
||||||
let debug_info = DebugInfo::new(&module);
|
let debug_info = DebugInfo::new(&module);
|
||||||
debug_info.initialize_module(llvm, &module);
|
debug_info.initialize_module(llvm, &module);
|
||||||
@@ -260,7 +246,6 @@ where
|
|||||||
code_type: None,
|
code_type: None,
|
||||||
globals: HashMap::with_capacity(Self::GLOBALS_HASHMAP_INITIAL_CAPACITY),
|
globals: HashMap::with_capacity(Self::GLOBALS_HASHMAP_INITIAL_CAPACITY),
|
||||||
intrinsics,
|
intrinsics,
|
||||||
llvm_runtime,
|
|
||||||
functions: HashMap::with_capacity(Self::FUNCTIONS_HASHMAP_INITIAL_CAPACITY),
|
functions: HashMap::with_capacity(Self::FUNCTIONS_HASHMAP_INITIAL_CAPACITY),
|
||||||
current_function: None,
|
current_function: None,
|
||||||
loop_stack: Vec::with_capacity(Self::LOOP_STACK_INITIAL_CAPACITY),
|
loop_stack: Vec::with_capacity(Self::LOOP_STACK_INITIAL_CAPACITY),
|
||||||
@@ -451,11 +436,6 @@ where
|
|||||||
&self.intrinsics
|
&self.intrinsics
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the LLVM runtime function collection reference.
|
|
||||||
pub fn llvm_runtime(&self) -> &LLVMRuntime<'ctx> {
|
|
||||||
&self.llvm_runtime
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Appends a function to the current module.
|
/// Appends a function to the current module.
|
||||||
pub fn add_function(
|
pub fn add_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
//! Translates the mathematical operations.
|
//! Translates the mathematical operations.
|
||||||
|
|
||||||
use inkwell::values::BasicValue;
|
|
||||||
|
|
||||||
use crate::polkavm::context::Context;
|
use crate::polkavm::context::Context;
|
||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
|
|
||||||
@@ -15,17 +13,26 @@ pub fn add_mod<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "addmod_result_pointer");
|
||||||
context.llvm_runtime().add_mod,
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_1");
|
||||||
&[
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "addmod_operand_2");
|
||||||
operand_1.as_basic_value_enum(),
|
let modulo_pointer =
|
||||||
operand_2.as_basic_value_enum(),
|
context.build_alloca_at_entry(context.word_type(), "addmod_modulo_operand");
|
||||||
modulo.as_basic_value_enum(),
|
|
||||||
],
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
"add_mod_call",
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
)
|
context.build_store(modulo_pointer, modulo)?;
|
||||||
.expect("Always exists"))
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
modulo_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::ADDMOD, arguments);
|
||||||
|
context.build_load(result_pointer, "addmod_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `mulmod` instruction.
|
/// Translates the `mulmod` instruction.
|
||||||
@@ -38,17 +45,26 @@ pub fn mul_mod<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "mulmod_result_pointer");
|
||||||
context.llvm_runtime().mul_mod,
|
let operand_1_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_1");
|
||||||
&[
|
let operand_2_pointer = context.build_alloca_at_entry(context.word_type(), "mulmod_operand_2");
|
||||||
operand_1.as_basic_value_enum(),
|
let modulo_pointer =
|
||||||
operand_2.as_basic_value_enum(),
|
context.build_alloca_at_entry(context.word_type(), "mulmod_modulo_operand");
|
||||||
modulo.as_basic_value_enum(),
|
|
||||||
],
|
context.build_store(operand_2_pointer, operand_2)?;
|
||||||
"mul_mod_call",
|
context.build_store(operand_1_pointer, operand_1)?;
|
||||||
)
|
context.build_store(modulo_pointer, modulo)?;
|
||||||
.expect("Always exists"))
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
operand_1_pointer.to_int(context).into(),
|
||||||
|
operand_2_pointer.to_int(context).into(),
|
||||||
|
modulo_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::MULMOD, arguments);
|
||||||
|
context.build_load(result_pointer, "addmod_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `exp` instruction.
|
/// Translates the `exp` instruction.
|
||||||
@@ -60,13 +76,22 @@ pub fn exponent<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer = context.build_alloca_at_entry(context.word_type(), "exp_result_pointer");
|
||||||
.build_call(
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "exp_value_pointer");
|
||||||
context.llvm_runtime().exp,
|
let exponent_pointer =
|
||||||
&[value.as_basic_value_enum(), exponent.as_basic_value_enum()],
|
context.build_alloca_at_entry(context.word_type(), "exp_exponent_pointer");
|
||||||
"exp_call",
|
|
||||||
)
|
context.build_store(value_pointer, value)?;
|
||||||
.expect("Always exists"))
|
context.build_store(exponent_pointer, exponent)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
value_pointer.to_int(context).into(),
|
||||||
|
exponent_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
|
||||||
|
context.build_load(result_pointer, "exponent_result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `signextend` instruction.
|
/// Translates the `signextend` instruction.
|
||||||
@@ -78,11 +103,20 @@ pub fn sign_extend<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let result_pointer =
|
||||||
.build_call(
|
context.build_alloca_at_entry(context.word_type(), "signext_result_pointer");
|
||||||
context.llvm_runtime().sign_extend,
|
let bytes_pointer = context.build_alloca_at_entry(context.word_type(), "bytes_pointer");
|
||||||
&[bytes.as_basic_value_enum(), value.as_basic_value_enum()],
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "signext_value_pointer");
|
||||||
"sign_extend_call",
|
|
||||||
)
|
context.build_store(bytes_pointer, bytes)?;
|
||||||
.expect("Always exists"))
|
context.build_store(value_pointer, value)?;
|
||||||
|
|
||||||
|
let arguments = &[
|
||||||
|
result_pointer.to_int(context).into(),
|
||||||
|
bytes_pointer.to_int(context).into(),
|
||||||
|
value_pointer.to_int(context).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::EXP, arguments);
|
||||||
|
context.build_load(result_pointer, "signext_mod_result")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,3 +104,19 @@ POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, ui
|
|||||||
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
|
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint64_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, div, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, sdiv, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, addmod, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, mulmod, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, mod, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, smod, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, exp, uint32_t, uint32_t, uint32_t);
|
||||||
|
|
||||||
|
POLKAVM_IMPORT(void, signext, uint32_t, uint32_t, uint32_t);
|
||||||
|
|||||||
@@ -68,9 +68,27 @@ pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
|||||||
|
|
||||||
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
|
pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
|
||||||
|
|
||||||
|
pub static DIV: &str = "div";
|
||||||
|
pub static SDIV: &str = "sdiv";
|
||||||
|
pub static ADDMOD: &str = "addmod";
|
||||||
|
pub static MULMOD: &str = "mulmod";
|
||||||
|
pub static MOD: &str = "mod";
|
||||||
|
pub static SMOD: &str = "smod";
|
||||||
|
pub static EXP: &str = "exp";
|
||||||
|
pub static SIGNEXT: &str = "signext";
|
||||||
|
|
||||||
/// All imported runtime API symbols.
|
/// All imported runtime API symbols.
|
||||||
/// Useful for configuring common attributes and linkage.
|
/// Useful for configuring common attributes and linkage.
|
||||||
pub static IMPORTS: [&str; 33] = [
|
pub static IMPORTS: [&str; 41] = [
|
||||||
|
DIV,
|
||||||
|
SDIV,
|
||||||
|
ADDMOD,
|
||||||
|
MULMOD,
|
||||||
|
MOD,
|
||||||
|
SMOD,
|
||||||
|
EXP,
|
||||||
|
SIGNEXT,
|
||||||
|
//
|
||||||
ADDRESS,
|
ADDRESS,
|
||||||
BALANCE,
|
BALANCE,
|
||||||
BALANCE_OF,
|
BALANCE_OF,
|
||||||
|
|||||||
Reference in New Issue
Block a user