bytecode

package
v1.2.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Copyright Consensys Software Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

SPDX-License-Identifier: Apache-2.0

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckSmallArgs added in v1.2.21

func CheckSmallArgs(args []RegisterId)

CheckSmallArgs panics if the given arguments cannot be encoded as a "small" (single-byte) operand list, since wide read/write instructions are unsupported.

func IsUnusedConstant

func IsUnusedConstant[W word.Word[W]](op Operation, constant W) bool

IsUnusedConstant checks whether a given constant is the "identity element". This depends on the arithmetic operation in question. For example, for addition and subtraction, this is zero. But, for multiplication it is one.

func RegisterGobTypes added in v1.2.21

func RegisterGobTypes[W word.Word[W]]()

RegisterGobTypes registers every concrete Bytecode[W] implementation with the gob package for the given word type W. This is required so that the Bytecode interface values held within a Vector can be marshalled / unmarshalled. gob registration is keyed on the concrete type, so registering the same instantiation more than once is harmless (and registering distinct word types yields distinct names, hence no conflict).

func RegisterToString added in v1.2.21

func RegisterToString[W word.Word[W]](reg RegisterId, env Environment[W]) string

RegisterToString formats a single register as a string, using the given mapping to resolve its name (falling back to a numeric placeholder). When the environment can supply a current value for the register (see Environment.ValueOf), that value is appended inline as "[0xVAL]"; this is how the debugger renders register values within an instruction's string.

func RegisterVectorToString added in v1.2.21

func RegisterVectorToString[W word.Word[W]](reg RegisterVector, mapping Environment[W]) string

RegisterVectorToString formats a register vector as a string, abbreviating vectors of more than two limbs.

func RegistersToString added in v1.2.21

func RegistersToString[W word.Word[W]](registers []RegisterId, mapping Environment[W], separator string) string

RegistersToString formats a slice of registers as a string, joining their individual representations with the given separator.

Types

type Address

type Address = uint32

Address just provides a convenient alias to make the code more readable.

type Arith

type Arith[W word.Word[W]] struct {
	Op       Operation
	Constant W
	Source   []RegisterId
	Target   []RegisterId
}

Arith (arithmetic) instruction encodes a wide range of related arithmetic operations (e.g. +,-,*) including various bitwise operations.

func AddConst

func AddConst[W word.Word[W]](target RegisterId, sources []RegisterId, constant W) *Arith[W]

AddConst constructs an addition instruction computing "target = sum(sources) + constant" into a single target register.

func AddVec

func AddVec[W word.Word[W]](targets []RegisterId, sources []RegisterId) *Arith[W]

AddVec constructs a vectored addition instruction computing "targets = sum(sources)" (i.e. with no constant addend), where targets is a multi-limb register vector.

func AddVecConst

func AddVecConst[W word.Word[W]](targets []RegisterId, sources []RegisterId, constant W) *Arith[W]

AddVecConst constructs a vectored addition instruction computing "targets = sum(sources) + constant", where targets is a multi-limb register vector.

func LoadConst

func LoadConst[W word.Word[W]](target RegisterId, constant W) *Arith[W]

LoadConst constructs a load-constant (LDC) instruction which assigns the given constant to the target register.

func LoadConstVec added in v1.2.21

func LoadConstVec[W word.Word[W]](targets []RegisterId, constant W) *Arith[W]

LoadConstVec constructs a load-constant (LDC) instruction which assigns the given constant to the target registers.

func MulConst

func MulConst[W word.Word[W]](target RegisterId, sources []RegisterId, constant W) *Arith[W]

MulConst constructs a multiplication instruction computing "target = product(sources) * constant" into a single target register.

func MulVecConst

func MulVecConst[W word.Word[W]](targets []RegisterId, sources []RegisterId, constant W) *Arith[W]

MulVecConst constructs a vectored multiplication instruction computing "targets = product(sources) * constant", where targets is a multi-limb register vector.

func NewArith added in v1.2.21

func NewArith[W word.Word[W]](op Operation, targets []RegisterId, sources []RegisterId, constant W) *Arith[W]

NewArith constructs a new arithmetic instruction computing "targets = sources[0] op sources[1] op ... op constant".

func SubConst

func SubConst[W word.Word[W]](target RegisterId, sources []RegisterId, constant W) *Arith[W]

SubConst constructs a subtraction instruction computing "target = sources[0] - ... - constant" into a single target register.

func SubVecConst

func SubVecConst[W word.Word[W]](targets []RegisterId, sources []RegisterId, constant W) *Arith[W]

SubVecConst constructs a vectored subtraction instruction computing "targets = sources[0] - ... - constant", where targets is a multi-limb register vector.

func (*Arith[W]) Definitions added in v1.2.21

func (p *Arith[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Arith[W]) String

func (p *Arith[W]) String(env Environment[W]) string

func (*Arith[W]) Uses added in v1.2.21

func (p *Arith[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*Arith[W]) Validate added in v1.2.21

func (p *Arith[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Bitwise

type Bitwise[W word.Word[W]] struct {
	// Opcode selects the operation (AND, OR or XOR).
	Op Operation
	// Target receives the result.
	Target RegisterId
	// Left and Right are the operand registers.
	Left, Right RegisterId
	// Bitwidth of operands
	Bitwidth uint16
}

Bitwise computes a binary bitwise operation between two registers. The operation is identified by Opcode, which is one of AND, OR or XOR.

func NewBitwise

func NewBitwise[W word.Word[W]](op Operation, target, left, right RegisterId, bitwidth uint16) *Bitwise[W]

NewBitwise constructs a bitwise instruction (and/or/xor) computing "target = left op right".

func (*Bitwise[W]) Definitions added in v1.2.21

func (p *Bitwise[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Bitwise[W]) String

func (p *Bitwise[W]) String(env Environment[W]) string

func (*Bitwise[W]) Uses added in v1.2.21

func (p *Bitwise[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A NOT carries its single operand duplicated across Left and Right (see compileNot), so returning both is always correct.

func (*Bitwise[W]) Validate added in v1.2.21

func (p *Bitwise[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Bytecode

type Bytecode[W word.Word[W]] interface {
	// Uses returns the set of registers used (i.e. read) by this bytecode.
	Uses() []RegisterId
	// Definitions returns the set of registers defined (i.e. written) by this
	// bytecode.
	Definitions() []RegisterId
	// Validate checks that this bytecode is well-formed, returning any errors
	// found (or nil when it is well-formed).  Field is the surrounding field
	// configuration and env resolves register and module information.
	Validate(field FieldConfig, env Environment[W]) []error
	// String returns a suitable string representation of this bytecode.
	String(Environment[W]) string
}

Bytecode encapsulates a single bytecode instruction.

type Call

type Call[W word.Word[W]] struct {
	// address of target function
	Target ModuleId
	// Arguments are caller-frame registers copied into callee inputs.
	Arguments []RegisterId
	// Returns are caller-frame registers receiving callee outputs.
	Returns []RegisterId
}

Call invokes another function module.

func CallFun

func CallFun[W word.Word[W]](target ModuleId, args []RegisterId, returns []RegisterId) *Call[W]

CallFun constructs a function-call bytecode with the given flags.

func (*Call[W]) Definitions added in v1.2.21

func (p *Call[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface. A call writes the callee's outputs into the return registers of the caller's frame.

func (*Call[W]) String

func (p *Call[W]) String(env Environment[W]) string

func (*Call[W]) Uses added in v1.2.21

func (p *Call[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A call reads the argument registers passed into the callee.

func (*Call[W]) Validate added in v1.2.21

func (p *Call[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Cat

type Cat[W word.Word[W]] struct {
	// Targets receive the concatenated value, least-significant limb first.
	Targets []RegisterId
	// Sources are concatenated with Sources[0] in the least-significant bits.
	Sources []RegisterId
}

Cat concatenates source register bits and stores the result across targets.

func Assign added in v1.2.21

func Assign[W word.Word[W]](target RegisterId, source RegisterId) *Cat[W]

Assign constructs a move instruction which copies the source register into the target register.

func Concat

func Concat[W word.Word[W]](targets []RegisterId, sources []RegisterId) *Cat[W]

Concat constructs a concatenation instruction which joins the source registers into the target register vector.

func (*Cat[W]) Definitions added in v1.2.21

func (p *Cat[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Cat[W]) String

func (p *Cat[W]) String(env Environment[W]) string

func (*Cat[W]) Uses added in v1.2.21

func (p *Cat[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*Cat[W]) Validate added in v1.2.21

func (p *Cat[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type CheckCast

type CheckCast[W word.Word[W]] struct {
	Bitwidth uint16
	Target   RegisterId
}

CheckCast instruction.

func NewCheckCast

func NewCheckCast[W word.Word[W]](target RegisterId, bitwidth uint16) *CheckCast[W]

NewCheckCast constructs a check-cast instruction asserting that the given target register fits within the given bit width.

func (*CheckCast[W]) Definitions added in v1.2.21

func (p *CheckCast[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface. A check-cast asserts a property of an existing register without writing a new value, so it defines nothing. In particular, it does not redefine its target: doing so would conflict with the definition it is paired with to validate (e.g. the preceding arithmetic write).

func (*CheckCast[W]) String

func (p *CheckCast[W]) String(env Environment[W]) string

func (*CheckCast[W]) Uses added in v1.2.21

func (p *CheckCast[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A check-cast reads its target to assert the held value fits within the given bit width.

func (*CheckCast[W]) Validate added in v1.2.21

func (p *CheckCast[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Condition added in v1.2.21

type Condition uint

Condition represents the set of permission comparitors for a SkipIf instruction.

const (
	// CONDITION_EQ indicates an equality condition
	CONDITION_EQ Condition = 0
	// CONDITION_NEQ indicates a non-equality condition
	CONDITION_NEQ Condition = 1
	// CONDITION_LT indicates a less-than condition
	CONDITION_LT Condition = 2
	// CONDITION_GT indicates a greater-than condition
	CONDITION_GT Condition = 3
	// CONDITION_LTEQ indicates a less-than-or-equals condition
	CONDITION_LTEQ Condition = 4
	// CONDITION_GTEQ indicates a greater-than-or-equals condition
	CONDITION_GTEQ Condition = 5
)

type Debug

type Debug[W word.Word[W]] struct {
	// Chunks is the formatted-print specification: literal text interleaved with
	// argument formats.  Carried through compilation into the program's debug
	// side-table rather than encoded inline.
	Chunks []FormattedChunk
	// Source registers used for displaying chunks
	Sources []RegisterVector
}

Debug carries a formatted-print (printf) specification so the interpreter can reproduce the reference machine's debug output. The chunks themselves are held in the program's debug side-table (they cannot be encoded inline as uint32 words); Index identifies this site's entry there and is the only thing packed into the bytecode stream (see Codes).

func NewDebug

func NewDebug[W word.Word[W]](chunks []FormattedChunk, sources []RegisterId) *Debug[W]

NewDebug constructs a debug instruction carrying the given formatted message.

func (*Debug[W]) Definitions added in v1.2.21

func (p *Debug[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Debug[W]) String

func (p *Debug[W]) String(env Environment[W]) string

func (*Debug[W]) Uses added in v1.2.21

func (p *Debug[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A debug reads the registers referenced by its formatted arguments.

func (*Debug[W]) Validate added in v1.2.21

func (p *Debug[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type DivRem

type DivRem[W word.Word[W]] struct {
	// Opcode selects the operation (DIV or REM).
	Opcode uint32
	// Target receives the result.
	Target RegisterId
	// Dividend and Divisor are the operand registers.
	Dividend, Divisor RegisterId
}

DivRem computes the (truncated) integer quotient or remainder of two registers. The operation is identified by Opcode, which is one of DIV or REM. A zero divisor aborts execution with a division-by-zero error.

func NewDivRem

func NewDivRem[W word.Word[W]](op uint32, target, dividend, divisor RegisterId) *DivRem[W]

NewDivRem constructs a division/remainder instruction computing "target = dividend op divisor".

func (*DivRem[W]) Definitions added in v1.2.21

func (p *DivRem[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*DivRem[W]) String

func (p *DivRem[W]) String(mapping Environment[W]) string

func (*DivRem[W]) Uses added in v1.2.21

func (p *DivRem[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*DivRem[W]) Validate added in v1.2.21

func (p *DivRem[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Environment added in v1.2.21

type Environment[W word.Word[W]] interface {
	// Name returns the name of the enclosing function.
	Name() string
	// HasModule checks whether a module with the given name exists and, if so,
	// returns its module identifier. Otherwise, it returns none.
	HasModule(name string) util.Option[ModuleId]
	// HasRegister checks whether a register with the given name exists and, if
	// so, returns its register identifier.  Otherwise, it returns none.
	HasRegister(name string) util.Option[RegisterId]
	// Module returns information about the given module, or none if it does not
	// exist.
	Module(id ModuleId) util.Option[ModuleInfo]
	// Register returns the ith register used in this module.
	Register(id RegisterId) RegisterInfo
	// RegisterCount returns the number of registers in the enclosing module.
	RegisterCount() uint
	// VectorCount returns the number of vectors in the enclosing function.
	VectorCount() uint
	// ValueOf optionally returns the current value held in the given register.
	// This is used (for example) by the debugger to render register values
	// inline within an instruction's string representation.  Environments which
	// have no notion of a "current value" (i.e. those used outside of a concrete
	// execution context) return None.
	ValueOf(id RegisterId) util.Option[W]
}

Environment provides a mechanism to allow Bytecode functions access to information about the enclosing environment. For example, to generate a suitable string for a given instruction, it is useful to know the names of registers in the enclosing function, etc.

type Fail

type Fail[W word.Word[W]] struct {
	// Chunks is the optional formatted-message specification: literal text
	// interleaved with argument formats.  Carried through compilation into the
	// program's chunk side-table rather than encoded inline.
	Chunks []FormattedChunk
	// Source registers used for displaying chunks
	Sources []RegisterVector
}

Fail aborts execution with a "machine panic". It optionally carries a formatted-message specification (the chunks) describing the error; this is held in the program's chunk side-table exactly as Debug's is, and Index identifies this site's entry there — the only thing packed into the bytecode stream (see Codes). When there are no chunks the panic carries no message.

func NewFail

func NewFail[W word.Word[W]](chunks []FormattedChunk, sources []RegisterId) *Fail[W]

NewFail constructs a fail instruction carrying the given formatted message.

func (*Fail[W]) Definitions added in v1.2.21

func (p *Fail[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Fail[W]) String

func (p *Fail[W]) String(env Environment[W]) string

func (*Fail[W]) Uses added in v1.2.21

func (p *Fail[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A fail reads the registers referenced by its formatted (error message) arguments.

func (*Fail[W]) Validate added in v1.2.21

func (p *Fail[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type FieldArith

type FieldArith[W word.Word[W]] struct {
	// Op selects the operation (ADDMOD_P, SUBMOD_P or MULMOD_P).
	Op Operation
	// Target receives the result.
	Target RegisterId
	// Sources are the operand registers, with Sources[0] the leftmost operand.
	Sources []RegisterId
	// Constant is folded into the operation (the identity element when unused:
	// zero for ADDMOD_P / SUBMOD_P, one for MULMOD_P).
	Constant W
}

FieldArith encodes a modular field-arithmetic operation, computing "target = sources[0] op ... op sources[n-1] op constant" reduced modulo the surrounding machine's prime characteristic. The operation is identified by Op, which is one of ADDMOD_P, SUBMOD_P or MULMOD_P. Unlike the integer Arith instruction the result always fits within a single (native) target register, so no cast check is ever required.

func NewFieldArith

func NewFieldArith[W word.Word[W]](op Operation, target RegisterId, sources []RegisterId, constant W) *FieldArith[W]

NewFieldArith constructs a field arithmetic instruction computing "target = sources[0] op ... op constant" modulo the field prime.

func (*FieldArith[W]) Definitions added in v1.2.21

func (p *FieldArith[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*FieldArith[W]) String

func (p *FieldArith[W]) String(env Environment[W]) string

func (*FieldArith[W]) Uses added in v1.2.21

func (p *FieldArith[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*FieldArith[W]) Validate added in v1.2.21

func (p *FieldArith[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type FieldConfig added in v1.2.21

type FieldConfig = field.Config

FieldConfig provides a convenient alias for the field configuration passed to Bytecode.Validate (mirroring the field.Config argument of instruction.Instruction.MicroValidate). Aliasing it here keeps the per- instance Validate signatures free of an otherwise package-wide import.

type FormattedChunk added in v1.2.21

type FormattedChunk struct {
	Text   string
	Format util.Format
}

FormattedChunk pairs a piece of literal text with the format used to render an accompanying value, as used to build fail/debug messages.

func (FormattedChunk) Cmp added in v1.2.21

Cmp compares two formatted chunks lexicographically, first by text and then by format.

type Intrinsic added in v1.2.21

type Intrinsic[W word.Word[W]] struct {
	// Op selects the intrinsic operation (e.g. DIV_HINT or WIDE_SHL).
	Op Operation
	// Targets receive the results (returns) written by this intrinsic.
	Targets []RegisterVector
	// Sources are the argument register vectors read by this intrinsic.
	Sources []RegisterVector
}

Intrinsic performs a built-in operation identified by Op, reading a variable number of arguments (Sources) and writing a variable number of returns (Targets), where each argument and return is a register vector. The supported operations are:

  • DIV_HINT, which reads exactly two arguments (dividend, divisor) and writes exactly three returns (quotient, remainder, range witness) for a division hint (i.e. as produced by the LowerDivisions transform). Specifically, quotient = dividend / divisor, remainder = dividend % divisor and witness = divisor - remainder - 1, with correctness validated by subsequent arithmetic checks. A zero divisor aborts execution with a division-by-zero error.
  • WIDE_SHL, which reads exactly two arguments (value, shift amount) and writes exactly one return (result), computing result = value << shift truncated to the total bitwidth of the target vector. This mirrors the Bitwise SHL instruction but operates over vectored (multi-limb) operands.
  • WIDE_SHR, which reads exactly two arguments (value, shift amount) and writes exactly one return (result), computing result = value >> shift truncated to the total bitwidth of the target vector. This mirrors the Bitwise SHR instruction but operates over vectored (multi-limb) operands.
  • WIDE_DIV, which reads exactly two arguments (dividend, divisor) and writes exactly one return (quotient), computing quotient = dividend / divisor. This mirrors the DIV instruction but operates over vectored (multi-limb) operands. A zero divisor aborts execution with a division-by-zero error.
  • WIDE_REM, which reads exactly two arguments (dividend, divisor) and writes exactly one return (remainder), computing remainder = dividend % divisor. This mirrors the REM instruction but operates over vectored (multi-limb) operands. A zero divisor aborts execution with a division-by-zero error.

func NewIntrinsic added in v1.2.21

func NewIntrinsic[W word.Word[W]](op Operation, targets, sources []RegisterVector) *Intrinsic[W]

NewIntrinsic constructs an intrinsic instruction performing the given operation op (e.g. DIV_HINT) which reads the given source (argument) register vectors and writes the given target (return) register vectors.

func (*Intrinsic[W]) Definitions added in v1.2.21

func (p *Intrinsic[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Intrinsic[W]) String added in v1.2.21

func (p *Intrinsic[W]) String(env Environment[W]) string

func (*Intrinsic[W]) Uses added in v1.2.21

func (p *Intrinsic[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*Intrinsic[W]) Validate added in v1.2.21

func (p *Intrinsic[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface. This checks that the number of arguments and returns matches what the selected operation expects.

type Jmp

type Jmp[W word.Word[W]] struct{ Target Address }

Jmp (unconditional branch) instruction

func Jump

func Jump[W word.Word[W]](target Address) *Jmp[W]

Jump creates an unconditional jump instruction transferring control to the given target address.

func (*Jmp[W]) Definitions added in v1.2.21

func (p *Jmp[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Jmp[W]) String

func (p *Jmp[W]) String(_ Environment[W]) string

func (*Jmp[W]) Uses added in v1.2.21

func (p *Jmp[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*Jmp[W]) Validate added in v1.2.21

func (p *Jmp[W]) Validate(_ FieldConfig, _ Environment[W]) []error

Validate implementation for Bytecode interface.

type ModuleId added in v1.2.21

type ModuleId = uint16

ModuleId represents module identifiers

type ModuleInfo added in v1.2.21

type ModuleInfo interface {
	// Name returns the name of this module.
	Name() string
	// IsFunction indicates whether this module can be called.
	IsFunction() bool
	// HasUnsafeArgs indicates whether a function accepts maybe-undefined arguments.
	HasUnsafeArgs() bool
	// IsMemory indicates whether this module supports memory accesses.
	IsMemory() bool
	// IsReadOnly indicates whether this module forbids writes.
	IsReadOnly() bool
	// IsWriteOnly indicates whether this module forbids reads.
	IsWriteOnly() bool
	// NumInputs returns the number of input registers in this module.
	NumInputs() uint
	// NumOutputs returns the number of output registers in this module.
	NumOutputs() uint
	// Width returns the total number of registers in this module.
	Width() uint
}

ModuleInfo provides a minimal amount of information about a module in the enclosing environment.

type Operation added in v1.2.21

type Operation uint8

Operation identifies an operation performed by a bytecode instruction: an arithmetic operation (ADD, SUB, MUL), a bitwise operation (AND, OR, XOR, NOT, SHL, SHR), a field operation (ADDMOD_P, SUBMOD_P, MULMOD_P) or a hint operation (DIV_HINT, WIDE_SHL, WIDE_SHR, WIDE_DIV, WIDE_REM).

const (
	// OP_ADD integer addition
	OP_ADD Operation = iota
	// OP_SUB integer subtraction
	OP_SUB
	// OP_MUL integer multiplication
	OP_MUL
	// OP_AND bitwise conjunction.
	OP_AND
	// OP_OR bitwise disjunction.
	OP_OR
	// OP_XOR bitwise exclusive-or.
	OP_XOR
	// OP_NOT bitwise negation.
	OP_NOT
	// OP_SHL logical shift left.
	OP_SHL
	// OP_SHR logical shift right.
	OP_SHR
	// OP_ADDMOD_P represents addition modulus the prime P
	OP_ADDMOD_P
	// OP_SUBMOD_P represents subtraction modulus the prime P
	OP_SUBMOD_P
	// OP_MULMOD_P represents multiplication modulus the prime P
	OP_MULMOD_P
	// DIV_HINT is the hint operation which computes the quotient, remainder
	// and range witness for a division hint (see Intrinsic).
	DIV_HINT
	// WIDE_SHL is the hint operation which computes a logical shift left of a
	// (possibly multi-limb) value by a given amount, mirroring the Bitwise SHL
	// instruction but operating over vectored operands (see Intrinsic).
	WIDE_SHL
	// WIDE_SHR is the hint operation which computes a logical shift right of a
	// (possibly multi-limb) value by a given amount, mirroring the Bitwise SHR
	// instruction but operating over vectored operands (see Intrinsic).
	WIDE_SHR
	// WIDE_DIV is the hint operation which computes the quotient of a
	// (possibly multi-limb) dividend and divisor, mirroring the DIV instruction
	// but operating over vectored operands (see Intrinsic).
	WIDE_DIV
	// WIDE_REM is the hint operation which computes the remainder of a
	// (possibly multi-limb) dividend and divisor, mirroring the REM instruction
	// but operating over vectored operands (see Intrinsic).
	WIDE_REM
)

func (Operation) Prefix added in v1.2.21

func (p Operation) Prefix() string

Prefix returns a suitable "prefix" string for this operator.

func (Operation) Symbol added in v1.2.21

func (p Operation) Symbol() string

Symbol returns a suitable string representation of this operator.

type ReadWrite

type ReadWrite[W word.Word[W]] struct {
	// Write distinguishes a memory write (true) from a memory read (false).
	Write bool
	// Identifies the memory being read or written.
	Id uint16
	// Address lines used to determine which data row to read.
	Address []RegisterId
	// Data lines identify where the data row is written.
	Data []RegisterId
}

ReadWrite instruction captures memory read/writes. It records only whether the access is a read or a write; the kind of memory being accessed (ROM, RAM, etc.) is resolved from the enclosing environment when the instruction is encoded.

func NewMemRead added in v1.2.21

func NewMemRead[W word.Word[W]](id uint16, address []RegisterId, data []RegisterId) *ReadWrite[W]

NewMemRead constructs a memory-read instruction. The data registers receive the row located at the address given by the address registers, in the memory identified by id. The kind of memory being read (ROM, static ROM, RAM, paged RAM) is not recorded here: it is resolved from the environment when the instruction is encoded.

func NewMemWrite added in v1.2.21

func NewMemWrite[W word.Word[W]](id uint16, address []RegisterId, data []RegisterId) *ReadWrite[W]

NewMemWrite constructs a memory-write instruction. The data registers are written to the row located at the address given by the address registers, in the memory identified by id. The kind of memory being written (write-once, RAM, paged RAM) is not recorded here: it is resolved from the environment when the instruction is encoded.

func (*ReadWrite[W]) Definitions added in v1.2.21

func (p *ReadWrite[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface. A read defines its data registers, whereas a write defines nothing in the surrounding frame.

func (*ReadWrite[W]) String

func (p *ReadWrite[W]) String(env Environment[W]) string

func (*ReadWrite[W]) Uses added in v1.2.21

func (p *ReadWrite[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A read uses only its address registers, whereas a write uses both the address and data registers.

func (*ReadWrite[W]) Validate added in v1.2.21

func (p *ReadWrite[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type RegisterId added in v1.2.21

type RegisterId = uint16

RegisterId just provides a convenient alias to make the code more readable.

type RegisterInfo added in v1.2.21

type RegisterInfo interface {
	// Name returns the  name of this register
	Name() string
	// Bitwidth returns the bitwidth of this register, or the empty option for a
	// native register (which has no fixed bitwidth).  Used by Bytecode.Validate
	// to detect width overflows.
	Bitwidth() util.Option[uint]
}

RegisterInfo provides a minimal amount of information about a register in the enclosing function.

type RegisterVector added in v1.2.21

type RegisterVector struct {
	// Base identifies the first register in the vector (i.e. that with the
	// least index).
	Base RegisterId
	// Len identifies the length of the vector.
	Len uint16
}

RegisterVector is a "register vector". That is, a set of n consecutively indexed registers.

func NewRegisterVector added in v1.2.21

func NewRegisterVector(regs ...RegisterId) RegisterVector

NewRegisterVector constructs a new register vector from an array of registers. These registers must be consecutively indexed, else this will panic.

func (RegisterVector) Registers added in v1.2.21

func (p RegisterVector) Registers() []RegisterId

Registers returns the individual registers making up this vector, in increasing index order (Base first). Note that register splitting lays limbs out most-significant first (see split.ApplyLimbsMap), so the lowest-indexed register (Base) holds the most-significant limb.

func (RegisterVector) String added in v1.2.21

func (p RegisterVector) String() string

type Ret

type Ret[W word.Word[W]] struct {
}

Ret (return from function call) instruction.

func NewRet

func NewRet[W word.Word[W]]() *Ret[W]

NewRet constructs a return instruction with the given frame width and return offset.

func (*Ret[W]) Definitions added in v1.2.21

func (p *Ret[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Ret[W]) String

func (p *Ret[W]) String(_ Environment[W]) string

func (*Ret[W]) Uses added in v1.2.21

func (p *Ret[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. The copying of return values is handled by the frame machinery rather than by named register operands, so a return reads no registers here.

func (*Ret[W]) Validate added in v1.2.21

func (p *Ret[W]) Validate(_ FieldConfig, _ Environment[W]) []error

Validate implementation for Bytecode interface.

type Skip added in v1.2.21

type Skip[W word.Word[W]] struct{ Skip uint16 }

Skip (unconditional skip) instruction

func NewSkip added in v1.2.21

func NewSkip[W word.Word[W]](skip uint16) *Skip[W]

NewSkip constructs an uncondition skip instruction which skips over n instructions.

func (*Skip[W]) Definitions added in v1.2.21

func (p *Skip[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Skip[W]) String added in v1.2.21

func (p *Skip[W]) String(_ Environment[W]) string

func (*Skip[W]) Uses added in v1.2.21

func (p *Skip[W]) Uses() []RegisterId

Uses implementation for Bytecode interface.

func (*Skip[W]) Validate added in v1.2.21

func (p *Skip[W]) Validate(_ FieldConfig, _ Environment[W]) []error

Validate implementation for Bytecode interface.

type SkipIf added in v1.2.21

type SkipIf[W word.Word[W]] struct {
	Skip  uint16
	Left  RegisterVector
	Right RegisterVector
	Op    Condition
}

SkipIf instruction performs a conditional skip over a given number of codes. This is a *vectored* instruction, meaning the condition compares two register *vectors*. For evaluating the condition, the interpretation of a vector is that the least significant register has the least index in the vector. Two compare two vectors "left" and "right" of equal length, we find the highest index i where left[i] != right[i]. If no such index exists, the vectors are equal. Otherwise, if left[i] < right[i] the left vector is "less than" the right, otherwise it is "greater than" the right. Then, the skip is taken or not depending on the condition opcode.

NOTE: currently their is an assumption that both vectors have the same length. This assumption could be relaxed in the future.

func NewSkipIf added in v1.2.21

func NewSkipIf[W word.Word[W]](op Condition, skip uint16, left, right RegisterId) *SkipIf[W]

NewSkipIf constructs a conditional branch instruction which jumps to the target address when "left op right" holds, comparing single registers.

func NewSkipIfVec added in v1.2.21

func NewSkipIfVec[W word.Word[W]](op Condition, skip uint16, left, right RegisterVector) *SkipIf[W]

NewSkipIfVec constructs a conditional branch instruction which jumps to the target address when "left op right" holds, comparing multi-limb register vectors.

func (*SkipIf[W]) Definitions added in v1.2.21

func (p *SkipIf[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*SkipIf[W]) String added in v1.2.21

func (p *SkipIf[W]) String(env Environment[W]) string

func (*SkipIf[W]) Uses added in v1.2.21

func (p *SkipIf[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A conditional skip reads both operand vectors being compared.

func (*SkipIf[W]) Validate added in v1.2.21

func (p *SkipIf[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface.

type Switch

type Switch[W word.Word[W]] struct {
	Source RegisterId
	Cases  []SwitchCase[W]
}

Switch (skip multiway) dispatches on the value of a source register: it is compared, in order, against each case's value and, on the first match, control transfers to that case's target. If no case matches, control falls through to the following instruction.

Encoding (1 + 3*len(Cases) words):

31      24 23       8 7      0
+---------+----------+--------+
|  count  |  source  | opcode |   word 0
+---------+----------+--------+
| .......... value_lo .......|   word 1   (case 0)
| .......... value_hi .......|   word 2
| .......... target .........|   word 3
|             ...            |            (further cases)

Here count is the number of cases (<= 255), source is the dispatch register, and each case occupies three words: a 64-bit value (low word then high word) followed by an absolute target address.

func MultiwaySkip

func MultiwaySkip[W word.Word[W]](source RegisterId, cases []SwitchCase[W]) *Switch[W]

MultiwaySkip constructs a multiway-skip (SMW) instruction which dispatches on the value of the source register against the given (value, target) table. Targets are label indices until resolved during encoding (see Smw.Patch).

func (*Switch[W]) Definitions added in v1.2.21

func (p *Switch[W]) Definitions() []RegisterId

Definitions implementation for Bytecode interface.

func (*Switch[W]) String

func (p *Switch[W]) String(_ Environment[W]) string

func (*Switch[W]) Uses added in v1.2.21

func (p *Switch[W]) Uses() []RegisterId

Uses implementation for Bytecode interface. A multiway skip reads the dispatch (source) register it compares against each case value.

func (*Switch[W]) Validate added in v1.2.21

func (p *Switch[W]) Validate(_ FieldConfig, env Environment[W]) []error

Validate implementation for Bytecode interface. This mirrors base.SkipMulti.MicroValidate: every dispatch value must be unique (since the first match wins, a duplicate is unreachable and almost certainly a mistake) and must fit within the source register's width. A native source register holds arbitrary-width values, so no value can overflow it.

type SwitchCase

type SwitchCase[W any] struct {
	// Value compared against the source register.
	Value W
	// Skip amount.
	Skip uint16
}

SwitchCase is a single (value, target) entry of a multiway-skip dispatch table: when the source register holds Value, control transfers to Target.

type Vector added in v1.2.21

type Vector[W word.Word[W]] struct {
	Bytecodes []Bytecode[W]
}

Vector instructions are instructions composed of some number of micro instructions which, with restrictions, can be executed by the underlying machine "in parallel". The approach is analoguous to the concept of "Very-Long Instruction Words (VLIW)" but taken to more of an extreme --- there is no limit on the number of micro-instructions.

To better understand vector instructions, consider two instructions executed in sequence (the at pc location 0, the second at pc location 1):

(pc=0) x = y + 1 (pc=1) z = 0

When executing these instructions, there is an intermediate state after the first instruction is executed but before the second has been where x has been written but z has not. Alternatively, the two instructions can be composed together to form a vector instruction, written like so:

(pc=0) x = y + 1 ; z = 0

In this case, both instructions are executed together and there is no intermediate state where x is written but z is not.

To ensure easy translation into polynomial constraints, there are restrictions on how vector instructions can be composed. In particular, no variable can be assigned twice on the same execution path. Thus, for example, this is an invalid vector instruction:

(pc=0) x = 0 ; x = 1

These writes are said to be _conflicting_. In contrast, the following is a valid vector instruction:

(pc=0) skip_if x != y 2 ; r = 0 ; ret ; r = 1 ; ret

In this case, whilst there are two assignments to register r, neither are on the same path. These writes are said to be _non-conflicting_. Finally, we should note that register forwarding is applied within vector instructions. Thus, for example, the following is allowed:

(pc=0) x = 0; y = x + 1; ret

Here, the value of x written in the instruction is "forwarded" to the assignment for y. This process is, roughly speaking, analoguous to register forwarding as found in CPU architectures.

func NewVector added in v1.2.21

func NewVector[W word.Word[W]](bytecodes ...Bytecode[W]) Vector[W]

NewVector creates a new Vector instruction from a variadic list of Bytecode instructions. A Vector instruction is composed of multiple micro-instructions that can be executed "in parallel" by the underlying machine with certain restrictions to ensure easy translation into polynomial constraints.

The function accepts a variadic parameter of Bytecode instructions and returns a Vector containing those bytecodes.

func (*Vector[W]) BranchTable added in v1.2.21

func (p *Vector[W]) BranchTable() (dfa.Result[dfa.Writes], dfa.Result[dfa.Path[W]])

BranchTable returns the branch table for this vector instruction, and also its write map (since this is needed to compute the branch table anway). The branch table maps a _branch condition_ to each bytecode in the vector. This identifies the conditions under which the given bytecode will execute. For example, consider the following sequence:

skip_if x!=0 1; y=0; skip_if x!=1 2; y=1; ret; y = 2; ret --------------+----+---------------+----+----+------+---- 0 | 1 | 2 | 3 | 4 | 5 | 6

This sequence gives rise to the following branch table:

--+-------------+----------------------- 0 | skip_if ... | TRUE 1 | y=0 | x==0 2 | skip_if ... | x!=0 3 | y=1 | x!=0 && x==1 ==> x==1 4 | ret | x!=0 && x==1 ==> x==1 5 | y=2 | x!=0 && x!=1 6 | ret | x!=0 && x!=1 --+-------------+-----------------------

Observe that the optimiser automatically reduces "x!=0 && x==1" to just x==1 (this is why it is sometimes called _branch table optimisation_).

func (*Vector[W]) Map added in v1.2.21

func (p *Vector[W]) Map(fun func(uint, Bytecode[W]) []Bytecode[W]) Vector[W]

Map applies a function over each instruction in the vector which returns zero or more registers. For example, the function could return nothing whenever it sees a "skip 0" operation (since this is a no-op). A key feature of this function, however, is that it updates skip offsets correctly account the changes in width of instructions. For example, consider this scenario:

> skip_if x == 0 2 ; skip 0 ; ret ; jmp 1

Then applying a map to remove "skip 0" instructions yields the following:

> skip_if x == 0 1 ; ret ; jmp 1

Specifically, we that the offset for the skip_if has been updated to reflect its new branch destination. Observer, however, that the mapping process can fail if the mapping function is ill-behaved. Consider this simple example:

> skip 1 ; ret ; jmp 1

Applying a mapping function which removed the "jmp 1" (for whatever reason) would lead to an invalid instruction and, hence, a mapping failure. Currently, mapping failures simply result in panics.

func (*Vector[W]) String added in v1.2.21

func (p *Vector[W]) String(env Environment[W]) string

String returns a human-readable representation of this vector, rendering each constituent bytecode (resolved against the given environment) separated by " ; ". This mirrors instruction.Vector.String.

func (*Vector[W]) Validate added in v1.2.21

func (p *Vector[W]) Validate(field FieldConfig, env Environment[W]) []error

Validate checks that this vector instruction is well-formed: every constituent bytecode must itself be well-formed, and there must be no conflicting reads or writes on any execution path. This mirrors instruction.Vector.Validate.

A write conflict arises when a register is written which _may_ already have been written on the same path; a read conflict arises when a register is read which _may_ (but not _definitely_) have been written.

func (*Vector[W]) WriteMap added in v1.2.21

func (p *Vector[W]) WriteMap() dfa.Result[dfa.Writes]

WriteMap constructs the write map for this vector instruction.

For each bytecode, the write map records — on entry to that bytecode — which registers have been written by preceding bytecodes (on any path to this point). This identifies: (1) whether a register _may_ have been written on some path; (2) or, whether it was _definitely_ written along all paths. For example, consider the following sequence:

x = 0; skip_if ... 1; y = 0; ret

When execution reaches the return bytecode, we know that x was definitely written but only that y may have been written (i.e. depending on which path was taken).

The write map serves two purposes: firstly, it allows conflict detection; secondly, it identifies where register forwarding should be used. A write conflict arises when a register is written which _may_ have already been written; likewise a read conflict arises when a register is read that _may_ (but not _definitely_) have been written. Finally, register forwarding arises when a register has _definitely_ been written by an earlier bytecode in the vector and, hence, subsequent reads use the new value (rather than the previous value).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL