Struct EvmCompiler
pub struct EvmCompiler<B>where
B: Backend,{Show 14 fields
name: Option<String>,
backend: B,
out_dir: Option<PathBuf>,
config: FcxConfig,
builtins: Builtins<B>,
gas_params: Option<GasParams>,
dedup: bool,
dse: bool,
dump_assembly: bool,
dump_unopt_assembly: bool,
compiler_gas_limit: u64,
remarks: Remarks,
compiled_sizes: Vec<(String, usize)>,
finalized: bool,
}Expand description
EVM bytecode compiler.
This currently represents one single-threaded IR context and module, which can be used to compile multiple functions as JIT or AOT.
Functions can be incrementally added with translate, and then either written to an object
file with write_object when in AOT mode, or JIT-compiled with jit_function.
Performing either of these operations finalizes the module, and no more functions can be added
afterwards until clear is called, which will reset the module to its initial state.
Fields§
§name: Option<String>§backend: B§out_dir: Option<PathBuf>§config: FcxConfig§builtins: Builtins<B>§gas_params: Option<GasParams>§dedup: bool§dse: bool§dump_assembly: bool§dump_unopt_assembly: bool§compiler_gas_limit: u64§remarks: Remarks§compiled_sizes: Vec<(String, usize)>§finalized: boolImplementations§
§impl EvmCompiler<EvmLlvmBackend>
impl EvmCompiler<EvmLlvmBackend>
pub fn new_llvm(aot: bool) -> Result<EvmCompiler<EvmLlvmBackend>, Report>
Available on crate feature llvm only.
pub fn new_llvm(aot: bool) -> Result<EvmCompiler<EvmLlvmBackend>, Report>
llvm only.Creates a new instance of the compiler with the LLVM backend.
§impl<B> EvmCompiler<B>where
B: Backend,
impl<B> EvmCompiler<B>where
B: Backend,
pub fn new(backend: B) -> EvmCompiler<B>
pub fn new(backend: B) -> EvmCompiler<B>
Creates a new instance of the compiler with the given backend.
pub fn set_module_name(&mut self, name: impl Into<String>)
pub fn set_module_name(&mut self, name: impl Into<String>)
Sets the name of the module.
pub fn take_timings(&self) -> CompileTimings
pub fn take_timings(&self) -> CompileTimings
Returns the per-phase timing breakdown from the last compilation and resets the counters.
pub fn set_dump_to(&mut self, output_dir: Option<PathBuf>)
pub fn set_dump_to(&mut self, output_dir: Option<PathBuf>)
Dumps intermediate outputs and other debug info to the given directory after compilation.
Disables dumping if output_dir is None.
pub fn dump_assembly(&mut self, yes: bool)
pub fn dump_assembly(&mut self, yes: bool)
Dumps assembly to the output directory.
This can be quite slow.
Defaults to true.
pub fn dump_unopt_assembly(&mut self, yes: bool)
pub fn dump_unopt_assembly(&mut self, yes: bool)
Dumps the unoptimized assembly to the output directory.
This can be quite slow.
Defaults to false.
pub fn opt_level(&self) -> OptimizationLevel
pub fn opt_level(&self) -> OptimizationLevel
Returns the optimization level.
pub fn set_opt_level(&mut self, level: OptimizationLevel)
pub fn set_opt_level(&mut self, level: OptimizationLevel)
Sets the optimization level.
Note that some backends may not support setting the optimization level after initialization.
Defaults to the backend’s initial optimization level.
pub fn debug_assertions(&mut self, yes: bool)
pub fn debug_assertions(&mut self, yes: bool)
Sets whether to enable debug assertions.
These are useful for debugging, but they do a moderate performance penalty due to the insertion of extra checks and removal of certain assumptions.
Defaults to cfg!(debug_assertions).
pub fn debug_support(&self) -> bool
pub fn debug_support(&self) -> bool
Returns whether JIT debug support is enabled.
Registers JIT objects with debuggers via __jit_debug_register_code,
allowing GDB/LLDB to resolve JIT-compiled function names and set breakpoints.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
Defaults to true.
pub fn set_debug_support(&mut self, yes: bool)
pub fn set_debug_support(&mut self, yes: bool)
Sets whether to enable JIT debug support.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
pub fn profiling_support(&self) -> bool
pub fn profiling_support(&self) -> bool
Returns whether JIT profiling support is enabled.
Installs the LLVM PerfSupportPlugin which writes jitdump records,
allowing profilers to resolve JIT-compiled symbols with debug and unwind info.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
Defaults to false.
pub fn set_profiling_support(&mut self, yes: bool)
pub fn set_profiling_support(&mut self, yes: bool)
Sets whether to enable JIT profiling support.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
pub fn simple_perf(&self) -> bool
pub fn simple_perf(&self) -> bool
Returns whether the simple perf map plugin is enabled.
Writes /tmp/perf-<pid>.map in the perf map format so that profilers
can resolve JIT-compiled symbols without the jitdump machinery.
Not suitable for long-running programs. The map file is append-only
and never cleaned up, so entries for freed JIT code accumulate
indefinitely. Prefer set_profiling_support
(jitdump) for long-lived processes.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
Defaults to true.
pub fn set_simple_perf(&mut self, yes: bool)
pub fn set_simple_perf(&mut self, yes: bool)
Sets whether to enable the simple perf map plugin.
This setting is applied once per process on first JIT compilation. Subsequent compilers inherit the value set by the first.
pub fn set_debug_info(&mut self, yes: bool)
pub fn set_debug_info(&mut self, yes: bool)
Sets whether to enable debug info emission.
Debug info embeds DWARF metadata and annotates IR/assembly dumps with source locations from the parsed bytecode.
Automatically enabled by set_dump_to.
Defaults to false.
pub fn frame_pointers(&mut self, yes: bool)
pub fn frame_pointers(&mut self, yes: bool)
Sets whether to enable frame pointers.
This is useful for profiling and debugging, but it incurs a very slight performance penalty.
Enabled by default in debug builds, when -Cforce-frame-pointers is set, or when
set_dump_to is called with a directory.
pub fn inspect_stack(&mut self, yes: bool)
pub fn inspect_stack(&mut self, yes: bool)
Sets whether to treat the stack as observable outside the function.
If this is set to true, the stack length must be passed in the arguments.
This is useful to inspect the stack after the function has been executed, but it does incur a performance penalty as the stack will be stored at all return sites.
Defaults to false.
pub unsafe fn stack_bound_checks(&mut self, yes: bool)
pub unsafe fn stack_bound_checks(&mut self, yes: bool)
Sets whether to enable stack bound checks.
Defaults to true.
§Safety
Removing stack length checks may improve compilation speed and performance, but will result
in undefined behavior if the stack length overflows at runtime, rather than a
StackUnderflow/StackOverflow result.
pub fn set_compiler_gas_limit(&mut self, limit: u64)
pub fn set_compiler_gas_limit(&mut self, limit: u64)
Sets the gas budget for compile-time evaluation of user-supplied bytecode.
The compiler evaluates EVM operations at compile time during analysis passes. Without a
budget, adversarial bytecode (e.g. many EXP) can make compilation
arbitrarily slow. This limit uses the EVM gas schedule to bound work.
When the budget is exhausted, further evaluation is skipped and values remain dynamic.
Defaults to 100k gas. Set to 0 to disable compile-time evaluation entirely, or
u64::MAX to disable the limit.
pub fn gas_metering(&mut self, yes: bool)
pub fn gas_metering(&mut self, yes: bool)
Sets whether to track gas costs.
Disabling this will greatly improves compilation speed and performance, at the cost of not being able to check for gas exhaustion.
Note that this does not disable gas usage in certain instructions, mainly the ones that are implemented as builtins.
Use with care, as executing a function with gas disabled may result in an infinite loop.
Defaults to true.
pub fn single_error(&mut self, yes: bool)
pub fn single_error(&mut self, yes: bool)
Sets whether to collapse every JIT failure path to a single
OutOfGas constant.
Failures (stack under/overflow, invalid jump, real OOG, invalid opcode, etc.) are
semantically interchangeable for callers that only branch on success vs failure, so
this lets LLVM DCE the per-failure-site materialization and the failure-block phi.
Successful exits (STOP/RETURN/REVERT) keep their original codes.
Useful for benchmarking the cost of failure-result materialization.
Defaults to true.
pub fn set_gas_params(&mut self, gas_params: GasParams)
pub fn set_gas_params(&mut self, gas_params: GasParams)
Sets custom gas parameters.
Overrides the default gas schedule derived from the spec_id. Useful for custom chains or hardforks with non-standard gas costs.
Defaults to GasParams::new_spec(spec_id).
pub fn translate<'a>(
&mut self,
name: &str,
input: impl Into<EvmCompilerInput<'a>>,
spec_id: SpecId,
) -> Result<<B as Backend>::FuncId, Report>
pub fn translate<'a>( &mut self, name: &str, input: impl Into<EvmCompilerInput<'a>>, spec_id: SpecId, ) -> Result<<B as Backend>::FuncId, Report>
Translates the given EVM bytecode into an internal function.
NOTE: name must be unique for each function, as it is used as the name of the final
symbol.
pub unsafe fn jit<'a>(
&mut self,
name: &str,
bytecode: impl Into<EvmCompilerInput<'a>>,
spec_id: SpecId,
) -> Result<EvmCompilerFn, Report>
pub unsafe fn jit<'a>( &mut self, name: &str, bytecode: impl Into<EvmCompilerInput<'a>>, spec_id: SpecId, ) -> Result<EvmCompilerFn, Report>
pub unsafe fn jit_function(
&mut self,
id: <B as Backend>::FuncId,
) -> Result<EvmCompilerFn, Report>
pub unsafe fn jit_function( &mut self, id: <B as Backend>::FuncId, ) -> Result<EvmCompilerFn, Report>
(JIT) Finalizes the module and JITs the given function.
§Safety
The returned function pointer is owned by the module, and must not be called after the module is cleared or the function is freed.
pub fn write_object_to_file(&mut self, path: &Path) -> Result<(), Report>
pub fn write_object_to_file(&mut self, path: &Path) -> Result<(), Report>
(AOT) Writes the compiled object to the given file.
pub fn write_object<W>(&mut self, w: W) -> Result<(), Report>where
W: Write,
pub fn write_object<W>(&mut self, w: W) -> Result<(), Report>where
W: Write,
(AOT) Finalizes the module and writes the compiled object to the given writer.
pub unsafe fn free_function(
&mut self,
id: <B as Backend>::FuncId,
) -> Result<(), Report>
pub unsafe fn free_function( &mut self, id: <B as Backend>::FuncId, ) -> Result<(), Report>
(JIT) Frees the memory associated with a single function.
Note that this will not reset the state of the internal module even if all functions are
freed with this function. Use clear to reset the module.
§Safety
Because this function invalidates any pointers retrieved from the corresponding module, it
should only be used when none of the functions from that module are currently executing and
none of the fn pointers are called afterwards.
pub fn clear_ir(&mut self) -> Result<(), Report>
pub fn clear_ir(&mut self) -> Result<(), Report>
Clears the IR module, freeing memory used by IR representations.
This does not free JIT-compiled machine code, so previously obtained function pointers remain valid. The module is left in a state where new functions can be translated.
pub unsafe fn clear(&mut self) -> Result<(), Report>
pub unsafe fn clear(&mut self) -> Result<(), Report>
Frees all functions and resets the state of the internal module, allowing for new functions to be compiled.
§Safety
Because this function invalidates any pointers retrieved from the corresponding module, it
should only be used when none of the functions from that module are currently executing and
none of the fn pointers are called afterwards.
Trait Implementations§
Auto Trait Implementations§
impl<B> !Freeze for EvmCompiler<B>
impl<B> !RefUnwindSafe for EvmCompiler<B>
impl<B> Send for EvmCompiler<B>where
B: Send,
impl<B> !Sync for EvmCompiler<B>
impl<B> Unpin for EvmCompiler<B>
impl<B> UnsafeUnpin for EvmCompiler<B>where
B: UnsafeUnpin,
<B as BackendTypes>::Function: UnsafeUnpin,
impl<B> UnwindSafe for EvmCompiler<B>where
B: UnwindSafe,
<B as BackendTypes>::Function: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.§impl<T> TryConv for T
impl<T> TryConv for T
§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where
S: Into<Dispatch>,
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where
S: Into<Dispatch>,
§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.