mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-24 03:08:03 +00:00
switch to pallet_revive runtime (#40)
Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
use inkwell::{
|
||||
builder::Builder,
|
||||
context::Context,
|
||||
module::Module,
|
||||
types::{BasicType, StructType},
|
||||
values::{BasicValue, PointerValue},
|
||||
};
|
||||
|
||||
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
||||
pub fn min_stack_size<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
size: u32,
|
||||
) -> Module<'context> {
|
||||
let module = context.create_module(module_name);
|
||||
module.set_inline_assembly(&format!(
|
||||
".pushsection .polkavm_min_stack_size,\"\",@progbits
|
||||
.word {size}
|
||||
.popsection"
|
||||
));
|
||||
module
|
||||
}
|
||||
|
||||
pub struct Spill<'a, 'ctx> {
|
||||
pointer: PointerValue<'ctx>,
|
||||
builder: &'a Builder<'ctx>,
|
||||
r#type: StructType<'ctx>,
|
||||
current_field: u32,
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> Spill<'a, 'ctx> {
|
||||
pub fn new(
|
||||
builder: &'a Builder<'ctx>,
|
||||
r#type: StructType<'ctx>,
|
||||
name: &str,
|
||||
) -> anyhow::Result<Self> {
|
||||
Ok(Self {
|
||||
pointer: builder.build_alloca(r#type, name)?,
|
||||
builder,
|
||||
r#type,
|
||||
current_field: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next<V: BasicValue<'ctx>>(mut self, value: V) -> anyhow::Result<Self> {
|
||||
let field_pointer = self.builder.build_struct_gep(
|
||||
self.r#type,
|
||||
self.pointer,
|
||||
self.current_field,
|
||||
&format!("spill_parameter_{}", self.current_field),
|
||||
)?;
|
||||
self.builder.build_store(field_pointer, value)?;
|
||||
self.current_field += 1;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn skip(mut self) -> Self {
|
||||
self.current_field += 1;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn done(self) -> PointerValue<'ctx> {
|
||||
assert!(
|
||||
self.r#type
|
||||
.get_field_type_at_index(self.current_field)
|
||||
.is_none(),
|
||||
"there must not be any missing parameters"
|
||||
);
|
||||
|
||||
self.pointer
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instantiate(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// code_hash_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// ref_time_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// proof_size_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// deposit_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// value_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// address_len_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// salt_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// salt_len: u32
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
],
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn call(context: &Context) -> StructType {
|
||||
context.struct_type(
|
||||
&[
|
||||
// flags: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// address_ptr:
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// ref_time_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// proof_size_limit: u64,
|
||||
context.i64_type().as_basic_type_enum(),
|
||||
// deposit_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// value_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// input_data_len: u32,
|
||||
context.i32_type().as_basic_type_enum(),
|
||||
// output_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
// output_len_ptr: u32,
|
||||
context.ptr_type(Default::default()).as_basic_type_enum(),
|
||||
],
|
||||
true,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting
|
||||
//! with the `pallet-revive` runtime API.
|
||||
//! At present, the contracts pallet requires blobs to export `call` and `deploy`,
|
||||
//! and offers a bunch of [runtime API methods][1]. The provided [module] implements
|
||||
//! those exports and imports.
|
||||
//! [0]: [https://crates.io/crates/polkavm]
|
||||
//! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html]
|
||||
|
||||
pub mod calling_convention;
|
||||
pub mod polkavm_exports;
|
||||
pub mod polkavm_imports;
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "polkavm_guest.h"
|
||||
|
||||
extern void __entry(bool);
|
||||
|
||||
static void deploy() {
|
||||
__entry(true);
|
||||
}
|
||||
|
||||
static void call() {
|
||||
__entry(false);
|
||||
}
|
||||
|
||||
POLKAVM_EXPORT(void, deploy)
|
||||
POLKAVM_EXPORT(void, call)
|
||||
@@ -0,0 +1,29 @@
|
||||
use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/polkavm_exports.rs"));
|
||||
|
||||
/// Creates a LLVM module from the [BITCODE].
|
||||
/// The module exports `call` and `deploy` functions (which are named thereafter).
|
||||
/// Returns `Error` if the bitcode fails to parse, which should never happen.
|
||||
pub fn module<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
) -> Result<Module<'context>, LLVMString> {
|
||||
let buf = MemoryBuffer::create_from_memory_range(BITCODE, module_name);
|
||||
Module::parse_bitcode_from_buffer(&buf, context)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::polkavm_exports;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||
let context = inkwell::context::Context::create();
|
||||
let module = polkavm_exports::module(&context, "polkavm_exports").unwrap();
|
||||
|
||||
assert!(module.get_function("call").is_some());
|
||||
assert!(module.get_function("deploy").is_some());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// Vendored from: https://github.com/koute/polkavm/blob/master/capi/polkavm_guest.h
|
||||
|
||||
#ifndef POLKAVM_GUEST_H_
|
||||
#define POLKAVM_GUEST_H_
|
||||
|
||||
#define POLKAVM_JOIN_IMPL(X,Y) X##Y
|
||||
#define POLKAVM_JOIN(X,Y) POLKAVM_JOIN_IMPL(X, Y)
|
||||
#define POLKAVM_UNIQUE(X) POLKAVM_JOIN(X, __COUNTER__)
|
||||
|
||||
#define POLKAVM_REGS_FOR_TY_void 0
|
||||
#define POLKAVM_REGS_FOR_TY_i32 1
|
||||
#define POLKAVM_REGS_FOR_TY_i64 2
|
||||
|
||||
#define POLKAVM_REGS_FOR_TY_int8_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_uint8_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_int16_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_uint16_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_int32_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_uint32_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_int64_t POLKAVM_REGS_FOR_TY_i64
|
||||
#define POLKAVM_REGS_FOR_TY_uint64_t POLKAVM_REGS_FOR_TY_i64
|
||||
#define POLKAVM_REGS_FOR_TY_int POLKAVM_REGS_FOR_TY_i32
|
||||
|
||||
#ifdef _LP64
|
||||
#define POLKAVM_REGS_FOR_TY_size_t POLKAVM_REGS_FOR_TY_i64
|
||||
#define POLKAVM_REGS_FOR_TY_long POLKAVM_REGS_FOR_TY_i64
|
||||
#else
|
||||
#define POLKAVM_REGS_FOR_TY_size_t POLKAVM_REGS_FOR_TY_i32
|
||||
#define POLKAVM_REGS_FOR_TY_long POLKAVM_REGS_FOR_TY_i32
|
||||
#endif
|
||||
|
||||
#define POLKAVM_COUNT_ARGS(...) POLKAVM_COUNT_ARGS_IMPL(0, ## __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#define POLKAVM_COUNT_ARGS_IMPL(_0, _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, count, ...) count
|
||||
|
||||
#define POLKAVM_REGS_FOR_TY(X) POLKAVM_JOIN(POLKAVM_REGS_FOR_TY_, X)
|
||||
|
||||
#define POLKAVM_ARG_ASM_4_0()
|
||||
#define POLKAVM_ARG_ASM_4_1(A) \
|
||||
".byte %[arg_1]\n"
|
||||
#define POLKAVM_ARG_ASM_4_2(A, B) \
|
||||
".byte %[arg_1]\n" \
|
||||
".byte %[arg_2]\n"
|
||||
#define POLKAVM_ARG_ASM_4_3(A, B, C) \
|
||||
".byte %[arg_1]\n" \
|
||||
".byte %[arg_2]\n" \
|
||||
".byte %[arg_3]\n"
|
||||
#define POLKAVM_ARG_ASM_4_4(A, B, C, D) \
|
||||
".byte %[arg_1]\n" \
|
||||
".byte %[arg_2]\n" \
|
||||
".byte %[arg_3]\n" \
|
||||
".byte %[arg_4]\n"
|
||||
#define POLKAVM_ARG_ASM_4_5(A, B, C, D, E) \
|
||||
".byte %[arg_1]\n" \
|
||||
".byte %[arg_2]\n" \
|
||||
".byte %[arg_3]\n" \
|
||||
".byte %[arg_4]\n" \
|
||||
".byte %[arg_5]\n"
|
||||
#define POLKAVM_ARG_ASM_4_6(A, B, C, D, E, F) \
|
||||
".byte %[arg_1]\n" \
|
||||
".byte %[arg_2]\n" \
|
||||
".byte %[arg_3]\n" \
|
||||
".byte %[arg_4]\n" \
|
||||
".byte %[arg_5]\n" \
|
||||
".byte %[arg_6]\n"
|
||||
|
||||
#define POLKAVM_ARG_ASM_3(N, ...) POLKAVM_ARG_ASM_4_ ## N(__VA_ARGS__)
|
||||
#define POLKAVM_ARG_ASM_2(N, ...) POLKAVM_ARG_ASM_3(N, ## __VA_ARGS__)
|
||||
#define POLKAVM_ARG_ASM(...) POLKAVM_ARG_ASM_2(POLKAVM_COUNT_ARGS(__VA_ARGS__), ## __VA_ARGS__)
|
||||
|
||||
#define POLKAVM_COUNT_REGS_4_0() \
|
||||
0
|
||||
#define POLKAVM_COUNT_REGS_4_1(A) \
|
||||
POLKAVM_REGS_FOR_TY(A)
|
||||
#define POLKAVM_COUNT_REGS_4_2(A, B) \
|
||||
POLKAVM_REGS_FOR_TY(A) + POLKAVM_REGS_FOR_TY(B)
|
||||
#define POLKAVM_COUNT_REGS_4_3(A, B, C) \
|
||||
POLKAVM_REGS_FOR_TY(A) + POLKAVM_REGS_FOR_TY(B) + POLKAVM_REGS_FOR_TY(C)
|
||||
#define POLKAVM_COUNT_REGS_4_4(A, B, C, D) \
|
||||
POLKAVM_REGS_FOR_TY(A) + POLKAVM_REGS_FOR_TY(B) + POLKAVM_REGS_FOR_TY(C) + POLKAVM_REGS_FOR_TY(D)
|
||||
#define POLKAVM_COUNT_REGS_4_5(A, B, C, D, E) \
|
||||
POLKAVM_REGS_FOR_TY(A) + POLKAVM_REGS_FOR_TY(B) + POLKAVM_REGS_FOR_TY(C) + POLKAVM_REGS_FOR_TY(D) + POLKAVM_REGS_FOR_TY(E)
|
||||
#define POLKAVM_COUNT_REGS_4_6(A, B, C, D, E, F) \
|
||||
POLKAVM_REGS_FOR_TY(A) + POLKAVM_REGS_FOR_TY(B) + POLKAVM_REGS_FOR_TY(C) + POLKAVM_REGS_FOR_TY(D) + POLKAVM_REGS_FOR_TY(E) + POLKAVM_REGS_FOR_TY(F)
|
||||
|
||||
#define POLKAVM_COUNT_REGS_3(N, ...) POLKAVM_COUNT_REGS_4_ ## N(__VA_ARGS__)
|
||||
#define POLKAVM_COUNT_REGS_2(N, ...) POLKAVM_COUNT_REGS_3(N, ## __VA_ARGS__)
|
||||
#define POLKAVM_COUNT_REGS(...) POLKAVM_COUNT_REGS_2(POLKAVM_COUNT_ARGS(__VA_ARGS__), ## __VA_ARGS__)
|
||||
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_0()
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_1(A0) A0 a0
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_2(A0, A1) A0 a0, A1 a1
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_3(A0, A1, A2) A0 a0, A1 a1, A2 a2
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_4(A0, A1, A2, A3) A0 a0, A1 a1, A2 a2, A3 a3
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_5(A0, A1, A2, A3, A4) A0 a0, A1 a1, A2 a2, A3 a3, A4 a4
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_4_6(A0, A1, A2, A3, A4, A5) A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5
|
||||
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_3(N, ...) POLKAVM_IMPORT_ARGS_IMPL_4_ ## N(__VA_ARGS__)
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL_2(N, ...) POLKAVM_IMPORT_ARGS_IMPL_3(N, ## __VA_ARGS__)
|
||||
#define POLKAVM_IMPORT_ARGS_IMPL(...) POLKAVM_IMPORT_ARGS_IMPL_2(POLKAVM_COUNT_ARGS(__VA_ARGS__), ## __VA_ARGS__)
|
||||
|
||||
struct PolkaVM_Metadata {
|
||||
unsigned char version;
|
||||
unsigned int flags;
|
||||
unsigned int symbol_length;
|
||||
const char * symbol;
|
||||
unsigned char input_regs;
|
||||
unsigned char output_regs;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define POLKAVM_EXPORT(arg_return_ty, fn_name, ...) \
|
||||
static struct PolkaVM_Metadata POLKAVM_JOIN(fn_name, __EXPORT_METADATA) __attribute__ ((section(".polkavm_metadata"))) = { \
|
||||
1, 0, sizeof(#fn_name) - 1, #fn_name, POLKAVM_COUNT_REGS(__VA_ARGS__), POLKAVM_COUNT_REGS(arg_return_ty) \
|
||||
}; \
|
||||
static void __attribute__ ((naked, used)) POLKAVM_UNIQUE(polkavm_export_dummy)() { \
|
||||
__asm__( \
|
||||
".pushsection .polkavm_exports,\"R\",@note\n" \
|
||||
".byte 1\n" \
|
||||
".word %[metadata]\n" \
|
||||
".word %[function]\n" \
|
||||
".popsection\n" \
|
||||
: \
|
||||
: \
|
||||
[metadata] "i" (&POLKAVM_JOIN(fn_name, __EXPORT_METADATA)), \
|
||||
[function] "i" (fn_name) \
|
||||
: "memory" \
|
||||
); \
|
||||
}
|
||||
|
||||
#define POLKAVM_IMPORT(arg_return_ty, fn_name, ...) \
|
||||
static struct PolkaVM_Metadata POLKAVM_JOIN(fn_name, __IMPORT_METADATA) __attribute__ ((section(".polkavm_metadata"))) = { \
|
||||
1, 0, sizeof(#fn_name) - 1, #fn_name, POLKAVM_COUNT_REGS(__VA_ARGS__), POLKAVM_COUNT_REGS(arg_return_ty) \
|
||||
}; \
|
||||
static arg_return_ty __attribute__ ((naked, used)) fn_name(POLKAVM_IMPORT_ARGS_IMPL(__VA_ARGS__)) { \
|
||||
__asm__( \
|
||||
".word 0x0000000b\n" \
|
||||
".word %[metadata]\n" \
|
||||
"ret\n" \
|
||||
: \
|
||||
: \
|
||||
[metadata] "i" (&POLKAVM_JOIN(fn_name, __IMPORT_METADATA)) \
|
||||
: "memory" \
|
||||
); \
|
||||
}
|
||||
|
||||
#define POLKAVM_MIN_STACK_SIZE(size) \
|
||||
static void __attribute__ ((naked, used)) POLKAVM_UNIQUE(polkavm_stack_size)() { \
|
||||
__asm__( \
|
||||
".pushsection .polkavm_min_stack_size,\"\",@progbits\n" \
|
||||
".word %[value]\n" \
|
||||
".popsection\n" \
|
||||
: \
|
||||
: \
|
||||
[value] "i" (size) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
|
||||
#define POLKAVM_TRAP() \
|
||||
{ \
|
||||
__asm__("unimp\n" :::); \
|
||||
__builtin_unreachable(); \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "polkavm_guest.h"
|
||||
|
||||
|
||||
// Missing builtins
|
||||
|
||||
void * memset(void *b, int c, size_t len) {
|
||||
uint8_t *dest = b;
|
||||
while (len-- > 0) *dest++ = c;
|
||||
return b;
|
||||
}
|
||||
|
||||
void * memcpy(void *dst, const void *_src, size_t len) {
|
||||
uint8_t *dest = dst;
|
||||
const uint8_t *src = _src;
|
||||
|
||||
while (len--) *dest++ = *src++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void * memmove(void *dst, const void *src, size_t n) {
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
|
||||
if (d==s) return d;
|
||||
if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
|
||||
|
||||
if (d<s) {
|
||||
for (; n; n--) *d++ = *s++;
|
||||
} else {
|
||||
while (n) n--, d[n] = s[n];
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void * __sbrk(uint32_t size) {
|
||||
uint32_t address;
|
||||
__asm__ __volatile__(
|
||||
".insn r 0xb, 1, 0, %[dst], %[sz], zero"
|
||||
: [dst] "=r" (address)
|
||||
: [sz] "ir" (size)
|
||||
:
|
||||
);
|
||||
return (void *)address;
|
||||
}
|
||||
|
||||
|
||||
// Imports
|
||||
|
||||
POLKAVM_IMPORT(void, input, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, seal_return, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, returndatacopy, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, value_transferred, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, clear_storage, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, contains_storage, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, take_storage, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, call, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, delegate_call, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, instantiate, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, terminate, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, caller, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, is_contract, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, code_hash, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, code_size, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, own_code_hash, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, caller_is_origin)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, caller_is_root)
|
||||
|
||||
POLKAVM_IMPORT(void, address, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, weight_to_fee, uint64_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, gas_left, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, balance, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, now, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, minimum_balance, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, block_number, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, hash_sha2_256, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, hash_blake2_256, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, hash_blake2_128, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, call_chain_extension, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, debug_message, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, set_code_hash, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint64_t, instantiation_nonce,)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, transfer, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
@@ -0,0 +1,34 @@
|
||||
//! This crate vendors the [PolkaVM][0] C API and provides a LLVM module for interacting
|
||||
//! with the `pallet-revive` runtime API.
|
||||
//! At present, the revive pallet requires blobs to export `call` and `deploy`,
|
||||
//! and offers a bunch of [runtime API methods][1]. The provided [module] implements
|
||||
//! those exports and imports.
|
||||
//! [0]: [https://crates.io/crates/polkavm]
|
||||
//! [1]: [https://docs.rs/pallet-contracts/26.0.0/pallet_contracts/api_doc/index.html]
|
||||
|
||||
use inkwell::{context::Context, memory_buffer::MemoryBuffer, module::Module, support::LLVMString};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/polkavm_imports.rs"));
|
||||
|
||||
/// Creates a LLVM module from the [BITCODE].
|
||||
/// The module imports `pallet-revive` runtime API functions.
|
||||
/// Returns `Error` if the bitcode fails to parse, which should never happen.
|
||||
pub fn module<'context>(
|
||||
context: &'context Context,
|
||||
module_name: &str,
|
||||
) -> Result<Module<'context>, LLVMString> {
|
||||
let buf = MemoryBuffer::create_from_memory_range(BITCODE, module_name);
|
||||
Module::parse_bitcode_from_buffer(&buf, context)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::polkavm_imports;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||
let context = inkwell::context::Context::create();
|
||||
let _ = polkavm_imports::module(&context, "polkavm_imports").unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user