pub struct Codegen {
pub ast: Option<Contract>,
pub artifact: Option<Artifact>,
pub main_bytecode: Option<String>,
pub constructor_bytecode: Option<String>,
}Expand description
Compiles Huff contracts into EVM bytecode.
Transforms a Contract AST into executable bytecode, handling macro expansion, label resolution, and bytecode optimization.
use huff_neo_codegen::Codegen;
let cg = Codegen::new();Fields§
§ast: Option<Contract>The Input AST
artifact: Option<Artifact>A cached codegen output artifact
main_bytecode: Option<String>Intermediate main bytecode store
constructor_bytecode: Option<String>Intermediate constructor bytecode store
Implementations§
Source§impl Codegen
impl Codegen
Sourcepub fn generate_main_bytecode(
evm_version: &EVMVersion,
contract: &Contract,
alternative_main: Option<String>,
relax_jumps: bool,
) -> Result<String, CodegenError>
pub fn generate_main_bytecode( evm_version: &EVMVersion, contract: &Contract, alternative_main: Option<String>, relax_jumps: bool, ) -> Result<String, CodegenError>
Compiles the contract’s main macro into executable bytecode.
§Arguments
evm_version- Target EVM versioncontract- The contract to compilealternative_main- Optional alternative entry point (defaults to “MAIN”)relax_jumps- Enable jump optimization to reduce bytecode size
Sourcepub fn generate_main_bytecode_with_sourcemap(
evm_version: &EVMVersion,
contract: &Contract,
alternative_main: Option<String>,
relax_jumps: bool,
) -> Result<MainBytecodeOutput, CodegenError>
pub fn generate_main_bytecode_with_sourcemap( evm_version: &EVMVersion, contract: &Contract, alternative_main: Option<String>, relax_jumps: bool, ) -> Result<MainBytecodeOutput, CodegenError>
Compiles the contract’s main macro into bytecode with source map.
Returns the full main bytecode (body + appended tables), its source map, the length of the
body section (offset at which the runtime tables begin), and the per-table runtime offsets.
build_artifact uses the body length and table offsets to dedupe constructor-side
__tablestart references into the runtime copy.
Sourcepub(crate) fn generate_main_bytecode_inner(
evm_version: &EVMVersion,
contract: &Contract,
alternative_main: Option<&str>,
relax_jumps: bool,
codesize_hints: Option<&BTreeMap<String, usize>>,
) -> Result<(MainBytecodeOutput, Option<BTreeMap<String, usize>>), CodegenError>
pub(crate) fn generate_main_bytecode_inner( evm_version: &EVMVersion, contract: &Contract, alternative_main: Option<&str>, relax_jumps: bool, codesize_hints: Option<&BTreeMap<String, usize>>, ) -> Result<(MainBytecodeOutput, Option<BTreeMap<String, usize>>), CodegenError>
Compiles MAIN once, with the macro sizes of the previous pass. Also returns the macro sizes
of this pass when a __codesize needed them, so they must reach a fixed point.
Sourcepub fn reject_args_start(res: &BytecodeRes) -> Result<(), CodegenError>
pub fn reject_args_start(res: &BytecodeRes) -> Result<(), CodegenError>
Rejects __argsstart() in code that runs as the runtime, such as MAIN or a test, since
constructor arguments are only part of the deployment code.
Sourcepub fn generate_constructor_bytecode(
evm_version: &EVMVersion,
contract: &Contract,
alternative_constructor: Option<String>,
relax_jumps: bool,
) -> Result<(String, bool), CodegenError>
pub fn generate_constructor_bytecode( evm_version: &EVMVersion, contract: &Contract, alternative_constructor: Option<String>, relax_jumps: bool, ) -> Result<(String, bool), CodegenError>
Generates the constructor section in isolation: macro body with all __tablestart
placeholders resolved against locally-emitted tables.
This standalone form (tables sitting directly after the body) does not include the
deployment-time auto-bootstrap and is not the layout that ends up in the deployed
artifact — use Codegen::churn for the final assembly. This function exists for tools
and tests that want to inspect just the constructor section. __argsstart() stays a
placeholder here, as the offset of the arguments depends on the deployment layout.
Sourcepub fn generate_constructor_macro_bytecode(
evm_version: &EVMVersion,
contract: &Contract,
alternative_constructor: Option<String>,
relax_jumps: bool,
) -> Result<(ConstructorMacroBytecode, Contract), CodegenError>
pub fn generate_constructor_macro_bytecode( evm_version: &EVMVersion, contract: &Contract, alternative_constructor: Option<String>, relax_jumps: bool, ) -> Result<(ConstructorMacroBytecode, Contract), CodegenError>
Generates constructor macro bytecode without resolving __tablestart placeholders.
This is phase 1 of constructor codegen. Table positions and __tablestart resolution depend
on the auto-bootstrap size and the runtime layout, which are only known once build_artifact
has both the constructor body and the compiled main bytecode in hand. Phase 2 runs inside
build_artifact via Codegen::gen_table_bytecode.
Sourcepub fn update_table_size(
_evm_version: &EVMVersion,
contract: &Contract,
) -> Result<Contract, CodegenError>
pub fn update_table_size( _evm_version: &EVMVersion, contract: &Contract, ) -> Result<Contract, CodegenError>
Update the table size in the contract that was not know at the time of parsing
Sourcepub(crate) fn get_macro_by_name<'a>(
name: &str,
contract: &'a Contract,
) -> Result<&'a MacroDefinition, CodegenError>
pub(crate) fn get_macro_by_name<'a>( name: &str, contract: &'a Contract, ) -> Result<&'a MacroDefinition, CodegenError>
Helper function to find a macro or generate a CodegenError
Sourcepub fn gen_constant_value(
contract: &Contract,
name: &str,
span: &AstSpan,
) -> Result<Option<PushValue>, CodegenError>
pub fn gen_constant_value( contract: &Contract, name: &str, span: &AstSpan, ) -> Result<Option<PushValue>, CodegenError>
Resolves a constant to the value [NAME] pushes, or None for a __NOOP constant
Sourcepub fn gen_builtin_bytecode(
contract: &Contract,
bf: &BuiltinFunctionCall,
span: AstSpan,
) -> Result<PushValue, CodegenError>
pub fn gen_builtin_bytecode( contract: &Contract, bf: &BuiltinFunctionCall, span: AstSpan, ) -> Result<PushValue, CodegenError>
Generates bytecode for a builtin function call used for constants, code tables, etc. Returns a PushValue that can be converted to bytecode with or without opcode
Sourcepub fn gen_table_bytecode_builtin(
contract: &Contract,
table_definition: &TableDefinition,
) -> Result<String, CodegenError>
pub fn gen_table_bytecode_builtin( contract: &Contract, table_definition: &TableDefinition, ) -> Result<String, CodegenError>
Generates bytecode for a code table with builtin functions
Sourcepub fn gen_table_bytecode(
contract: &Contract,
res: BytecodeRes,
base_offset: usize,
external_table_offsets: &HashMap<String, usize>,
) -> Result<TableBytecodeOutput, CodegenError>
pub fn gen_table_bytecode( contract: &Contract, res: BytecodeRes, base_offset: usize, external_table_offsets: &HashMap<String, usize>, ) -> Result<TableBytecodeOutput, CodegenError>
Appends table bytecode for tables referenced by res and fills __tablestart placeholders.
base_offset is added to every locally-emitted table’s offset before resolution — used by the
constructor pathway to push tables past the auto-bootstrap and main bytecode.
external_table_offsets lets the caller resolve __tablestart to a table emitted somewhere
else (e.g. shared with the runtime). Tables found here are not emitted locally; their offset
is used directly when filling placeholders.
Sourcepub fn macro_to_bytecode<'a>(
evm_version: &EVMVersion,
macro_def: &'a MacroDefinition,
contract: &'a Contract,
scope_mgr: &mut ScopeManager<'a>,
offset: usize,
relax_jumps: bool,
) -> Result<BytecodeRes, CodegenError>
pub fn macro_to_bytecode<'a>( evm_version: &EVMVersion, macro_def: &'a MacroDefinition, contract: &'a Contract, scope_mgr: &mut ScopeManager<'a>, offset: usize, relax_jumps: bool, ) -> Result<BytecodeRes, CodegenError>
Generates bytecode from a macro definition.
Expands the macro body into bytecode, resolving labels, arguments, and nested macro calls.
§Arguments
evm_version- Target EVM version for opcode compatibilitymacro_def- The macro to compilecontract- Contract context for macro and constant lookupsscope_mgr- Call stack for tracking macro invocations and scopeoffset- Starting bytecode offsetrelax_jumps- Enable jump size optimization
§Returns
Bytecode with label indices, unresolved jumps, and source map information.
Sourcepub fn relax_jump_offsets(
bytes: BytecodeSegments,
jump_table: &JumpTable,
label_indices: &LabelIndices,
) -> ResizedBytecode
pub fn relax_jump_offsets( bytes: BytecodeSegments, jump_table: &JumpTable, label_indices: &LabelIndices, ) -> ResizedBytecode
Shrinks PUSH2 jumps to PUSH1 where the target fits in one byte.
Jump relaxation for span-dependent instructions (“start big and shrink”), an iterative variant of the technique described in Thomas G. Szymanski, “Assembling Code for Machines with Span-Dependent Instructions”, CACM 21(4), 1978, p. 300-308. See also: https://www.complang.tuwien.ac.at/anton/assembling-span-dependent.html
Shrinking only moves code backwards, so it never pushes a target out of range of a jump that was widened before.
Returns the relaxed bytecode, updated label indices, and a mapping from original to new segment offsets.
Sourcepub fn widen_jump_offsets(
bytes: BytecodeSegments,
jump_table: &JumpTable,
label_indices: &LabelIndices,
) -> ResizedBytecode
pub fn widen_jump_offsets( bytes: BytecodeSegments, jump_table: &JumpTable, label_indices: &LabelIndices, ) -> ResizedBytecode
Widens jumps and self-referencing __codesize pushes whose value no longer fits.
Jumps start as PUSH2 and self-referencing __codesize pushes as PUSH1. Code beyond 64 KiB
(possible in initcode from Amsterdam) needs PUSH3 targets, and a macro’s own size can need a
wider push than first assumed. Widening moves all following code, so this repeats until no
push changes (“start small and grow”); it always terminates because pushes only grow.
Returns the widened bytecode, updated label indices, and a mapping from original to new segment offsets.
Sourcepub(crate) fn resize_span_dependent_pushes(
bytes: BytecodeSegments,
jump_table: &JumpTable,
label_indices: &LabelIndices,
mode: ResizeMode,
) -> ResizedBytecode
pub(crate) fn resize_span_dependent_pushes( bytes: BytecodeSegments, jump_table: &JumpTable, label_indices: &LabelIndices, mode: ResizeMode, ) -> ResizedBytecode
Repeatedly resizes span-dependent pushes until their widths are stable.
After every round that changed a width, segment offsets and label positions are recomputed, since a different width moves all code that follows.
Sourcepub fn fill_unmatched(
bytes: BytecodeSegments,
jump_table: &JumpTable,
label_indices: &LabelIndices,
relax_jumps: bool,
) -> Result<FilledJumps, CodegenError>
pub fn fill_unmatched( bytes: BytecodeSegments, jump_table: &JumpTable, label_indices: &LabelIndices, relax_jumps: bool, ) -> Result<FilledJumps, CodegenError>
Resolves jump placeholders to their target offsets with optional size optimization.
Replaces jump placeholders with actual bytecode offsets by looking up labels in the
label index. Jumps whose target does not fit in PUSH2 are widened first; when
relax_jumps is enabled, PUSH2 jumps are then shrunk to PUSH1 where targets fit within a
single byte (0-255).
§Arguments
bytes- Bytecode segments with jump placeholdersjump_table- Jump metadata indexed by bytecode offsetlabel_indices- Scoped label positionsrelax_jumps- Enable jump size optimization
§Returns
Returns resolved bytecode, any unmatched jumps, the final label positions, and a mapping from original to final segment offsets, or an error for label conflicts or invalid jump targets.
Sourcepub fn append_functions<'a>(
evm_version: &EVMVersion,
contract: &'a Contract,
scope_mgr: &mut ScopeManager<'a>,
offset: &mut usize,
jump_table: &mut JumpTable,
label_indices: &mut LabelIndices,
table_instances: &mut Jumps,
bytes: BytecodeSegments,
) -> Result<BytecodeSegments, CodegenError>
pub fn append_functions<'a>( evm_version: &EVMVersion, contract: &'a Contract, scope_mgr: &mut ScopeManager<'a>, offset: &mut usize, jump_table: &mut JumpTable, label_indices: &mut LabelIndices, table_instances: &mut Jumps, bytes: BytecodeSegments, ) -> Result<BytecodeSegments, CodegenError>
Helper associated function to append functions to the end of the bytecode.
§Overview
Iterates over the contract’s functions, generates their bytecode, fills unmatched jumps & label indices, and appends the functions’ bytecode to the end of the contract’s bytecode.
On success, passes ownership of bytes back to the caller.
On failure, returns a CodegenError.
Sourcepub fn churn(
&mut self,
evm_version: &EVMVersion,
file: Arc<FileSource>,
args: Vec<DynSolValue>,
main_bytecode: &str,
constructor_bytecode: &str,
has_custom_bootstrap: bool,
main_source_map: Option<Vec<SourceMapEntry>>,
constructor_source_map: Option<Vec<SourceMapEntry>>,
no_size_limit: bool,
) -> Result<Artifact, CodegenError>
pub fn churn( &mut self, evm_version: &EVMVersion, file: Arc<FileSource>, args: Vec<DynSolValue>, main_bytecode: &str, constructor_bytecode: &str, has_custom_bootstrap: bool, main_source_map: Option<Vec<SourceMapEntry>>, constructor_source_map: Option<Vec<SourceMapEntry>>, no_size_limit: bool, ) -> Result<Artifact, CodegenError>
Back-compat shim for assembly from raw bytecode strings.
Synthesizes MainBytecodeOutput and ConstructorMacroBytecode from raw hex strings and
forwards to Codegen::assemble_artifact. Use this when you have pre-baked main and
constructor bytecode (e.g. existing snapshot tests) and do not need the table-dedup pathway.
Behaves identically to the structured API for inputs that contain no tables.
Sourcepub fn assemble_artifact(
&mut self,
evm_version: &EVMVersion,
file: Arc<FileSource>,
contract: &Contract,
args: Vec<DynSolValue>,
main: MainBytecodeOutput,
constructor: Option<ConstructorMacroBytecode>,
no_size_limit: bool,
) -> Result<Artifact, CodegenError>
pub fn assemble_artifact( &mut self, evm_version: &EVMVersion, file: Arc<FileSource>, contract: &Contract, args: Vec<DynSolValue>, main: MainBytecodeOutput, constructor: Option<ConstructorMacroBytecode>, no_size_limit: bool, ) -> Result<Artifact, CodegenError>
Generate a codegen artifact.
Deployment bytecode is laid out as:
[ctor_body][bootstrap?][main_bytecode][ctor_only_tables][constructor_args]
A __tablestart(T) reference inside the constructor is resolved against a runtime-resident
copy of T when main already emits one (no duplicate); otherwise the table is appended
once to the deployment tail and the constructor’s reference points there.
§Arguments
evm_version— target EVM version; selects the runtime and initcode size limits.contract— contract AST with table sizes populated byupdate_table_size. Used to read table definitions during constructor table finalization.args— encoded constructor arguments, appended at the very end of the deployment bytes.main— main/runtime bytecode plus its body length and per-table offsets within the runtime.constructor— phase-1 constructor macro output;Nonewhen the contract has noCONSTRUCTORmacro (deployment becomes justbootstrap + main).no_size_limit— skip the runtime and initcode size checks.
Sourcepub fn encode_constructor_args(
args: &[String],
types: Option<&[String]>,
) -> Result<Vec<DynSolValue>, CodegenError>
pub fn encode_constructor_args( args: &[String], types: Option<&[String]>, ) -> Result<Vec<DynSolValue>, CodegenError>
Reads constructor arguments given as text. With the declared constructor parameter types, each argument is read as its type and the count must match; otherwise each type is guessed from the text. Without arguments nothing is appended, so the deployer can append them later.
Sourcepub fn declared_constructor_types(contract: &Contract) -> Option<Vec<String>>
pub fn declared_constructor_types(contract: &Contract) -> Option<Vec<String>>
The parameter types of the contract’s #define function constructor(...), if it declares one
Sourcepub fn abi_encode_constructor_args(args: Vec<DynSolValue>) -> String
pub fn abi_encode_constructor_args(args: Vec<DynSolValue>) -> String
Encodes constructor arguments as hex, the way Solidity’s abi.encode does
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Codegen
impl RefUnwindSafe for Codegen
impl Send for Codegen
impl Sync for Codegen
impl Unpin for Codegen
impl UnsafeUnpin for Codegen
impl UnwindSafe for Codegen
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> 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 moreSource§impl<S, T> Upcast<T> for S
impl<S, T> Upcast<T> for S
§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: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 672 bytes