mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 20:21:07 +00:00
Compare commits
5 Commits
v0.4.0
...
cl/optsize
| Author | SHA1 | Date | |
|---|---|---|---|
| af8074cfde | |||
| bb3b6ddb41 | |||
| dfe56f9306 | |||
| 63011b6d24 | |||
| d40ef3e462 |
@@ -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::intrinsics::Intrinsics as PolkaVMIntrinsicFunction;
|
||||||
pub use self::polkavm::context::function::llvm_runtime::LLVMRuntime as PolkaVMLLVMRuntime;
|
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::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::Division as PolkaVMDivisionFunction;
|
||||||
pub use self::polkavm::context::function::runtime::arithmetics::Remainder as PolkaVMRemainderFunction;
|
pub use self::polkavm::context::function::runtime::arithmetics::Remainder as PolkaVMRemainderFunction;
|
||||||
pub use self::polkavm::context::function::runtime::arithmetics::SignedDivision as PolkaVMSignedDivisionFunction;
|
pub use self::polkavm::context::function::runtime::arithmetics::SignedDivision as PolkaVMSignedDivisionFunction;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ pub mod r#return;
|
|||||||
pub mod runtime;
|
pub mod runtime;
|
||||||
pub mod yul_data;
|
pub mod yul_data;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
use inkwell::debug_info::AsDIScope;
|
use inkwell::debug_info::AsDIScope;
|
||||||
|
|
||||||
@@ -29,6 +29,10 @@ pub struct Function<'ctx> {
|
|||||||
declaration: Declaration<'ctx>,
|
declaration: Declaration<'ctx>,
|
||||||
/// The stack representation.
|
/// The stack representation.
|
||||||
stack: HashMap<String, Pointer<'ctx>>,
|
stack: HashMap<String, Pointer<'ctx>>,
|
||||||
|
/// The stack variables buffer.
|
||||||
|
stack_variables: inkwell::values::GlobalValue<'ctx>,
|
||||||
|
/// The stack variable names to slot mapping.
|
||||||
|
stack_slots: BTreeMap<String, usize>,
|
||||||
/// The return value entity.
|
/// The return value entity.
|
||||||
r#return: Return<'ctx>,
|
r#return: Return<'ctx>,
|
||||||
|
|
||||||
@@ -53,6 +57,7 @@ impl<'ctx> Function<'ctx> {
|
|||||||
name: String,
|
name: String,
|
||||||
declaration: Declaration<'ctx>,
|
declaration: Declaration<'ctx>,
|
||||||
r#return: Return<'ctx>,
|
r#return: Return<'ctx>,
|
||||||
|
stack_variables: inkwell::values::GlobalValue<'ctx>,
|
||||||
|
|
||||||
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
|
entry_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||||
return_block: inkwell::basic_block::BasicBlock<'ctx>,
|
return_block: inkwell::basic_block::BasicBlock<'ctx>,
|
||||||
@@ -61,6 +66,8 @@ impl<'ctx> Function<'ctx> {
|
|||||||
name,
|
name,
|
||||||
declaration,
|
declaration,
|
||||||
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
|
stack: HashMap::with_capacity(Self::STACK_HASHMAP_INITIAL_CAPACITY),
|
||||||
|
stack_variables,
|
||||||
|
stack_slots: BTreeMap::new(),
|
||||||
r#return,
|
r#return,
|
||||||
|
|
||||||
entry_block,
|
entry_block,
|
||||||
@@ -279,4 +286,45 @@ impl<'ctx> Function<'ctx> {
|
|||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("The Yul data must have been initialized")
|
.expect("The Yul data must have been initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the stack variables global value.
|
||||||
|
pub fn stack_variables(&self) -> inkwell::values::GlobalValue<'ctx> {
|
||||||
|
self.stack_variables
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the slot for the given variable name.
|
||||||
|
pub fn stack_variable_slot(&mut self, name: String) -> usize {
|
||||||
|
let len = self.stack_slots.len();
|
||||||
|
*self.stack_slots.entry(name).or_insert_with(|| len)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// References the stack variable `name`.
|
||||||
|
pub fn stack_variable_pointer<D: crate::PolkaVMDependency + Clone>(
|
||||||
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
context: &mut super::Context<'ctx, D>,
|
||||||
|
) -> Pointer<'ctx> {
|
||||||
|
if let Some(pointer) = self.get_stack_pointer(&name) {
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pointer_name = format!("var_{}", &name);
|
||||||
|
let slot = self.stack_variable_slot(name);
|
||||||
|
Pointer::new(
|
||||||
|
context.word_type(),
|
||||||
|
Default::default(),
|
||||||
|
unsafe {
|
||||||
|
context.builder().build_gep(
|
||||||
|
context.word_type().array_type(0),
|
||||||
|
self.stack_variables().as_pointer_value(),
|
||||||
|
&[
|
||||||
|
context.xlen_type().const_zero(),
|
||||||
|
context.xlen_type().const_int(slot as u64, false),
|
||||||
|
],
|
||||||
|
&pointer_name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,65 @@ use crate::polkavm::context::Context;
|
|||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
use crate::polkavm::WriteLLVM;
|
use crate::polkavm::WriteLLVM;
|
||||||
|
|
||||||
|
/// Implements the division operator according to the EVM specification.
|
||||||
|
pub struct Addition;
|
||||||
|
|
||||||
|
impl<D> RuntimeFunction<D> 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<Option<inkwell::values::BasicValueEnum<'ctx>>> {
|
||||||
|
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<D> WriteLLVM<D> for Addition
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Implements the division operator according to the EVM specification.
|
/// Implements the division operator according to the EVM specification.
|
||||||
pub struct Division;
|
pub struct Division;
|
||||||
|
|
||||||
|
|||||||
@@ -503,10 +503,17 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let stack_variables = format!("__vars_{name}");
|
||||||
|
self.declare_global(
|
||||||
|
&stack_variables,
|
||||||
|
self.word_type().array_type(0),
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
let function = Function::new(
|
let function = Function::new(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
FunctionDeclaration::new(r#type, value),
|
FunctionDeclaration::new(r#type, value),
|
||||||
r#return,
|
r#return,
|
||||||
|
self.get_global(&stack_variables).unwrap().value,
|
||||||
entry_block,
|
entry_block,
|
||||||
return_block,
|
return_block,
|
||||||
);
|
);
|
||||||
@@ -1271,6 +1278,20 @@ where
|
|||||||
where
|
where
|
||||||
T: BasicType<'ctx>,
|
T: BasicType<'ctx>,
|
||||||
{
|
{
|
||||||
|
let argument_types: Vec<inkwell::types::BasicMetadataTypeEnum> =
|
||||||
|
vec![self.llvm().ptr_type(Default::default()).into(); return_values_size]
|
||||||
|
.into_iter()
|
||||||
|
.chain(
|
||||||
|
argument_types
|
||||||
|
.as_slice()
|
||||||
|
.iter()
|
||||||
|
.map(T::as_basic_type_enum)
|
||||||
|
.map(inkwell::types::BasicMetadataTypeEnum::from),
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
self.void_type().fn_type(&argument_types.as_slice(), false)
|
||||||
|
|
||||||
|
/*
|
||||||
let argument_types: Vec<inkwell::types::BasicMetadataTypeEnum> = argument_types
|
let argument_types: Vec<inkwell::types::BasicMetadataTypeEnum> = argument_types
|
||||||
.as_slice()
|
.as_slice()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -1287,6 +1308,7 @@ where
|
|||||||
.structure_type(vec![self.word_type().as_basic_type_enum(); size].as_slice())
|
.structure_type(vec![self.word_type().as_basic_type_enum(); size].as_slice())
|
||||||
.fn_type(argument_types.as_slice(), false),
|
.fn_type(argument_types.as_slice(), false),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modifies the call site value, setting the default attributes.
|
/// Modifies the call site value, setting the default attributes.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use crate::polkavm::context::Context;
|
|||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
|
|
||||||
pub mod heap;
|
pub mod heap;
|
||||||
|
//pub mod stack;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
|
||||||
/// The LLVM pointer.
|
/// The LLVM pointer.
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
//! The revive simulated EVM stack variable functions.
|
||||||
|
|
||||||
|
use inkwell::values::BasicValueEnum;
|
||||||
|
|
||||||
|
use crate::polkavm::context::runtime::RuntimeFunction;
|
||||||
|
use crate::polkavm::context::Context;
|
||||||
|
use crate::polkavm::Dependency;
|
||||||
|
use crate::polkavm::WriteLLVM;
|
||||||
|
|
||||||
|
/// Load a word size value from a heap pointer.
|
||||||
|
pub struct DeclareVariable;
|
||||||
|
|
||||||
|
impl<D> RuntimeFunction<D> for DeclareVariable
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
const NAME: &'static str = "__revive_declare_variable";
|
||||||
|
|
||||||
|
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||||
|
context
|
||||||
|
.llvm
|
||||||
|
.ptr_type(Default::default())
|
||||||
|
.fn_type(&[context.xlen_type().into()], false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_body<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &mut Context<'ctx, D>,
|
||||||
|
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
|
let length = context
|
||||||
|
.xlen_type()
|
||||||
|
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
||||||
|
let pointer = context.build_heap_gep(offset, length)?;
|
||||||
|
let value = context
|
||||||
|
.builder()
|
||||||
|
.build_load(context.word_type(), pointer.value, "value")?;
|
||||||
|
context
|
||||||
|
.basic_block()
|
||||||
|
.get_last_instruction()
|
||||||
|
.expect("Always exists")
|
||||||
|
.set_alignment(revive_common::BYTE_LENGTH_BYTE as u32)
|
||||||
|
.expect("Alignment is valid");
|
||||||
|
|
||||||
|
let swapped_value = context.build_byte_swap(value)?;
|
||||||
|
Ok(Some(swapped_value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> WriteLLVM<D> for LoadWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Store a word size value through a heap pointer.
|
||||||
|
pub struct StoreWord;
|
||||||
|
|
||||||
|
impl<D> RuntimeFunction<D> for StoreWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
const NAME: &'static str = "__revive_store_heap_word";
|
||||||
|
|
||||||
|
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||||
|
context.void_type().fn_type(
|
||||||
|
&[context.xlen_type().into(), context.word_type().into()],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_body<'ctx>(
|
||||||
|
&self,
|
||||||
|
context: &mut Context<'ctx, D>,
|
||||||
|
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
|
let offset = Self::paramater(context, 0).into_int_value();
|
||||||
|
let length = context
|
||||||
|
.xlen_type()
|
||||||
|
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false);
|
||||||
|
let pointer = context.build_heap_gep(offset, length)?;
|
||||||
|
|
||||||
|
let value = context.build_byte_swap(Self::paramater(context, 1))?;
|
||||||
|
|
||||||
|
context
|
||||||
|
.builder()
|
||||||
|
.build_store(pointer.value, value)?
|
||||||
|
.set_alignment(revive_common::BYTE_LENGTH_BYTE as u32)
|
||||||
|
.expect("Alignment is valid");
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> WriteLLVM<D> for StoreWord
|
||||||
|
where
|
||||||
|
D: Dependency + Clone,
|
||||||
|
{
|
||||||
|
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||||
|
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ use inkwell::values::BasicValue;
|
|||||||
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;
|
||||||
|
use crate::PolkaVMAdditionFunction;
|
||||||
use crate::PolkaVMDivisionFunction;
|
use crate::PolkaVMDivisionFunction;
|
||||||
use crate::PolkaVMRemainderFunction;
|
use crate::PolkaVMRemainderFunction;
|
||||||
use crate::PolkaVMSignedDivisionFunction;
|
use crate::PolkaVMSignedDivisionFunction;
|
||||||
@@ -13,16 +14,20 @@ use crate::PolkaVMSignedRemainderFunction;
|
|||||||
/// Translates the arithmetic addition.
|
/// Translates the arithmetic addition.
|
||||||
pub fn addition<'ctx, D>(
|
pub fn addition<'ctx, D>(
|
||||||
context: &mut Context<'ctx, D>,
|
context: &mut Context<'ctx, D>,
|
||||||
operand_1: inkwell::values::IntValue<'ctx>,
|
binding: inkwell::values::PointerValue<'ctx>,
|
||||||
operand_2: inkwell::values::IntValue<'ctx>,
|
operand_1: inkwell::values::PointerValue<'ctx>,
|
||||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
operand_2: inkwell::values::PointerValue<'ctx>,
|
||||||
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
Ok(context
|
let declaration = <PolkaVMAdditionFunction as RuntimeFunction<D>>::declaration(context);
|
||||||
.builder()
|
context.build_call(
|
||||||
.build_int_add(operand_1, operand_2, "addition_result")?
|
declaration,
|
||||||
.as_basic_value_enum())
|
&[binding.into(), operand_1.into(), operand_2.into()],
|
||||||
|
"add",
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the arithmetic subtraction.
|
/// Translates the arithmetic subtraction.
|
||||||
|
|||||||
@@ -115,13 +115,29 @@ impl<D> revive_llvm_context::PolkaVMWriteLLVM<D> for Assignment
|
|||||||
where
|
where
|
||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
fn into_llvm(
|
fn into_llvm<'ctx>(
|
||||||
mut self,
|
mut self,
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> 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)? {
|
let bindings: Vec<(String, revive_llvm_context::PolkaVMPointer<'ctx>)> = self
|
||||||
|
.bindings
|
||||||
|
.into_iter()
|
||||||
|
.map(|binding| {
|
||||||
|
(
|
||||||
|
binding.inner.clone(),
|
||||||
|
context
|
||||||
|
.current_function()
|
||||||
|
.borrow_mut()
|
||||||
|
.stack_variable_pointer(binding.inner, context),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
self.initializer.into_llvm(bindings.as_slice(), context)?;
|
||||||
|
/*
|
||||||
|
let value = match self.initializer.into_llvm(bindings.as_slice(), context)? {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
@@ -181,6 +197,8 @@ where
|
|||||||
context.build_store(binding_pointer, value)?;
|
context.build_store(binding_pointer, value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ where
|
|||||||
block.into_llvm(context)?;
|
block.into_llvm(context)?;
|
||||||
}
|
}
|
||||||
Statement::Expression(expression) => {
|
Statement::Expression(expression) => {
|
||||||
expression.into_llvm(context)?;
|
expression.into_llvm(&[], context)?;
|
||||||
}
|
}
|
||||||
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)?,
|
||||||
|
|||||||
@@ -117,8 +117,9 @@ impl FunctionCall {
|
|||||||
/// Converts the function call into an LLVM value.
|
/// Converts the function call into an LLVM value.
|
||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
mut self,
|
mut self,
|
||||||
|
bindings: &[(String, revive_llvm_context::PolkaVMPointer<'ctx>)],
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<Option<inkwell::values::BasicValueEnum<'ctx>>>
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
@@ -127,15 +128,26 @@ impl FunctionCall {
|
|||||||
|
|
||||||
match self.name {
|
match self.name {
|
||||||
Name::UserDefined(name) => {
|
Name::UserDefined(name) => {
|
||||||
let mut values = Vec::with_capacity(self.arguments.len());
|
let mut values = Vec::with_capacity(bindings.len() + self.arguments.len());
|
||||||
for argument in self.arguments.into_iter().rev() {
|
for (n, argument) in self.arguments.into_iter().rev().enumerate() {
|
||||||
|
let id = format!("arg_{n}");
|
||||||
|
let binding_pointer = context.build_alloca(context.word_type(), &id);
|
||||||
let value = argument
|
let value = argument
|
||||||
.into_llvm(context)?
|
.into_llvm(&[(id, binding_pointer)], context)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?;
|
.as_pointer(context)?
|
||||||
|
.value
|
||||||
|
.as_basic_value_enum();
|
||||||
values.push(value);
|
values.push(value);
|
||||||
}
|
}
|
||||||
values.reverse();
|
values.reverse();
|
||||||
|
|
||||||
|
let values = bindings
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, pointer)| pointer.value.as_basic_value_enum())
|
||||||
|
.chain(values.into_iter())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let function = context.get_function(name.as_str()).ok_or_else(|| {
|
let function = context.get_function(name.as_str()).ok_or_else(|| {
|
||||||
anyhow::anyhow!("{} Undeclared function `{}`", location, name)
|
anyhow::anyhow!("{} Undeclared function `{}`", location, name)
|
||||||
})?;
|
})?;
|
||||||
@@ -152,23 +164,24 @@ impl FunctionCall {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_value = context.build_call(
|
let _return_value = context.build_call(
|
||||||
function.borrow().declaration(),
|
function.borrow().declaration(),
|
||||||
values.as_slice(),
|
values.as_slice(),
|
||||||
format!("{name}_call").as_str(),
|
format!("{name}_call").as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(return_value)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Name::Add => {
|
Name::Add => {
|
||||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||||
revive_llvm_context::polkavm_evm_arithmetic::addition(
|
revive_llvm_context::polkavm_evm_arithmetic::addition(
|
||||||
context,
|
context,
|
||||||
arguments[0].into_int_value(),
|
bindings,
|
||||||
arguments[1].into_int_value(),
|
arguments[0].into_pointer_value(),
|
||||||
)
|
arguments[1].into_pointer_value(),
|
||||||
.map(Some)
|
)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Name::Sub => {
|
Name::Sub => {
|
||||||
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
let arguments = self.pop_arguments_llvm::<D, 2>(context)?;
|
||||||
@@ -987,10 +1000,12 @@ impl FunctionCall {
|
|||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
let mut arguments = Vec::with_capacity(N);
|
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(
|
arguments.push(
|
||||||
expression
|
expression
|
||||||
.into_llvm(context)?
|
.into_llvm(&[(name, pointer)], context)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?,
|
.access(context)?,
|
||||||
);
|
);
|
||||||
@@ -1009,8 +1024,14 @@ impl FunctionCall {
|
|||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
let mut arguments = Vec::with_capacity(N);
|
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() {
|
||||||
arguments.push(expression.into_llvm(context)?.expect("Always exists"));
|
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();
|
arguments.reverse();
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ impl Literal {
|
|||||||
/// Converts the literal into its LLVM.
|
/// Converts the literal into its LLVM.
|
||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
self,
|
self,
|
||||||
|
binding: Option<(String, revive_llvm_context::PolkaVMPointer<'ctx>)>,
|
||||||
context: &revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<revive_llvm_context::PolkaVMArgument<'ctx>>
|
) -> anyhow::Result<revive_llvm_context::PolkaVMArgument<'ctx>>
|
||||||
where
|
where
|
||||||
@@ -97,7 +98,17 @@ impl Literal {
|
|||||||
BooleanLiteral::True => num::BigUint::one(),
|
BooleanLiteral::True => num::BigUint::one(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_constant(constant))
|
match binding {
|
||||||
|
Some((id, pointer)) => {
|
||||||
|
context.build_store(pointer, value)?;
|
||||||
|
Ok(revive_llvm_context::PolkaVMArgument::pointer(pointer, id)
|
||||||
|
.with_constant(constant))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Ok(revive_llvm_context::PolkaVMArgument::value(value)
|
||||||
|
.with_constant(constant))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LexicalLiteral::Integer(inner) => {
|
LexicalLiteral::Integer(inner) => {
|
||||||
let r#type = self.yul_type.unwrap_or_default().into_llvm(context);
|
let r#type = self.yul_type.unwrap_or_default().into_llvm(context);
|
||||||
@@ -125,7 +136,17 @@ impl Literal {
|
|||||||
}
|
}
|
||||||
.expect("Always valid");
|
.expect("Always valid");
|
||||||
|
|
||||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_constant(constant))
|
match binding {
|
||||||
|
Some((id, pointer)) => {
|
||||||
|
context.build_store(pointer, value)?;
|
||||||
|
Ok(revive_llvm_context::PolkaVMArgument::pointer(pointer, id)
|
||||||
|
.with_constant(constant))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Ok(revive_llvm_context::PolkaVMArgument::value(value)
|
||||||
|
.with_constant(constant))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LexicalLiteral::String(inner) => {
|
LexicalLiteral::String(inner) => {
|
||||||
let string = inner.inner;
|
let string = inner.inner;
|
||||||
@@ -216,7 +237,16 @@ impl Literal {
|
|||||||
)
|
)
|
||||||
.expect("The value is valid")
|
.expect("The value is valid")
|
||||||
.as_basic_value_enum();
|
.as_basic_value_enum();
|
||||||
Ok(revive_llvm_context::PolkaVMArgument::value(value).with_original(string))
|
match binding {
|
||||||
|
Some((id, pointer)) => {
|
||||||
|
context.build_store(pointer, value)?;
|
||||||
|
Ok(revive_llvm_context::PolkaVMArgument::pointer(pointer, id)
|
||||||
|
.with_original(string))
|
||||||
|
}
|
||||||
|
None => Ok(
|
||||||
|
revive_llvm_context::PolkaVMArgument::value(value).with_original(string)
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ impl Expression {
|
|||||||
/// Converts the expression into an LLVM value.
|
/// Converts the expression into an LLVM value.
|
||||||
pub fn into_llvm<'ctx, D>(
|
pub fn into_llvm<'ctx, D>(
|
||||||
self,
|
self,
|
||||||
|
bindings: &[(String, revive_llvm_context::PolkaVMPointer<'ctx>)],
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
) -> anyhow::Result<Option<revive_llvm_context::PolkaVMArgument<'ctx>>>
|
||||||
where
|
where
|
||||||
@@ -108,7 +109,13 @@ impl Expression {
|
|||||||
match self {
|
match self {
|
||||||
Self::Literal(literal) => literal
|
Self::Literal(literal) => literal
|
||||||
.clone()
|
.clone()
|
||||||
.into_llvm(context)
|
.into_llvm(
|
||||||
|
bindings
|
||||||
|
.first()
|
||||||
|
.to_owned()
|
||||||
|
.map(|(id, binding)| (id.to_string(), *binding)),
|
||||||
|
context,
|
||||||
|
)
|
||||||
.map_err(|error| {
|
.map_err(|error| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"{} Invalid literal `{}`: {}",
|
"{} Invalid literal `{}`: {}",
|
||||||
@@ -138,9 +145,10 @@ impl Expression {
|
|||||||
_ => argument,
|
_ => argument,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Self::FunctionCall(call) => Ok(call
|
Self::FunctionCall(call) => {
|
||||||
.into_llvm(context)?
|
call.into_llvm(bindings, context)?;
|
||||||
.map(revive_llvm_context::PolkaVMArgument::value)),
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,9 +74,10 @@ where
|
|||||||
|
|
||||||
context.build_unconditional_branch(condition_block);
|
context.build_unconditional_branch(condition_block);
|
||||||
context.set_basic_block(condition_block);
|
context.set_basic_block(condition_block);
|
||||||
|
let binding_pointer = context.build_alloca(context.word_type(), "if_condition");
|
||||||
let condition = self
|
let condition = self
|
||||||
.condition
|
.condition
|
||||||
.into_llvm(context)?
|
.into_llvm(&[("todo".to_string(), binding_pointer)], context)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?
|
.access(context)?
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|||||||
@@ -231,8 +231,80 @@ where
|
|||||||
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
context: &mut revive_llvm_context::PolkaVMContext<D>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
context.set_current_function(self.identifier.as_str(), Some(self.location.line))?;
|
context.set_current_function(self.identifier.as_str(), Some(self.location.line))?;
|
||||||
|
|
||||||
context.set_basic_block(context.current_function().borrow().entry_block());
|
context.set_basic_block(context.current_function().borrow().entry_block());
|
||||||
|
|
||||||
|
let return_types: Vec<_> = self
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|argument| {
|
||||||
|
let yul_type = argument.r#type.to_owned().unwrap_or_default();
|
||||||
|
yul_type.into_llvm(context)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for (index, argument) in self.result.iter().enumerate() {
|
||||||
|
let pointer = context
|
||||||
|
.current_function()
|
||||||
|
.borrow()
|
||||||
|
.get_nth_param(index)
|
||||||
|
.into_pointer_value();
|
||||||
|
let pointer = revive_llvm_context::PolkaVMPointer::new(
|
||||||
|
return_types[index],
|
||||||
|
Default::default(),
|
||||||
|
pointer,
|
||||||
|
);
|
||||||
|
context.build_store(pointer, pointer.r#type.const_zero())?;
|
||||||
|
context
|
||||||
|
.current_function()
|
||||||
|
.borrow_mut()
|
||||||
|
.insert_stack_pointer(argument.inner.clone(), pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let argument_types: Vec<_> = self
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|argument| {
|
||||||
|
let yul_type = argument.r#type.to_owned().unwrap_or_default();
|
||||||
|
yul_type.into_llvm(context)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for (index, argument) in self.arguments.iter().enumerate() {
|
||||||
|
let pointer = context
|
||||||
|
.current_function()
|
||||||
|
.borrow()
|
||||||
|
.get_nth_param(index + self.result.len())
|
||||||
|
.into_pointer_value();
|
||||||
|
let pointer = revive_llvm_context::PolkaVMPointer::new(
|
||||||
|
argument_types[index],
|
||||||
|
Default::default(),
|
||||||
|
pointer,
|
||||||
|
);
|
||||||
|
context
|
||||||
|
.current_function()
|
||||||
|
.borrow_mut()
|
||||||
|
.insert_stack_pointer(argument.inner.clone(), pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.body.into_llvm(context)?;
|
||||||
|
context.set_debug_location(self.location.line, 0, None)?;
|
||||||
|
|
||||||
|
match context
|
||||||
|
.basic_block()
|
||||||
|
.get_last_instruction()
|
||||||
|
.map(|instruction| instruction.get_opcode())
|
||||||
|
{
|
||||||
|
Some(inkwell::values::InstructionOpcode::Br) => {}
|
||||||
|
Some(inkwell::values::InstructionOpcode::Switch) => {}
|
||||||
|
_ => context
|
||||||
|
.build_unconditional_branch(context.current_function().borrow().return_block()),
|
||||||
|
}
|
||||||
|
|
||||||
|
context.set_basic_block(context.current_function().borrow().return_block());
|
||||||
|
context.build_return(None);
|
||||||
|
|
||||||
|
context.pop_debug_scope();
|
||||||
|
|
||||||
|
/*
|
||||||
let r#return = context.current_function().borrow().r#return();
|
let r#return = context.current_function().borrow().r#return();
|
||||||
match r#return {
|
match r#return {
|
||||||
revive_llvm_context::PolkaVMFunctionReturn::None => {}
|
revive_llvm_context::PolkaVMFunctionReturn::None => {}
|
||||||
@@ -319,6 +391,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.pop_debug_scope();
|
context.pop_debug_scope();
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,11 @@ 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 binding_pointer = context.build_alloca(context.word_type(), "if_condition");
|
||||||
context.set_debug_location(self.location.line, 0, None)?;
|
context.set_debug_location(self.location.line, 0, None)?;
|
||||||
let condition = self
|
let condition = self
|
||||||
.condition
|
.condition
|
||||||
.into_llvm(context)?
|
.into_llvm(&[("todo".to_string(), binding_pointer)], context)?
|
||||||
.expect("Always exists")
|
.expect("Always exists")
|
||||||
.access(context)?
|
.access(context)?
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ where
|
|||||||
revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<3>.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?;
|
revive_llvm_context::PolkaVMEventLogFunction::<4>.declare(context)?;
|
||||||
|
|
||||||
|
revive_llvm_context::PolkaVMAdditionFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
|
revive_llvm_context::PolkaVMDivisionFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
|
revive_llvm_context::PolkaVMSignedDivisionFunction.declare(context)?;
|
||||||
revive_llvm_context::PolkaVMRemainderFunction.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::<3>.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMEventLogFunction::<4>.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::PolkaVMDivisionFunction.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
|
revive_llvm_context::PolkaVMSignedDivisionFunction.into_llvm(context)?;
|
||||||
revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
|
revive_llvm_context::PolkaVMRemainderFunction.into_llvm(context)?;
|
||||||
|
|||||||
@@ -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)?;
|
let scrutinee = self.expression.into_llvm(&[], context)?;
|
||||||
|
|
||||||
if self.cases.is_empty() {
|
if self.cases.is_empty() {
|
||||||
if let Some(block) = self.default {
|
if let Some(block) = self.default {
|
||||||
@@ -137,7 +137,7 @@ where
|
|||||||
|
|
||||||
let mut branches = Vec::with_capacity(self.cases.len());
|
let mut branches = Vec::with_capacity(self.cases.len());
|
||||||
for (index, case) in self.cases.into_iter().enumerate() {
|
for (index, case) in self.cases.into_iter().enumerate() {
|
||||||
let constant = case.literal.into_llvm(context)?.access(context)?;
|
let constant = case.literal.into_llvm(None, context)?.access(context)?;
|
||||||
|
|
||||||
let expression_block = context
|
let expression_block = context
|
||||||
.append_basic_block(format!("switch_case_branch_{}_block", index + 1).as_str());
|
.append_basic_block(format!("switch_case_branch_{}_block", index + 1).as_str());
|
||||||
|
|||||||
@@ -99,6 +99,25 @@ where
|
|||||||
mut self,
|
mut self,
|
||||||
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let bindings: Vec<(String, revive_llvm_context::PolkaVMPointer<'ctx>)> = self
|
||||||
|
.bindings
|
||||||
|
.into_iter()
|
||||||
|
.map(|binding| {
|
||||||
|
(
|
||||||
|
binding.inner.clone(),
|
||||||
|
context
|
||||||
|
.current_function()
|
||||||
|
.borrow_mut()
|
||||||
|
.stack_variable_pointer(binding.inner, context),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if let Some(expression) = self.expression {
|
||||||
|
expression.into_llvm(&bindings, context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if self.bindings.len() == 1 {
|
if self.bindings.len() == 1 {
|
||||||
let identifier = self.bindings.remove(0);
|
let identifier = self.bindings.remove(0);
|
||||||
context.set_debug_location(self.location.line, 0, None)?;
|
context.set_debug_location(self.location.line, 0, None)?;
|
||||||
@@ -213,6 +232,7 @@ where
|
|||||||
})?;
|
})?;
|
||||||
context.build_store(pointer, value)?;
|
context.build_store(pointer, value)?;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,10 +70,11 @@ impl Type {
|
|||||||
D: revive_llvm_context::PolkaVMDependency + Clone,
|
D: revive_llvm_context::PolkaVMDependency + Clone,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
|
//Self::Bool => context.integer_type(revive_common::BIT_LENGTH_BOOLEAN),
|
||||||
Self::Int(bitlength) => context.integer_type(bitlength),
|
//Self::Int(bitlength) => context.integer_type(bitlength),
|
||||||
Self::UInt(bitlength) => context.integer_type(bitlength),
|
Self::UInt(bitlength) => context.integer_type(bitlength),
|
||||||
Self::Custom(_) => context.word_type(),
|
//Self::Custom(_) => context.word_type(),
|
||||||
|
_ => panic!("oh no"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user