From bb3b6ddb4122ea0524fecd3e591570d304f767b1 Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Thu, 3 Jul 2025 15:36:11 +0200 Subject: [PATCH] wip evm builtins Signed-off-by: Cyrill Leutwiler --- crates/llvm-context/src/lib.rs | 1 + .../context/function/runtime/arithmetics.rs | 59 +++++++++++++++++++ .../src/polkavm/evm/arithmetic.rs | 19 +++--- .../statement/expression/function_call/mod.rs | 25 +++++--- crates/yul/src/parser/statement/object.rs | 2 + 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/crates/llvm-context/src/lib.rs b/crates/llvm-context/src/lib.rs index c7a9ae7..6186c15 100644 --- a/crates/llvm-context/src/lib.rs +++ b/crates/llvm-context/src/lib.rs @@ -19,6 +19,7 @@ pub use self::polkavm::context::function::declaration::Declaration as PolkaVMFun pub use self::polkavm::context::function::intrinsics::Intrinsics as PolkaVMIntrinsicFunction; pub use self::polkavm::context::function::llvm_runtime::LLVMRuntime as PolkaVMLLVMRuntime; pub use self::polkavm::context::function::r#return::Return as PolkaVMFunctionReturn; +pub use self::polkavm::context::function::runtime::arithmetics::Addition as PolkaVMAdditionFunction; pub use self::polkavm::context::function::runtime::arithmetics::Division as PolkaVMDivisionFunction; pub use self::polkavm::context::function::runtime::arithmetics::Remainder as PolkaVMRemainderFunction; pub use self::polkavm::context::function::runtime::arithmetics::SignedDivision as PolkaVMSignedDivisionFunction; diff --git a/crates/llvm-context/src/polkavm/context/function/runtime/arithmetics.rs b/crates/llvm-context/src/polkavm/context/function/runtime/arithmetics.rs index ba9395f..c736faa 100644 --- a/crates/llvm-context/src/polkavm/context/function/runtime/arithmetics.rs +++ b/crates/llvm-context/src/polkavm/context/function/runtime/arithmetics.rs @@ -7,6 +7,65 @@ use crate::polkavm::context::Context; use crate::polkavm::Dependency; use crate::polkavm::WriteLLVM; +/// Implements the division operator according to the EVM specification. +pub struct Addition; + +impl RuntimeFunction for Addition +where + D: Dependency + Clone, +{ + const NAME: &'static str = "__revive_addition"; + + fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { + context.void_type().fn_type( + &[ + context.llvm().ptr_type(Default::default()).into(), + context.llvm().ptr_type(Default::default()).into(), + context.llvm().ptr_type(Default::default()).into(), + ], + false, + ) + } + + fn emit_body<'ctx>( + &self, + context: &mut Context<'ctx, D>, + ) -> anyhow::Result>> { + let result_pointer = Self::paramater(context, 0).into_pointer_value(); + let operand_1 = Self::paramater(context, 1).into_pointer_value(); + let operand_2 = Self::paramater(context, 2).into_pointer_value(); + + let operand_1 = context + .builder() + .build_load(context.word_type(), operand_1, "operand_1")? + .into_int_value(); + let operand_2 = context + .builder() + .build_load(context.word_type(), operand_2, "operand_2")? + .into_int_value(); + let result = context + .builder() + .build_int_add(operand_1, operand_2, "addition_result")?; + + context.builder().build_store(result_pointer, result)?; + + Ok(None) + } +} + +impl WriteLLVM for Addition +where + D: Dependency + Clone, +{ + fn declare(&mut self, context: &mut Context) -> anyhow::Result<()> { + >::declare(self, context) + } + + fn into_llvm(self, context: &mut Context) -> anyhow::Result<()> { + >::emit(&self, context) + } +} + /// Implements the division operator according to the EVM specification. pub struct Division; diff --git a/crates/llvm-context/src/polkavm/evm/arithmetic.rs b/crates/llvm-context/src/polkavm/evm/arithmetic.rs index 143cf1c..868bd07 100644 --- a/crates/llvm-context/src/polkavm/evm/arithmetic.rs +++ b/crates/llvm-context/src/polkavm/evm/arithmetic.rs @@ -5,6 +5,7 @@ use inkwell::values::BasicValue; use crate::polkavm::context::runtime::RuntimeFunction; use crate::polkavm::context::Context; use crate::polkavm::Dependency; +use crate::PolkaVMAdditionFunction; use crate::PolkaVMDivisionFunction; use crate::PolkaVMRemainderFunction; use crate::PolkaVMSignedDivisionFunction; @@ -13,16 +14,20 @@ use crate::PolkaVMSignedRemainderFunction; /// Translates the arithmetic addition. pub fn addition<'ctx, D>( context: &mut Context<'ctx, D>, - operand_1: inkwell::values::IntValue<'ctx>, - operand_2: inkwell::values::IntValue<'ctx>, -) -> anyhow::Result> + binding: inkwell::values::PointerValue<'ctx>, + operand_1: inkwell::values::PointerValue<'ctx>, + operand_2: inkwell::values::PointerValue<'ctx>, +) -> anyhow::Result<()> where D: Dependency + Clone, { - Ok(context - .builder() - .build_int_add(operand_1, operand_2, "addition_result")? - .as_basic_value_enum()) + let declaration = >::declaration(context); + context.build_call( + declaration, + &[binding.into(), operand_1.into(), operand_2.into()], + "add", + ); + Ok(()) } /// Translates the arithmetic subtraction. diff --git a/crates/yul/src/parser/statement/expression/function_call/mod.rs b/crates/yul/src/parser/statement/expression/function_call/mod.rs index d704e5e..ea7625d 100644 --- a/crates/yul/src/parser/statement/expression/function_call/mod.rs +++ b/crates/yul/src/parser/statement/expression/function_call/mod.rs @@ -176,10 +176,11 @@ impl FunctionCall { let arguments = self.pop_arguments_llvm::(context)?; revive_llvm_context::polkavm_evm_arithmetic::addition( context, - arguments[0].into_int_value(), - arguments[1].into_int_value(), - ) - .map(Some) + bindings, + arguments[0].into_pointer_value(), + arguments[1].into_pointer_value(), + )?; + Ok(()) } Name::Sub => { let arguments = self.pop_arguments_llvm::(context)?; @@ -998,10 +999,12 @@ impl FunctionCall { D: revive_llvm_context::PolkaVMDependency + Clone, { let mut arguments = Vec::with_capacity(N); - for expression in self.arguments.drain(0..N).rev() { + for (index, expression) in self.arguments.drain(0..N).rev().enumerate() { + let name = format!("arg_{index}"); + let pointer = context.build_alloca(context.word_type(), &name); arguments.push( expression - .into_llvm(context)? + .into_llvm(&[(name, pointer)], context)? .expect("Always exists") .access(context)?, ); @@ -1020,8 +1023,14 @@ impl FunctionCall { D: revive_llvm_context::PolkaVMDependency + Clone, { let mut arguments = Vec::with_capacity(N); - for expression in self.arguments.drain(0..N).rev() { - arguments.push(expression.into_llvm(context)?.expect("Always exists")); + for (index, expression) in self.arguments.drain(0..N).rev().enumerate() { + let name = format!("arg_{index}"); + let pointer = context.build_alloca(context.word_type(), &name); + arguments.push( + expression + .into_llvm(&[(name, pointer)], context)? + .expect("Always exists"), + ); } arguments.reverse(); diff --git a/crates/yul/src/parser/statement/object.rs b/crates/yul/src/parser/statement/object.rs index 7af755d..c9c68ba 100644 --- a/crates/yul/src/parser/statement/object.rs +++ b/crates/yul/src/parser/statement/object.rs @@ -204,6 +204,7 @@ where revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?; revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?; + revive_llvm_context::PolkaVMAdditionFunction.declare(context)?; revive_llvm_context::PolkaVMDivisionFunction.declare(context)?; revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?; revive_llvm_context::PolkaVMRemainderFunction.declare(context)?; @@ -258,6 +259,7 @@ where revive_llvm_context::PolkaVMEventLogFunction::<3>.into_llvm(context)?; revive_llvm_context::PolkaVMEventLogFunction::<4>.into_llvm(context)?; + revive_llvm_context::PolkaVMAdditionFunction.into_llvm(context)?; revive_llvm_context::PolkaVMDivisionFunction.into_llvm(context)?; revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?; revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;