Emerge Yul recompiler (#1)

Provide a modified (and incomplete) version of ZKSync zksolc that can compile the most basic contracts
This commit is contained in:
Cyrill Leutwiler
2024-03-12 12:06:02 +01:00
committed by GitHub
parent d238d8f39e
commit cffa14a4d2
247 changed files with 35357 additions and 4905 deletions
@@ -0,0 +1,126 @@
//!
//! The LLVM target machine.
//!
pub mod target;
use crate::optimizer::settings::size_level::SizeLevel as OptimizerSettingsSizeLevel;
use crate::optimizer::settings::Settings as OptimizerSettings;
use self::target::Target;
///
/// The LLVM target machine.
///
#[derive(Debug)]
pub struct TargetMachine {
/// The LLVM target.
target: Target,
/// The LLVM target machine reference.
target_machine: inkwell::targets::TargetMachine,
/// The optimizer settings.
optimizer_settings: OptimizerSettings,
}
impl TargetMachine {
/// The LLVM target name.
pub const VM_TARGET_NAME: &'static str = "riscv32";
/// The LLVM target triple.
pub const VM_TARGET_TRIPLE: &'static str = "riscv32-unknown-unknown-elf";
///
/// A shortcut constructor.
///
/// A separate instance for every optimization level is created.
///
pub fn new(target: Target, optimizer_settings: &OptimizerSettings) -> anyhow::Result<Self> {
let target_machine = inkwell::targets::Target::from_name(target.name())
.ok_or_else(|| anyhow::anyhow!("LLVM target machine `{}` not found", target.name()))?
.create_target_machine(
&inkwell::targets::TargetTriple::create(target.triple()),
"generic-rv32",
"+e,+m",
optimizer_settings.level_back_end,
inkwell::targets::RelocMode::PIC,
inkwell::targets::CodeModel::Default,
)
.ok_or_else(|| {
anyhow::anyhow!(
"LLVM target machine `{}` initialization error",
target.name(),
)
})?;
Ok(Self {
target,
target_machine,
optimizer_settings: optimizer_settings.to_owned(),
})
}
///
/// Sets the target-specific data in the module.
///
pub fn set_target_data(&self, module: &inkwell::module::Module) {
module.set_triple(&self.target_machine.get_triple());
let data_layout = self
.target_machine
.get_target_data()
.get_data_layout()
.as_str()
.to_str()
.expect("datalayout sting should be valid")
.to_owned();
module.set_data_layout(&self.target_machine.get_target_data().get_data_layout());
}
///
/// Writes the LLVM module to a memory buffer.
///
pub fn write_to_memory_buffer(
&self,
module: &inkwell::module::Module,
) -> Result<inkwell::memory_buffer::MemoryBuffer, inkwell::support::LLVMString> {
match self.target {
Target::PVM => self
.target_machine
.write_to_memory_buffer(module, inkwell::targets::FileType::Object),
}
}
///
/// Runs the optimization passes on `module`.
///
pub fn run_optimization_passes(
&self,
module: &inkwell::module::Module,
passes: &str,
) -> Result<(), inkwell::support::LLVMString> {
let pass_builder_options = inkwell::passes::PassBuilderOptions::create();
pass_builder_options.set_verify_each(self.optimizer_settings.is_verify_each_enabled);
pass_builder_options.set_debug_logging(self.optimizer_settings.is_debug_logging_enabled);
pass_builder_options.set_loop_unrolling(
self.optimizer_settings.level_middle_end_size == OptimizerSettingsSizeLevel::Zero,
);
pass_builder_options.set_merge_functions(true);
module.run_passes(passes, &self.target_machine, pass_builder_options)
}
///
/// Returns the target triple.
///
pub fn get_triple(&self) -> inkwell::targets::TargetTriple {
self.target_machine.get_triple()
}
///
/// Returns the target data.
///
pub fn get_target_data(&self) -> inkwell::targets::TargetData {
self.target_machine.get_target_data()
}
}
@@ -0,0 +1,66 @@
//!
//! The LLVM target.
//!
use std::str::FromStr;
///
/// The LLVM target.
///
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Target {
/// The EraVM target.
PVM,
}
impl Target {
///
/// Returns the target name.
///
pub fn name(&self) -> &str {
match self {
Self::PVM => "riscv32",
}
}
///
/// Returns the target triple.
///
pub fn triple(&self) -> &str {
match self {
Self::PVM => "riscv32-unknown-unknown-elf",
}
}
///
/// Returns the target production name.
///
pub fn production_name(&self) -> &str {
match self {
Self::PVM => "PVM",
}
}
}
impl FromStr for Target {
type Err = anyhow::Error;
fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"riscv32" => Ok(Self::PVM),
_ => Err(anyhow::anyhow!(
"Unknown target `{}`. Supported targets: {:?}",
string,
Self::PVM
)),
}
}
}
impl std::fmt::Display for Target {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Target::PVM => write!(f, "riscv32"),
}
}
}