mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-05-07 20:08:02 +00:00
Separate compilation and linker phases (#376)
Separate between compilation and linker phases to allow deploy time linking and back-porting era compiler changes to fix #91. Unlinked contract binaries (caused by missing libraries or missing factory dependencies in turn) are emitted as raw ELF object. Few drive by fixes: - #98 - A compiler panic on missing libraries definitions. - Fixes some incosistent type forwarding in JSON output (empty string vs. null object). - Remove the unused fallback for size optimization setting. - Remove the broken `--lvm-ir` mode. - CI workflow fixes. --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by: xermicus <bigcyrill@hotmail.com> Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
//! The assignment expression statement.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use inkwell::types::BasicType;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_common::BIT_LENGTH_X32;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::symbol::Symbol;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -108,19 +112,13 @@ impl Assignment {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
self.initializer.get_missing_libraries()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Assignment
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(
|
||||
mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
||||
) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for Assignment {
|
||||
fn into_llvm(mut self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
context.set_debug_location(self.location.line, self.location.column, None)?;
|
||||
|
||||
let value = match self.initializer.into_llvm(context)? {
|
||||
@@ -158,7 +156,7 @@ where
|
||||
&[
|
||||
context.word_const(0),
|
||||
context
|
||||
.integer_type(revive_common::BIT_LENGTH_X32)
|
||||
.integer_type(BIT_LENGTH_X32)
|
||||
.const_int(index as u64, false),
|
||||
],
|
||||
context.word_type().as_basic_type_enum(),
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
//! The source code block.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::symbol::Symbol;
|
||||
@@ -123,8 +125,8 @@ impl Block {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
let mut libraries = HashSet::new();
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut libraries = BTreeSet::new();
|
||||
for statement in self.statements.iter() {
|
||||
libraries.extend(statement.get_missing_libraries());
|
||||
}
|
||||
@@ -132,11 +134,8 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Block
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for Block {
|
||||
fn into_llvm(self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
let current_function = context.current_function().borrow().name().to_owned();
|
||||
let current_block = context.basic_block();
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
//! The YUL code.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::keyword::Keyword;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -52,16 +55,13 @@ impl Code {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
self.block.get_missing_libraries()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Code
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for Code {
|
||||
fn into_llvm(self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
self.block.into_llvm(context)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
pub mod name;
|
||||
pub mod verbatim;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use inkwell::values::BasicValue;
|
||||
use serde::Deserialize;
|
||||
@@ -95,8 +95,8 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
let mut libraries = HashSet::new();
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut libraries = BTreeSet::new();
|
||||
|
||||
if let Name::LinkerSymbol = self.name {
|
||||
let _argument = self.arguments.first().expect("Always exists");
|
||||
@@ -117,13 +117,10 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
/// Converts the function call into an LLVM value.
|
||||
pub fn into_llvm<'ctx, D>(
|
||||
pub fn into_llvm<'ctx>(
|
||||
mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx>,
|
||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>> {
|
||||
let location = self.location;
|
||||
context.set_debug_location(location.line, location.column, None)?;
|
||||
|
||||
@@ -164,7 +161,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Add => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::addition(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -173,7 +170,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Sub => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::subtraction(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -182,7 +179,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Mul => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::multiplication(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -191,7 +188,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Div => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::division(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -200,7 +197,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Mod => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::remainder(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -209,7 +206,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Sdiv => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::division_signed(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -218,7 +215,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Smod => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_arithmetic::remainder_signed(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -228,7 +225,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Lt => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -238,7 +235,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Gt => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -248,7 +245,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Eq => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -258,7 +255,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::IsZero => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -268,7 +265,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Slt => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -278,7 +275,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Sgt => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_comparison::compare(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -289,7 +286,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Or => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::or(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -298,7 +295,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Xor => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::xor(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -307,7 +304,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Not => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::xor(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -316,7 +313,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::And => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::and(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -325,7 +322,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Shl => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::shift_left(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -334,7 +331,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Shr => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::shift_right(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -343,7 +340,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Sar => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::shift_right_arithmetic(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -352,7 +349,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Byte => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_bitwise::byte(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -361,12 +358,12 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Pop => {
|
||||
let _arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let _arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
Name::AddMod => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_math::add_mod(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -376,7 +373,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::MulMod => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_math::mul_mod(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -386,7 +383,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Exp => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_math::exponent(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -395,7 +392,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::SignExtend => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_math::sign_extend(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -405,7 +402,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Keccak256 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_crypto::sha3(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -415,7 +412,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::MLoad => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_memory::load(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -423,7 +420,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::MStore => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_memory::store(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -432,7 +429,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::MStore8 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_memory::store_byte(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -441,7 +438,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::MCopy => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
let destination = revive_llvm_context::PolkaVMPointer::new_with_offset(
|
||||
context,
|
||||
revive_llvm_context::PolkaVMAddressSpace::Heap,
|
||||
@@ -467,11 +464,11 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::SLoad => {
|
||||
let arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_storage::load(context, &arguments[0]).map(Some)
|
||||
}
|
||||
Name::SStore => {
|
||||
let arguments = self.pop_arguments::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_storage::store(
|
||||
context,
|
||||
&arguments[0],
|
||||
@@ -480,12 +477,12 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::TLoad => {
|
||||
let arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_storage::transient_load(context, &arguments[0])
|
||||
.map(Some)
|
||||
}
|
||||
Name::TStore => {
|
||||
let arguments = self.pop_arguments::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_storage::transient_store(
|
||||
context,
|
||||
&arguments[0],
|
||||
@@ -494,7 +491,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::LoadImmutable => {
|
||||
let mut arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let mut arguments = self.pop_arguments::<1>(context)?;
|
||||
let key = arguments[0].original.take().ok_or_else(|| {
|
||||
anyhow::anyhow!("{} `load_immutable` literal is missing", location)
|
||||
})?;
|
||||
@@ -506,7 +503,7 @@ impl FunctionCall {
|
||||
revive_llvm_context::polkavm_evm_immutable::load(context, index).map(Some)
|
||||
}
|
||||
Name::SetImmutable => {
|
||||
let mut arguments = self.pop_arguments::<D, 3>(context)?;
|
||||
let mut arguments = self.pop_arguments::<3>(context)?;
|
||||
let key = arguments[1].original.take().ok_or_else(|| {
|
||||
anyhow::anyhow!("{} `load_immutable` literal is missing", location)
|
||||
})?;
|
||||
@@ -518,7 +515,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::CallDataLoad => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
|
||||
match context
|
||||
.code_type()
|
||||
@@ -550,7 +547,7 @@ impl FunctionCall {
|
||||
}
|
||||
}
|
||||
Name::CallDataCopy => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
|
||||
match context
|
||||
.code_type()
|
||||
@@ -603,7 +600,7 @@ impl FunctionCall {
|
||||
);
|
||||
}
|
||||
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_calldata::copy(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -616,7 +613,7 @@ impl FunctionCall {
|
||||
revive_llvm_context::polkavm_evm_return_data::size(context).map(Some)
|
||||
}
|
||||
Name::ReturnDataCopy => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_return_data::copy(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -626,7 +623,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::ExtCodeSize => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_ext_code::size(
|
||||
context,
|
||||
Some(arguments[0].into_int_value()),
|
||||
@@ -634,7 +631,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::ExtCodeHash => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
revive_llvm_context::polkavm_evm_ext_code::hash(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -643,7 +640,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Return => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_return::r#return(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -652,7 +649,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::Revert => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_return::revert(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -666,7 +663,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Log0 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<2>(context)?;
|
||||
revive_llvm_context::polkavm_evm_event::log(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -676,7 +673,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::Log1 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_event::log(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -686,7 +683,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::Log2 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 4>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<4>(context)?;
|
||||
revive_llvm_context::polkavm_evm_event::log(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -696,7 +693,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::Log3 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 5>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<5>(context)?;
|
||||
revive_llvm_context::polkavm_evm_event::log(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -706,7 +703,7 @@ impl FunctionCall {
|
||||
.map(|_| None)
|
||||
}
|
||||
Name::Log4 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 6>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<6>(context)?;
|
||||
revive_llvm_context::polkavm_evm_event::log(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -717,7 +714,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Call => {
|
||||
let arguments = self.pop_arguments::<D, 7>(context)?;
|
||||
let arguments = self.pop_arguments::<7>(context)?;
|
||||
|
||||
let gas = arguments[0].access(context)?.into_int_value();
|
||||
let address = arguments[1].access(context)?.into_int_value();
|
||||
@@ -747,7 +744,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::StaticCall => {
|
||||
let arguments = self.pop_arguments::<D, 6>(context)?;
|
||||
let arguments = self.pop_arguments::<6>(context)?;
|
||||
|
||||
let gas = arguments[0].access(context)?.into_int_value();
|
||||
let address = arguments[1].access(context)?.into_int_value();
|
||||
@@ -776,7 +773,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::DelegateCall => {
|
||||
let arguments = self.pop_arguments::<D, 6>(context)?;
|
||||
let arguments = self.pop_arguments::<6>(context)?;
|
||||
|
||||
let gas = arguments[0].access(context)?.into_int_value();
|
||||
let address = arguments[1].access(context)?.into_int_value();
|
||||
@@ -804,7 +801,7 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::Create => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
|
||||
let value = arguments[0].into_int_value();
|
||||
let input_offset = arguments[1].into_int_value();
|
||||
@@ -820,7 +817,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::Create2 => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 4>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<4>(context)?;
|
||||
|
||||
let value = arguments[0].into_int_value();
|
||||
let input_offset = arguments[1].into_int_value();
|
||||
@@ -837,7 +834,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::DataOffset => {
|
||||
let mut arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let mut arguments = self.pop_arguments::<1>(context)?;
|
||||
|
||||
let identifier = arguments[0].original.take().ok_or_else(|| {
|
||||
anyhow::anyhow!("{} `dataoffset` object identifier is missing", location)
|
||||
@@ -848,7 +845,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::DataSize => {
|
||||
let mut arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let mut arguments = self.pop_arguments::<1>(context)?;
|
||||
|
||||
let identifier = arguments[0].original.take().ok_or_else(|| {
|
||||
anyhow::anyhow!("{} `dataoffset` object identifier is missing", location)
|
||||
@@ -859,7 +856,7 @@ impl FunctionCall {
|
||||
.map(Some)
|
||||
}
|
||||
Name::DataCopy => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 3>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<3>(context)?;
|
||||
revive_llvm_context::polkavm_evm_memory::store(
|
||||
context,
|
||||
arguments[0].into_int_value(),
|
||||
@@ -869,19 +866,14 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
Name::LinkerSymbol => {
|
||||
let mut arguments = self.pop_arguments::<D, 1>(context)?;
|
||||
let mut arguments = self.pop_arguments::<1>(context)?;
|
||||
let path = arguments[0].original.take().ok_or_else(|| {
|
||||
anyhow::anyhow!("{} Linker symbol literal is missing", location)
|
||||
})?;
|
||||
|
||||
Ok(Some(
|
||||
context
|
||||
.resolve_library(path.as_str())?
|
||||
.as_basic_value_enum(),
|
||||
))
|
||||
revive_llvm_context::polkavm_evm_call::linker_symbol(context, &path).map(Some)
|
||||
}
|
||||
Name::MemoryGuard => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
Ok(Some(arguments[0]))
|
||||
}
|
||||
|
||||
@@ -894,7 +886,7 @@ impl FunctionCall {
|
||||
Name::CallValue => revive_llvm_context::polkavm_evm_ether_gas::value(context).map(Some),
|
||||
Name::Gas => revive_llvm_context::polkavm_evm_ether_gas::gas(context).map(Some),
|
||||
Name::Balance => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
|
||||
let address = arguments[0].into_int_value();
|
||||
revive_llvm_context::polkavm_evm_ether_gas::balance(context, address).map(Some)
|
||||
@@ -923,14 +915,14 @@ impl FunctionCall {
|
||||
revive_llvm_context::polkavm_evm_contract_context::block_number(context).map(Some)
|
||||
}
|
||||
Name::BlockHash => {
|
||||
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
let index = arguments[0].into_int_value();
|
||||
|
||||
revive_llvm_context::polkavm_evm_contract_context::block_hash(context, index)
|
||||
.map(Some)
|
||||
}
|
||||
Name::BlobHash => {
|
||||
let _arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let _arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
anyhow::bail!(
|
||||
"{} The `BLOBHASH` instruction is not supported in revive",
|
||||
location
|
||||
@@ -959,19 +951,19 @@ impl FunctionCall {
|
||||
} => verbatim::verbatim(context, &mut self, input_size, output_size),
|
||||
|
||||
Name::CallCode => {
|
||||
let _arguments = self.pop_arguments_llvm::<D, 7>(context)?;
|
||||
let _arguments = self.pop_arguments_llvm::<7>(context)?;
|
||||
anyhow::bail!("{} The `CALLCODE` instruction is not supported", location)
|
||||
}
|
||||
Name::Pc => anyhow::bail!("{} The `PC` instruction is not supported", location),
|
||||
Name::ExtCodeCopy => {
|
||||
let _arguments = self.pop_arguments_llvm::<D, 4>(context)?;
|
||||
let _arguments = self.pop_arguments_llvm::<4>(context)?;
|
||||
anyhow::bail!(
|
||||
"{} The `EXTCODECOPY` instruction is not supported",
|
||||
location
|
||||
)
|
||||
}
|
||||
Name::SelfDestruct => {
|
||||
let _arguments = self.pop_arguments_llvm::<D, 1>(context)?;
|
||||
let _arguments = self.pop_arguments_llvm::<1>(context)?;
|
||||
anyhow::bail!(
|
||||
"{} The `SELFDESTRUCT` instruction is not supported",
|
||||
location
|
||||
@@ -981,13 +973,10 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
/// Pops the specified number of arguments, converted into their LLVM values.
|
||||
fn pop_arguments_llvm<'ctx, D, const N: usize>(
|
||||
fn pop_arguments_llvm<'ctx, const N: usize>(
|
||||
&mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<[inkwell::values::BasicValueEnum<'ctx>; N]>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx>,
|
||||
) -> anyhow::Result<[inkwell::values::BasicValueEnum<'ctx>; N]> {
|
||||
let mut arguments = Vec::with_capacity(N);
|
||||
for expression in self.arguments.drain(0..N).rev() {
|
||||
arguments.push(
|
||||
@@ -1005,13 +994,10 @@ impl FunctionCall {
|
||||
}
|
||||
|
||||
/// Pops the specified number of arguments.
|
||||
fn pop_arguments<'ctx, D, const N: usize>(
|
||||
fn pop_arguments<'ctx, const N: usize>(
|
||||
&mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<[revive_llvm_context::PolkaVMArgument<'ctx>; N]>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx>,
|
||||
) -> anyhow::Result<[revive_llvm_context::PolkaVMArgument<'ctx>; N]> {
|
||||
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"));
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
//! Translates the verbatim simulations.
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
|
||||
use crate::parser::statement::expression::function_call::FunctionCall;
|
||||
|
||||
/// Translates the verbatim simulations.
|
||||
pub fn verbatim<'ctx, D>(
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
pub fn verbatim<'ctx>(
|
||||
context: &mut PolkaVMContext<'ctx>,
|
||||
call: &mut FunctionCall,
|
||||
_input_size: usize,
|
||||
output_size: usize,
|
||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>> {
|
||||
if output_size > 1 {
|
||||
anyhow::bail!(
|
||||
"{} Verbatim instructions with multiple return values are not supported",
|
||||
@@ -19,7 +18,7 @@ where
|
||||
);
|
||||
}
|
||||
|
||||
let mut arguments = call.pop_arguments::<D, 1>(context)?;
|
||||
let mut arguments = call.pop_arguments::<1>(context)?;
|
||||
let identifier = arguments[0]
|
||||
.original
|
||||
.take()
|
||||
|
||||
@@ -7,6 +7,12 @@ use num::Zero;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_common::BASE_DECIMAL;
|
||||
use revive_common::BASE_HEXADECIMAL;
|
||||
use revive_common::BYTE_LENGTH_WORD;
|
||||
use revive_llvm_context::PolkaVMArgument;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::literal::boolean::Boolean as BooleanLiteral;
|
||||
use crate::lexer::token::lexeme::literal::integer::Integer as IntegerLiteral;
|
||||
@@ -72,13 +78,10 @@ impl Literal {
|
||||
}
|
||||
|
||||
/// Converts the literal into its LLVM.
|
||||
pub fn into_llvm<'ctx, D>(
|
||||
pub fn into_llvm<'ctx>(
|
||||
self,
|
||||
context: &revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<revive_llvm_context::PolkaVMArgument<'ctx>>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
context: &PolkaVMContext<'ctx>,
|
||||
) -> anyhow::Result<PolkaVMArgument<'ctx>> {
|
||||
match self.inner {
|
||||
LexicalLiteral::Boolean(inner) => {
|
||||
let value = self
|
||||
@@ -99,7 +102,7 @@ impl Literal {
|
||||
BooleanLiteral::True => num::BigUint::one(),
|
||||
};
|
||||
|
||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_constant(constant))
|
||||
Ok(PolkaVMArgument::value(value).with_constant(constant))
|
||||
}
|
||||
LexicalLiteral::Integer(inner) => {
|
||||
let r#type = self.yul_type.unwrap_or_default().into_llvm(context);
|
||||
@@ -118,16 +121,15 @@ impl Literal {
|
||||
|
||||
let constant = match inner {
|
||||
IntegerLiteral::Decimal { ref inner } => {
|
||||
num::BigUint::from_str_radix(inner.as_str(), revive_common::BASE_DECIMAL)
|
||||
num::BigUint::from_str_radix(inner.as_str(), BASE_DECIMAL)
|
||||
}
|
||||
IntegerLiteral::Hexadecimal { ref inner } => {
|
||||
num::BigUint::from_str_radix(&inner["0x".len()..], BASE_HEXADECIMAL)
|
||||
}
|
||||
IntegerLiteral::Hexadecimal { ref inner } => num::BigUint::from_str_radix(
|
||||
&inner["0x".len()..],
|
||||
revive_common::BASE_HEXADECIMAL,
|
||||
),
|
||||
}
|
||||
.expect("Always valid");
|
||||
|
||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_constant(constant))
|
||||
Ok(PolkaVMArgument::value(value).with_constant(constant))
|
||||
}
|
||||
LexicalLiteral::String(inner) => {
|
||||
let string = inner.inner;
|
||||
@@ -136,7 +138,7 @@ impl Literal {
|
||||
let mut hex_string = if inner.is_hexadecimal {
|
||||
string.clone()
|
||||
} else {
|
||||
let mut hex_string = String::with_capacity(revive_common::BYTE_LENGTH_WORD * 2);
|
||||
let mut hex_string = String::with_capacity(BYTE_LENGTH_WORD * 2);
|
||||
let mut index = 0;
|
||||
loop {
|
||||
if index >= string.len() {
|
||||
@@ -151,17 +153,16 @@ impl Literal {
|
||||
index += 3;
|
||||
} else if string[index..].starts_with('u') {
|
||||
let codepoint_str = &string[index + 1..index + 5];
|
||||
let codepoint = u32::from_str_radix(
|
||||
codepoint_str,
|
||||
revive_common::BASE_HEXADECIMAL,
|
||||
)
|
||||
.map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"Invalid codepoint `{}`: {}",
|
||||
codepoint_str,
|
||||
error
|
||||
)
|
||||
})?;
|
||||
let codepoint =
|
||||
u32::from_str_radix(codepoint_str, BASE_HEXADECIMAL).map_err(
|
||||
|error| {
|
||||
anyhow::anyhow!(
|
||||
"Invalid codepoint `{}`: {}",
|
||||
codepoint_str,
|
||||
error
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let unicode_char = char::from_u32(codepoint).ok_or_else(|| {
|
||||
anyhow::anyhow!("Invalid codepoint {}", codepoint)
|
||||
})?;
|
||||
@@ -197,16 +198,16 @@ impl Literal {
|
||||
hex_string
|
||||
};
|
||||
|
||||
if hex_string.len() > revive_common::BYTE_LENGTH_WORD * 2 {
|
||||
if hex_string.len() > BYTE_LENGTH_WORD * 2 {
|
||||
return Ok(revive_llvm_context::PolkaVMArgument::value(
|
||||
r#type.const_zero().as_basic_value_enum(),
|
||||
)
|
||||
.with_original(string));
|
||||
}
|
||||
|
||||
if hex_string.len() < revive_common::BYTE_LENGTH_WORD * 2 {
|
||||
if hex_string.len() < BYTE_LENGTH_WORD * 2 {
|
||||
hex_string.push_str(
|
||||
"0".repeat((revive_common::BYTE_LENGTH_WORD * 2) - hex_string.len())
|
||||
"0".repeat((BYTE_LENGTH_WORD * 2) - hex_string.len())
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
@@ -218,7 +219,7 @@ impl Literal {
|
||||
)
|
||||
.expect("The value is valid")
|
||||
.as_basic_value_enum();
|
||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_original(string))
|
||||
Ok(PolkaVMArgument::value(value).with_original(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//! The expression statement.
|
||||
|
||||
pub mod function_call;
|
||||
pub mod literal;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMArgument;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::symbol::Symbol;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -22,6 +22,9 @@ use crate::visitor::AstVisitor;
|
||||
use self::function_call::FunctionCall;
|
||||
use self::literal::Literal;
|
||||
|
||||
pub mod function_call;
|
||||
pub mod literal;
|
||||
|
||||
/// The Yul expression statement.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub enum Expression {
|
||||
@@ -82,11 +85,11 @@ impl Expression {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
match self {
|
||||
Self::FunctionCall(inner) => inner.get_missing_libraries(),
|
||||
Self::Identifier(_) => HashSet::new(),
|
||||
Self::Literal(_) => HashSet::new(),
|
||||
Self::Identifier(_) => BTreeSet::new(),
|
||||
Self::Literal(_) => BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,13 +103,10 @@ impl Expression {
|
||||
}
|
||||
|
||||
/// Converts the expression into an LLVM value.
|
||||
pub fn into_llvm<'ctx, D>(
|
||||
pub fn into_llvm<'ctx>(
|
||||
self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
context: &mut PolkaVMContext<'ctx>,
|
||||
) -> anyhow::Result<Option<PolkaVMArgument<'ctx>>> {
|
||||
match self {
|
||||
Self::Literal(literal) => literal
|
||||
.clone()
|
||||
@@ -133,16 +133,14 @@ impl Expression {
|
||||
|
||||
let constant = context.current_function().borrow().yul().get_constant(&id);
|
||||
|
||||
let argument = revive_llvm_context::PolkaVMArgument::pointer(pointer, id);
|
||||
let argument = PolkaVMArgument::pointer(pointer, id);
|
||||
|
||||
Ok(Some(match constant {
|
||||
Some(constant) => argument.with_constant(constant),
|
||||
_ => argument,
|
||||
}))
|
||||
}
|
||||
Self::FunctionCall(call) => Ok(call
|
||||
.into_llvm(context)?
|
||||
.map(revive_llvm_context::PolkaVMArgument::value)),
|
||||
Self::FunctionCall(call) => Ok(call.into_llvm(context)?.map(PolkaVMArgument::value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
//! The for-loop statement.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::location::Location;
|
||||
use crate::lexer::token::Token;
|
||||
@@ -53,7 +56,7 @@ impl ForLoop {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut libraries = self.initializer.get_missing_libraries();
|
||||
libraries.extend(self.condition.get_missing_libraries());
|
||||
libraries.extend(self.finalizer.get_missing_libraries());
|
||||
@@ -62,11 +65,8 @@ impl ForLoop {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for ForLoop
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for ForLoop {
|
||||
fn into_llvm(self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
self.initializer.into_llvm(context)?;
|
||||
|
||||
let condition_block = context.append_basic_block("for_condition");
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
//! The function definition statement.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use inkwell::types::BasicType;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_common::BIT_LENGTH_X32;
|
||||
use revive_llvm_context::PolkaVMAttribute;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMFunction;
|
||||
use revive_llvm_context::PolkaVMFunctionReturn;
|
||||
use revive_llvm_context::PolkaVMFunctionYulData;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::symbol::Symbol;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -38,7 +45,7 @@ pub struct FunctionDefinition {
|
||||
/// The function body block.
|
||||
pub body: Block,
|
||||
/// The function LLVM attributes encoded in the identifier.
|
||||
pub attributes: BTreeSet<revive_llvm_context::PolkaVMAttribute>,
|
||||
pub attributes: BTreeSet<PolkaVMAttribute>,
|
||||
}
|
||||
|
||||
impl FunctionDefinition {
|
||||
@@ -148,14 +155,14 @@ impl FunctionDefinition {
|
||||
}
|
||||
|
||||
/// Gets the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
self.body.get_missing_libraries()
|
||||
}
|
||||
|
||||
/// Gets the list of LLVM attributes provided in the function name.
|
||||
pub fn get_llvm_attributes(
|
||||
identifier: &Identifier,
|
||||
) -> Result<BTreeSet<revive_llvm_context::PolkaVMAttribute>, Error> {
|
||||
) -> Result<BTreeSet<PolkaVMAttribute>, Error> {
|
||||
let mut valid_attributes = BTreeSet::new();
|
||||
|
||||
let llvm_begin = identifier.inner.find(Self::LLVM_ATTRIBUTE_PREFIX);
|
||||
@@ -172,7 +179,7 @@ impl FunctionDefinition {
|
||||
|
||||
let mut invalid_attributes = BTreeSet::new();
|
||||
for value in attribute_string.split('_') {
|
||||
match revive_llvm_context::PolkaVMAttribute::try_from(value) {
|
||||
match PolkaVMAttribute::try_from(value) {
|
||||
Ok(attribute) => valid_attributes.insert(attribute),
|
||||
Err(value) => invalid_attributes.insert(value),
|
||||
};
|
||||
@@ -190,14 +197,8 @@ impl FunctionDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for FunctionDefinition
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn declare(
|
||||
&mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
||||
) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for FunctionDefinition {
|
||||
fn declare(&mut self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
context.set_debug_location(self.location.line, self.location.column, None)?;
|
||||
let argument_types: Vec<_> = self
|
||||
.arguments
|
||||
@@ -217,7 +218,7 @@ where
|
||||
Some(inkwell::module::Linkage::External),
|
||||
Some((self.location.line, self.location.column)),
|
||||
)?;
|
||||
revive_llvm_context::PolkaVMFunction::set_attributes(
|
||||
PolkaVMFunction::set_attributes(
|
||||
context.llvm(),
|
||||
function.borrow().declaration(),
|
||||
&self.attributes.clone().into_iter().collect::<Vec<_>>(),
|
||||
@@ -225,15 +226,12 @@ where
|
||||
);
|
||||
function
|
||||
.borrow_mut()
|
||||
.set_yul_data(revive_llvm_context::PolkaVMFunctionYulData::default());
|
||||
.set_yul_data(PolkaVMFunctionYulData::default());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn into_llvm(
|
||||
mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
||||
) -> anyhow::Result<()> {
|
||||
fn into_llvm(mut self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
context.set_current_function(
|
||||
self.identifier.as_str(),
|
||||
Some((self.location.line, self.location.column)),
|
||||
@@ -242,8 +240,8 @@ where
|
||||
|
||||
let r#return = context.current_function().borrow().r#return();
|
||||
match r#return {
|
||||
revive_llvm_context::PolkaVMFunctionReturn::None => {}
|
||||
revive_llvm_context::PolkaVMFunctionReturn::Primitive { pointer } => {
|
||||
PolkaVMFunctionReturn::None => {}
|
||||
PolkaVMFunctionReturn::Primitive { pointer } => {
|
||||
let identifier = self.result.pop().expect("Always exists");
|
||||
|
||||
let r#type = identifier.r#type.unwrap_or_default();
|
||||
@@ -253,7 +251,7 @@ where
|
||||
.borrow_mut()
|
||||
.insert_stack_pointer(identifier.inner, pointer);
|
||||
}
|
||||
revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. } => {
|
||||
PolkaVMFunctionReturn::Compound { pointer, .. } => {
|
||||
for (index, identifier) in self.result.into_iter().enumerate() {
|
||||
let r#type = identifier.r#type.unwrap_or_default().into_llvm(context);
|
||||
let pointer = context.build_gep(
|
||||
@@ -261,7 +259,7 @@ where
|
||||
&[
|
||||
context.word_const(0),
|
||||
context
|
||||
.integer_type(revive_common::BIT_LENGTH_X32)
|
||||
.integer_type(BIT_LENGTH_X32)
|
||||
.const_int(index as u64, false),
|
||||
],
|
||||
context.word_type(),
|
||||
@@ -312,14 +310,14 @@ where
|
||||
|
||||
context.set_basic_block(context.current_function().borrow().return_block());
|
||||
match context.current_function().borrow().r#return() {
|
||||
revive_llvm_context::PolkaVMFunctionReturn::None => {
|
||||
PolkaVMFunctionReturn::None => {
|
||||
context.build_return(None);
|
||||
}
|
||||
revive_llvm_context::PolkaVMFunctionReturn::Primitive { pointer } => {
|
||||
PolkaVMFunctionReturn::Primitive { pointer } => {
|
||||
let return_value = context.build_load(pointer, "return_value")?;
|
||||
context.build_return(Some(&return_value));
|
||||
}
|
||||
revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. } => {
|
||||
PolkaVMFunctionReturn::Compound { pointer, .. } => {
|
||||
let return_value = context.build_load(pointer, "return_value")?;
|
||||
context.build_return(Some(&return_value));
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
//! The if-conditional statement.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::location::Location;
|
||||
use crate::lexer::token::Token;
|
||||
@@ -43,18 +46,15 @@ impl IfConditional {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut libraries = self.condition.get_missing_libraries();
|
||||
libraries.extend(self.block.get_missing_libraries());
|
||||
libraries
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for IfConditional
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for IfConditional {
|
||||
fn into_llvm(self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
let condition = self
|
||||
.condition
|
||||
.into_llvm(context)?
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
//! The block statement.
|
||||
|
||||
pub mod assignment;
|
||||
pub mod block;
|
||||
pub mod code;
|
||||
pub mod expression;
|
||||
pub mod for_loop;
|
||||
pub mod function_definition;
|
||||
pub mod if_conditional;
|
||||
pub mod object;
|
||||
pub mod switch;
|
||||
pub mod variable_declaration;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -37,6 +26,17 @@ use self::object::Object;
|
||||
use self::switch::Switch;
|
||||
use self::variable_declaration::VariableDeclaration;
|
||||
|
||||
pub mod assignment;
|
||||
pub mod block;
|
||||
pub mod code;
|
||||
pub mod expression;
|
||||
pub mod for_loop;
|
||||
pub mod function_definition;
|
||||
pub mod if_conditional;
|
||||
pub mod object;
|
||||
pub mod switch;
|
||||
pub mod variable_declaration;
|
||||
|
||||
/// The Yul block statement.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub enum Statement {
|
||||
@@ -142,7 +142,7 @@ impl Statement {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
match self {
|
||||
Self::Object(inner) => inner.get_missing_libraries(),
|
||||
Self::Code(inner) => inner.get_missing_libraries(),
|
||||
@@ -154,9 +154,9 @@ impl Statement {
|
||||
Self::IfConditional(inner) => inner.get_missing_libraries(),
|
||||
Self::Switch(inner) => inner.get_missing_libraries(),
|
||||
Self::ForLoop(inner) => inner.get_missing_libraries(),
|
||||
Self::Continue(_) => HashSet::new(),
|
||||
Self::Break(_) => HashSet::new(),
|
||||
Self::Leave(_) => HashSet::new(),
|
||||
Self::Continue(_) => BTreeSet::new(),
|
||||
Self::Break(_) => BTreeSet::new(),
|
||||
Self::Leave(_) => BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
//! The YUL object.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::keyword::Keyword;
|
||||
use crate::lexer::token::lexeme::literal::Literal;
|
||||
@@ -170,7 +173,7 @@ impl Object {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut missing_libraries = self.code.get_missing_libraries();
|
||||
if let Some(inner_object) = &self.inner_object {
|
||||
missing_libraries.extend(inner_object.get_missing_libraries());
|
||||
@@ -179,14 +182,8 @@ impl Object {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Object
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn declare(
|
||||
&mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
||||
) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for Object {
|
||||
fn declare(&mut self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
revive_llvm_context::PolkaVMLoadImmutableDataFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMStoreImmutableDataFunction.declare(context)?;
|
||||
|
||||
@@ -270,7 +267,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext) -> anyhow::Result<()> {
|
||||
if let Some(debug_info) = context.debug_info() {
|
||||
let di_builder = debug_info.builder();
|
||||
let object_name: &str = self.identifier.as_str();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! The switch statement case.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -58,7 +58,7 @@ impl Case {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
self.block.get_missing_libraries()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//! The switch statement.
|
||||
|
||||
pub mod case;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::keyword::Keyword;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -21,6 +22,8 @@ use crate::visitor::AstVisitor;
|
||||
|
||||
use self::case::Case;
|
||||
|
||||
pub mod case;
|
||||
|
||||
/// The Yul switch statement.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct Switch {
|
||||
@@ -108,8 +111,8 @@ impl Switch {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
let mut libraries = HashSet::new();
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
let mut libraries = BTreeSet::new();
|
||||
for case in self.cases.iter() {
|
||||
libraries.extend(case.get_missing_libraries());
|
||||
}
|
||||
@@ -120,11 +123,8 @@ impl Switch {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Switch
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for Switch {
|
||||
fn into_llvm(self, context: &mut PolkaVMContext) -> anyhow::Result<()> {
|
||||
context.set_debug_location(self.location.line, self.location.column, None)?;
|
||||
let scrutinee = self.expression.into_llvm(context)?;
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
//! The variable declaration statement.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use inkwell::types::BasicType;
|
||||
use inkwell::values::BasicValue;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use revive_common::BIT_LENGTH_X32;
|
||||
use revive_llvm_context::PolkaVMContext;
|
||||
use revive_llvm_context::PolkaVMWriteLLVM;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::lexer::token::lexeme::symbol::Symbol;
|
||||
use crate::lexer::token::lexeme::Lexeme;
|
||||
@@ -84,23 +88,17 @@ impl VariableDeclaration {
|
||||
}
|
||||
|
||||
/// Get the list of missing deployable libraries.
|
||||
pub fn get_missing_libraries(&self) -> HashSet<String> {
|
||||
pub fn get_missing_libraries(&self) -> BTreeSet<String> {
|
||||
self.expression
|
||||
.as_ref()
|
||||
.map_or_else(HashSet::new, |expression| {
|
||||
.map_or_else(BTreeSet::new, |expression| {
|
||||
expression.get_missing_libraries()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for VariableDeclaration
|
||||
where
|
||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||
{
|
||||
fn into_llvm<'ctx>(
|
||||
mut self,
|
||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||
) -> anyhow::Result<()> {
|
||||
impl PolkaVMWriteLLVM for VariableDeclaration {
|
||||
fn into_llvm<'ctx>(mut self, context: &mut PolkaVMContext<'ctx>) -> anyhow::Result<()> {
|
||||
if self.bindings.len() == 1 {
|
||||
let identifier = self.bindings.remove(0);
|
||||
context.set_debug_location(self.location.line, self.location.column, None)?;
|
||||
@@ -194,7 +192,7 @@ where
|
||||
&[
|
||||
context.word_const(0),
|
||||
context
|
||||
.integer_type(revive_common::BIT_LENGTH_X32)
|
||||
.integer_type(BIT_LENGTH_X32)
|
||||
.const_int(index as u64, false),
|
||||
],
|
||||
binding.r#type.unwrap_or_default().into_llvm(context),
|
||||
|
||||
Reference in New Issue
Block a user