mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 06:01:06 +00:00
add crate for custom isa extensions
Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
Generated
+7
@@ -1415,6 +1415,13 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
|||||||
name = "revive-builtins"
|
name = "revive-builtins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revive-extensions"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"inkwell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revive-integration"
|
name = "revive-integration"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "revive-extensions"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
inkwell = { workspace = true, no-default-features = true, features = ["target-riscv", "no-libffi-linking", "llvm16-0"] }
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
|
||||||
|
target triple = "riscv32-unknown-unknown-elf"
|
||||||
|
|
||||||
|
define dso_local noundef i256 @__bswap(i256 noundef %0) local_unnamed_addr #0 {
|
||||||
|
%2 = tail call i256 @llvm.bswap.i256(i256 %0)
|
||||||
|
ret i256 %2
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i256 @llvm.bswap.i256(i256) #1
|
||||||
|
|
||||||
|
attributes #0 = { alwaysinline mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
||||||
|
attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
use std::{env, fs, path::Path, process::Command};
|
||||||
|
|
||||||
|
fn compile(source_path: &str, output_path: &str) {
|
||||||
|
let output = Command::new("llc")
|
||||||
|
.args([
|
||||||
|
"-O3",
|
||||||
|
"-filetype=asm",
|
||||||
|
"-mattr=+zbb,+e",
|
||||||
|
source_path,
|
||||||
|
"-o",
|
||||||
|
output_path,
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.expect("should be able to invoke llc");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to compile {}: {:?}",
|
||||||
|
source_path,
|
||||||
|
output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let in_file = "bswap.ll";
|
||||||
|
let out_file = "bswap.s";
|
||||||
|
let out_dir = env::var_os("OUT_DIR").expect("env should have $OUT_DIR");
|
||||||
|
let out_path = Path::new(&out_dir).join(out_file);
|
||||||
|
compile(
|
||||||
|
in_file,
|
||||||
|
out_path.to_str().expect("$OUT_DIR should be UTF-8"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let src_path = Path::new(&out_dir).join("bswap.rs");
|
||||||
|
let src = format!("pub static ASSEMBLY: &str = include_str!(\"{out_file}\");");
|
||||||
|
fs::write(src_path, src).expect("should be able to write in $OUT_DIR");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=bswap.ll");
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
//! Custom RISC-V extension in PolkaVM that are partially supported.
|
||||||
|
//! We use inline assembly to emit partially supported instructions.
|
||||||
|
|
||||||
|
use inkwell::{context::Context, module::Module, support::LLVMString};
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/bswap.rs"));
|
||||||
|
|
||||||
|
/// Returns a LLVM module containing a `__bswap` function, which
|
||||||
|
/// - Takes a `i256` value argument
|
||||||
|
/// - Byte swaps it using `rev8` from the `zbb` extension
|
||||||
|
/// - Returns the `i256` value
|
||||||
|
///
|
||||||
|
/// Returns `Error` if the module fails to validate, which should never happen.
|
||||||
|
pub fn module<'context>(
|
||||||
|
context: &'context Context,
|
||||||
|
module_name: &str,
|
||||||
|
) -> Result<Module<'context>, LLVMString> {
|
||||||
|
let module = context.create_module(module_name);
|
||||||
|
|
||||||
|
module.set_inline_assembly(ASSEMBLY);
|
||||||
|
module.verify()?;
|
||||||
|
|
||||||
|
Ok(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn assembly_contains_rev8_instruction() {
|
||||||
|
assert!(crate::ASSEMBLY.contains("rev8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn module_is_valid() {
|
||||||
|
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||||
|
let context = inkwell::context::Context::create();
|
||||||
|
|
||||||
|
assert!(crate::module(&context, "polkavm_bswap").is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user