mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 08:21:09 +00:00
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Baseline": 950,
|
"Baseline": 950,
|
||||||
"Computation": 2222,
|
"Computation": 2262,
|
||||||
"DivisionArithmetics": 8802,
|
"DivisionArithmetics": 8915,
|
||||||
"ERC20": 17602,
|
"ERC20": 17233,
|
||||||
"Events": 1628,
|
"Events": 1628,
|
||||||
"FibonacciIterative": 1485,
|
"FibonacciIterative": 1485,
|
||||||
"Flipper": 2082,
|
"Flipper": 2132,
|
||||||
"SHA1": 8230
|
"SHA1": 8381
|
||||||
}
|
}
|
||||||
@@ -773,27 +773,49 @@ where
|
|||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a stack load instruction.
|
/// Builds a stack load instruction with a direct assignment.
|
||||||
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
|
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
|
||||||
pub fn build_load(
|
pub fn build_load_assign(
|
||||||
&self,
|
&self,
|
||||||
pointer: Pointer<'ctx>,
|
pointer: Pointer<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> {
|
assignment_pointer: &mut Option<inkwell::values::PointerValue<'ctx>>,
|
||||||
|
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>> {
|
||||||
match pointer.address_space {
|
match pointer.address_space {
|
||||||
AddressSpace::Heap => {
|
AddressSpace::Heap => {
|
||||||
let name = <PolkaVMLoadHeapWordFunction as RuntimeFunction<D>>::NAME;
|
|
||||||
let declaration =
|
let declaration =
|
||||||
<PolkaVMLoadHeapWordFunction as RuntimeFunction<D>>::declaration(self);
|
<PolkaVMLoadHeapWordFunction as RuntimeFunction<D>>::declaration(self);
|
||||||
let arguments = [self
|
match assignment_pointer.take() {
|
||||||
.builder()
|
Some(assignment_pointer) => {
|
||||||
.build_ptr_to_int(pointer.value, self.xlen_type(), "offset_ptrtoint")?
|
let arguments = [
|
||||||
.as_basic_value_enum()];
|
self.builder()
|
||||||
Ok(self
|
.build_ptr_to_int(
|
||||||
.build_call(declaration, &arguments, "heap_load")
|
pointer.value,
|
||||||
.unwrap_or_else(|| {
|
self.xlen_type(),
|
||||||
panic!("revive runtime function {name} should return a value")
|
"offset_ptrtoint",
|
||||||
}))
|
)?
|
||||||
|
.as_basic_value_enum(),
|
||||||
|
assignment_pointer.into(),
|
||||||
|
];
|
||||||
|
self.build_call(declaration, &arguments, "heap_load");
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let pointer = self.build_alloca_at_entry(self.word_type(), "pointer");
|
||||||
|
let arguments = [
|
||||||
|
self.builder()
|
||||||
|
.build_ptr_to_int(
|
||||||
|
pointer.value,
|
||||||
|
self.xlen_type(),
|
||||||
|
"offset_ptrtoint",
|
||||||
|
)?
|
||||||
|
.as_basic_value_enum(),
|
||||||
|
pointer.value.into(),
|
||||||
|
];
|
||||||
|
self.build_call(declaration, &arguments, "heap_load");
|
||||||
|
Ok(Some(self.build_load(pointer, "storage_value")?))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AddressSpace::Stack => {
|
AddressSpace::Stack => {
|
||||||
let value = self
|
let value = self
|
||||||
@@ -806,11 +828,23 @@ where
|
|||||||
.set_alignment(revive_common::BYTE_LENGTH_STACK_ALIGN as u32)
|
.set_alignment(revive_common::BYTE_LENGTH_STACK_ALIGN as u32)
|
||||||
.expect("Alignment is valid");
|
.expect("Alignment is valid");
|
||||||
|
|
||||||
Ok(value)
|
Ok(Some(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds a stack load instruction.
|
||||||
|
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
|
||||||
|
pub fn build_load(
|
||||||
|
&self,
|
||||||
|
pointer: Pointer<'ctx>,
|
||||||
|
name: &str,
|
||||||
|
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> {
|
||||||
|
Ok(self
|
||||||
|
.build_load_assign(pointer, name, &mut None)?
|
||||||
|
.expect("without an assignment pointer loads return a value"))
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds a stack store instruction.
|
/// Builds a stack store instruction.
|
||||||
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
|
/// Sets the alignment to 256 bits for the stack and 1 bit for the heap, parent, and child.
|
||||||
pub fn build_store<V>(&self, pointer: Pointer<'ctx>, value: V) -> anyhow::Result<()>
|
pub fn build_store<V>(&self, pointer: Pointer<'ctx>, value: V) -> anyhow::Result<()>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use inkwell::values::BasicValueEnum;
|
use inkwell::values::BasicValueEnum;
|
||||||
|
|
||||||
|
use crate::polkavm::context::address_space::AddressSpace;
|
||||||
|
use crate::polkavm::context::pointer::Pointer;
|
||||||
use crate::polkavm::context::runtime::RuntimeFunction;
|
use crate::polkavm::context::runtime::RuntimeFunction;
|
||||||
use crate::polkavm::context::Context;
|
use crate::polkavm::context::Context;
|
||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
@@ -17,9 +19,13 @@ where
|
|||||||
const NAME: &'static str = "__revive_load_heap_word";
|
const NAME: &'static str = "__revive_load_heap_word";
|
||||||
|
|
||||||
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||||
context
|
context.void_type().fn_type(
|
||||||
.word_type()
|
&[
|
||||||
.fn_type(&[context.xlen_type().into()], false)
|
context.xlen_type().into(),
|
||||||
|
context.llvm().ptr_type(Default::default()).into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_body<'ctx>(
|
fn emit_body<'ctx>(
|
||||||
@@ -27,6 +33,7 @@ where
|
|||||||
context: &mut Context<'ctx, D>,
|
context: &mut Context<'ctx, D>,
|
||||||
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
let offset = Self::paramater(context, 0).into_int_value();
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
|
let assignment_pointer = Self::paramater(context, 1).into_pointer_value();
|
||||||
let length = context
|
let length = context
|
||||||
.xlen_type()
|
.xlen_type()
|
||||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
||||||
@@ -42,7 +49,11 @@ where
|
|||||||
.expect("Alignment is valid");
|
.expect("Alignment is valid");
|
||||||
|
|
||||||
let swapped_value = context.build_byte_swap(value)?;
|
let swapped_value = context.build_byte_swap(value)?;
|
||||||
Ok(Some(swapped_value))
|
context.build_store(
|
||||||
|
Pointer::new(context.word_type(), AddressSpace::Stack, assignment_pointer),
|
||||||
|
swapped_value,
|
||||||
|
)?;
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ where
|
|||||||
pub fn load<'ctx, D>(
|
pub fn load<'ctx, D>(
|
||||||
context: &mut Context<'ctx, D>,
|
context: &mut Context<'ctx, D>,
|
||||||
offset: inkwell::values::IntValue<'ctx>,
|
offset: inkwell::values::IntValue<'ctx>,
|
||||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
assignment_pointer: &mut Option<inkwell::values::PointerValue<'ctx>>,
|
||||||
|
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
@@ -40,7 +41,7 @@ where
|
|||||||
offset,
|
offset,
|
||||||
"memory_load_pointer",
|
"memory_load_pointer",
|
||||||
);
|
);
|
||||||
context.build_load(pointer, "memory_load_result")
|
context.build_load_assign(pointer, "memory_load_result", assignment_pointer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `mstore` instruction.
|
/// Translates the `mstore` instruction.
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ use crate::PolkaVMStoreTransientStorageWordFunction;
|
|||||||
pub fn load<'ctx, D>(
|
pub fn load<'ctx, D>(
|
||||||
context: &mut Context<'ctx, D>,
|
context: &mut Context<'ctx, D>,
|
||||||
position: &PolkaVMArgument<'ctx>,
|
position: &PolkaVMArgument<'ctx>,
|
||||||
assignment_pointer: Option<inkwell::values::PointerValue<'ctx>>,
|
assignment_pointer: &mut Option<inkwell::values::PointerValue<'ctx>>,
|
||||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let _name = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::NAME;
|
let _name = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::NAME;
|
||||||
let declaration = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
let declaration = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||||
match assignment_pointer {
|
match assignment_pointer.take() {
|
||||||
Some(assignment_pointer) => {
|
Some(assignment_pointer) => {
|
||||||
let arguments = [
|
let arguments = [
|
||||||
position.as_pointer(context)?.value.into(),
|
position.as_pointer(context)?.value.into(),
|
||||||
|
|||||||
@@ -121,11 +121,6 @@ where
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
context.set_debug_location(self.location.line, 0, None)?;
|
context.set_debug_location(self.location.line, 0, None)?;
|
||||||
|
|
||||||
let value = match self.initializer.into_llvm(context, None)? {
|
|
||||||
Some(value) => value,
|
|
||||||
None => return Ok(()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.bindings.len() == 1 {
|
if self.bindings.len() == 1 {
|
||||||
let identifier = self.bindings.remove(0);
|
let identifier = self.bindings.remove(0);
|
||||||
let pointer = context
|
let pointer = context
|
||||||
@@ -139,9 +134,27 @@ where
|
|||||||
identifier.inner,
|
identifier.inner,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
context.build_store(pointer, value.access(context)?)?;
|
|
||||||
|
let mut assignment_pointer = Some(pointer.value);
|
||||||
|
let value = match self
|
||||||
|
.initializer
|
||||||
|
.into_llvm(context, &mut assignment_pointer)?
|
||||||
|
{
|
||||||
|
Some(value) => value,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if assignment_pointer.is_some() {
|
||||||
|
context.build_store(pointer, value.access(context)?)?;
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let value = match self.initializer.into_llvm(context, &mut None)? {
|
||||||
|
Some(value) => value,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
let value = value.access(context)?;
|
let value = value.access(context)?;
|
||||||
let llvm_type = value.into_struct_value().get_type();
|
let llvm_type = value.into_struct_value().get_type();
|
||||||
let tuple_pointer = context.build_alloca(llvm_type, "assignment_pointer");
|
let tuple_pointer = context.build_alloca(llvm_type, "assignment_pointer");
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ where
|
|||||||
block.into_llvm(context)?;
|
block.into_llvm(context)?;
|
||||||
}
|
}
|
||||||
Statement::Expression(expression) => {
|
Statement::Expression(expression) => {
|
||||||
expression.into_llvm(context, None)?;
|
expression.into_llvm(context, &mut None)?;
|
||||||
}
|
}
|
||||||
Statement::VariableDeclaration(statement) => statement.into_llvm(context)?,
|
Statement::VariableDeclaration(statement) => statement.into_llvm(context)?,
|
||||||
Statement::Assignment(statement) => statement.into_llvm(context)?,
|
Statement::Assignment(statement) => statement.into_llvm(context)?,
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ impl FunctionCall {
|
|||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
mut self,
|
mut self,
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
assignment_pointer: Option<inkwell::values::PointerValue<'ctx>>,
|
assignment_pointer: &mut Option<inkwell::values::PointerValue<'ctx>>,
|
||||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
||||||
where
|
where
|
||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
@@ -130,7 +130,7 @@ impl FunctionCall {
|
|||||||
let mut values = Vec::with_capacity(self.arguments.len());
|
let mut values = Vec::with_capacity(self.arguments.len());
|
||||||
for argument in self.arguments.into_iter().rev() {
|
for argument in self.arguments.into_iter().rev() {
|
||||||
let value = argument
|
let value = argument
|
||||||
.into_llvm(context, None)?
|
.into_llvm(context, &mut None)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?;
|
.access(context)?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
@@ -417,8 +417,8 @@ impl FunctionCall {
|
|||||||
revive_llvm_context::polkavm_evm_memory::load(
|
revive_llvm_context::polkavm_evm_memory::load(
|
||||||
context,
|
context,
|
||||||
arguments[0].into_int_value(),
|
arguments[0].into_int_value(),
|
||||||
|
assignment_pointer,
|
||||||
)
|
)
|
||||||
.map(Some)
|
|
||||||
}
|
}
|
||||||
Name::MStore => {
|
Name::MStore => {
|
||||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||||
@@ -994,7 +994,7 @@ impl FunctionCall {
|
|||||||
for expression in self.arguments.drain(0..N).rev() {
|
for expression in self.arguments.drain(0..N).rev() {
|
||||||
arguments.push(
|
arguments.push(
|
||||||
expression
|
expression
|
||||||
.into_llvm(context, None)?
|
.into_llvm(context, &mut None)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?,
|
.access(context)?,
|
||||||
);
|
);
|
||||||
@@ -1014,7 +1014,11 @@ impl FunctionCall {
|
|||||||
{
|
{
|
||||||
let mut arguments = Vec::with_capacity(N);
|
let mut arguments = Vec::with_capacity(N);
|
||||||
for expression in self.arguments.drain(0..N).rev() {
|
for expression in self.arguments.drain(0..N).rev() {
|
||||||
arguments.push(expression.into_llvm(context, None)?.expect("Always exists"));
|
arguments.push(
|
||||||
|
expression
|
||||||
|
.into_llvm(context, &mut None)?
|
||||||
|
.expect("Always exists"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
arguments.reverse();
|
arguments.reverse();
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ impl Expression {
|
|||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
self,
|
self,
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
assignment_pointer: Option<inkwell::values::PointerValue<'ctx>>,
|
assignment_pointer: &mut Option<inkwell::values::PointerValue<'ctx>>,
|
||||||
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
||||||
where
|
where
|
||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ where
|
|||||||
context.set_basic_block(condition_block);
|
context.set_basic_block(condition_block);
|
||||||
let condition = self
|
let condition = self
|
||||||
.condition
|
.condition
|
||||||
.into_llvm(context, None)?
|
.into_llvm(context, &mut None)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?
|
.access(context)?
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ where
|
|||||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||||
let condition = self
|
let condition = self
|
||||||
.condition
|
.condition
|
||||||
.into_llvm(context, None)?
|
.into_llvm(context, &mut None)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?
|
.access(context)?
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ where
|
|||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||||
let scrutinee = self.expression.into_llvm(context, None)?;
|
let scrutinee = self.expression.into_llvm(context, &mut None)?;
|
||||||
|
|
||||||
if self.cases.is_empty() {
|
if self.cases.is_empty() {
|
||||||
if let Some(block) = self.default {
|
if let Some(block) = self.default {
|
||||||
|
|||||||
@@ -110,8 +110,9 @@ where
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert_stack_pointer(identifier.inner.clone(), pointer);
|
.insert_stack_pointer(identifier.inner.clone(), pointer);
|
||||||
|
|
||||||
|
let mut assignment_pointer = Some(pointer.value);
|
||||||
let value = if let Some(expression) = self.expression {
|
let value = if let Some(expression) = self.expression {
|
||||||
match expression.into_llvm(context, None)? {
|
match expression.into_llvm(context, &mut assignment_pointer)? {
|
||||||
Some(mut value) => {
|
Some(mut value) => {
|
||||||
if let Some(constant) = value.constant.take() {
|
if let Some(constant) = value.constant.take() {
|
||||||
context
|
context
|
||||||
@@ -128,7 +129,9 @@ where
|
|||||||
} else {
|
} else {
|
||||||
r#type.const_zero().as_basic_value_enum()
|
r#type.const_zero().as_basic_value_enum()
|
||||||
};
|
};
|
||||||
context.build_store(pointer, value)?;
|
if assignment_pointer.is_some() {
|
||||||
|
context.build_store(pointer, value)?;
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +159,7 @@ where
|
|||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
let location = expression.location();
|
let location = expression.location();
|
||||||
let expression = match expression.into_llvm(context, None)? {
|
let expression = match expression.into_llvm(context, &mut None)? {
|
||||||
Some(expression) => expression,
|
Some(expression) => expression,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user