L2Generator

class L2Generator

The L2Generator converts a Level One function into a Level Two chunk. It optimizes as it does so, folding and inlining method invocations whenever possible.

Author

Mark van Gulik

Parameters

optimizationLevel

The OptimizationLevel for controlling code generation.

topFrame

The topmost Frame for code generation.

codeName

The descriptive name of the code being translated.

Types

Link copied to clipboard
object Companion
Link copied to clipboard
class RegisterCounter : L2OperandDispatcher

A class for finding the highest numbered register of each time.

Link copied to clipboard
enum SpecialBlock : Enum<L2Generator.SpecialBlock>

An enumeration of symbolic names of key blocks of the controlFlowGraph. These are associated with optional L2BasicBlocks within the generator's specialBlocks.

Functions

Link copied to clipboard
fun addContingentValue(contingentValue: A_ChunkDependable)

Record the fact that the chunk being created depends on the given A_ChunkDependable. If that A_ChunkDependable changes, the chunk will be invalidated.

Link copied to clipboard
fun addInstruction(instruction: L2Instruction): Unit?
fun addInstruction(operation: L2Operation, vararg operands: L2Operand): Unit?

Create and add an L2Instruction with the given L2Operation and variable number of L2Operands.

Link copied to clipboard
fun addUnreachableCode()

Add an instruction that's not supposed to be reachable.

Link copied to clipboard
fun boxedConstant(value: A_BasicObject): L2ReadBoxedOperand

Generate code to move the given constant into a boxed register, if it's not already known to be in a boxed register. Answer an L2ReadBoxedOperand to retrieve this value.

Link copied to clipboard
fun boxedWrite(semanticValue: L2SemanticValue, restriction: TypeRestriction): L2WriteBoxedOperand

Allocate a new L2BoxedRegister. Answer an L2WriteBoxedOperand that writes to it as the given L2SemanticValue, restricting it with the given TypeRestriction.

fun boxedWrite(semanticValues: Set<L2SemanticValue>, restriction: TypeRestriction): L2WriteBoxedOperand

Allocate a new L2BoxedRegister. Answer an L2WriteBoxedOperand that writes to it as the given L2SemanticValues, restricting it with the given TypeRestriction.

Link copied to clipboard
fun boxedWriteTemp(restriction: TypeRestriction): L2WriteBoxedOperand

Allocate a new L2BoxedRegister. Answer an L2WriteBoxedOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.

Link copied to clipboard
fun chunk(): L2Chunk

Return the L2Chunk previously created via createChunk.

Link copied to clipboard
fun createBasicBlock(name: String): L2BasicBlock

Create a new L2BasicBlock. It's initially not connected to anything, and is ignored if it is never actually added with startBlock.

fun createBasicBlock(name: String, zone: L2ControlFlowGraph.Zone?): L2BasicBlock

Create an L2BasicBlock, and mark it as used for reification.

Link copied to clipboard
fun createChunk(code: A_RawFunction)

Generate a Level Two chunk from the control flow graph. Store it in the L2Generator, from which it can be retrieved via chunk.

Link copied to clipboard
fun createLoopHeadBlock(name: String): L2BasicBlock

Create an L2BasicBlock, and mark it as a loop head.

Link copied to clipboard
fun createTuple(elements: List<L2ReadBoxedOperand>): L2ReadBoxedOperand

Cause a tuple to be constructed from the given L2ReadBoxedOperands.

Link copied to clipboard
fun currentBlock(): L2BasicBlock

Answer the current L2BasicBlock being generated.

Link copied to clipboard
fun currentlyReachable(): Boolean

Determine whether the current block is probably reachable. If it has no predecessors and is removable, it's unreachable, but otherwise we assume it's reachable, at least until dead code elimination.

Link copied to clipboard
fun determineRawFunction(functionToCallReg: L2ReadBoxedOperand): A_RawFunction?

Given a register that holds the function to invoke, answer either the A_RawFunction it will be known to run, or null.

Link copied to clipboard
fun explodeTupleIfPossible(tupleReg: L2ReadBoxedOperand, requiredTypes: List<A_Type>): List<L2ReadBoxedOperand>?

Given a register that will hold a tuple, check that the tuple has the number of elements and statically satisfies the corresponding provided type constraints. If so, generate code and answer a list of register reads corresponding to the elements of the tuple; otherwise, generate no code and answer null.

Link copied to clipboard
fun extractParameterTypeFromFunction(functionRead: L2ReadBoxedOperand, parameterIndex: Int): L2ReadBoxedOperand

Given a register containing a function and a parameter index, emit code to extract the parameter type at runtime from the actual function.

Link copied to clipboard
fun extractTupleElement(tupleReg: L2ReadBoxedOperand, index: Int): L2ReadBoxedOperand

Given a register that will hold a tuple and a fixed index that is known to be in range, generate code and answer a L2ReadBoxedOperand that accesses that element.

Link copied to clipboard
fun floatWrite(semanticValues: Set<L2SemanticUnboxedFloat>, restriction: TypeRestriction): L2WriteFloatOperand

Allocate a new L2FloatRegister. Answer an L2WriteFloatOperand that writes to it as the given L2SemanticValue, restricting it with the given TypeRestriction.

Link copied to clipboard
fun floatWriteTemp(restriction: TypeRestriction): L2WriteFloatOperand

Allocate a new L2FloatRegister. Answer an L2WriteFloatOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.

Link copied to clipboard
fun generateRetroactivelyBeforeEdge(edge: L2PcOperand, body: L2Generator.() -> Unit)

Temporarily switch my state to generate code just prior to the control flow altering instruction leading to this edge. Update the edge's manifest, under the assumption that the newly generated code and the (existing) final instruction of the block do not interfere in terms of the semantic values they populate and consume.

Link copied to clipboard
fun intWrite(semanticValues: Set<L2SemanticUnboxedInt>, restriction: TypeRestriction): L2WriteIntOperand

Allocate a new L2IntRegister. Answer an L2WriteIntOperand that writes to it as the given L2SemanticValues, restricted with the given TypeRestriction.

Link copied to clipboard
fun intWriteTemp(restriction: TypeRestriction): L2WriteIntOperand

Allocate a new L2IntRegister. Answer an L2WriteIntOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.

Link copied to clipboard
fun jumpIfEqualsConstant(    registerToTest: L2ReadBoxedOperand,     constantValue: A_BasicObject,     passBlock: L2BasicBlock,     failBlock: L2BasicBlock)

Generate a conditional branch to either passBlock or failBlock, based on whether the given register equals the given constant value.

Link copied to clipboard
fun jumpIfKindOfConstant(    valueRead: L2ReadBoxedOperand,     expectedType: A_Type,     passedCheck: L2BasicBlock,     failedCheck: L2BasicBlock)

Generate code to test the value in valueRead against the constant expectedType, jumping to passedCheck if it conforms, or failedCheck otherwise.

Link copied to clipboard
fun jumpTo(targetBlock: L2BasicBlock)

Emit an instruction to jump to the specified L2BasicBlock.

Link copied to clipboard
fun makeImmutable(read: L2ReadBoxedOperand): L2ReadBoxedOperand

Generate code to ensure an immutable version of the given register is written to the returned register. Update the currentManifest to indicate that after this point, the returned register should be used for reading the boxed form of the given register's semantic values.

Link copied to clipboard
fun <R : L2Register, RR : L2ReadOperand<R>, WR : L2WriteOperand<R>, RV : L2ReadVectorOperand<R, RR>> moveRegister(    moveOperation: L2_MOVE<R, RR, WR, RV>,     sourceSemanticValue: L2SemanticValue,     targetSemanticValue: L2SemanticValue)

Generate instructions to arrange for the value in the given L2ReadOperand to end up in an L2Register associated in the L2ValueManifest with the new L2SemanticValue. After the move, the synonyms for the source and destination are effectively merged, which is justified by virtue of SSA (static-single-assignment) being in effect.

Link copied to clipboard
fun newTemp(): L2SemanticValue

Create a new L2SemanticValue to use as a temporary value.

Link copied to clipboard
fun nextUnique(): Int

Answer the next value from the unique counter. This is only used to distinguish registers for visual debugging.

Link copied to clipboard
fun readBoxed(write: L2WriteBoxedOperand): L2ReadBoxedOperand

Given an L2WriteBoxedOperand, produce an L2ReadBoxedOperand of the same value, but with the current manifest's TypeRestriction applied.

fun readBoxed(semanticValue: L2SemanticValue): L2ReadBoxedOperand

Answer an L2ReadBoxedOperand for the given L2SemanticValue, generating code to transform it as necessary.

Link copied to clipboard
fun readFloat(semanticUnboxed: L2SemanticUnboxedFloat, onFailure: L2BasicBlock): L2ReadFloatOperand

Return an L2ReadFloatOperand for the given L2SemanticUnboxedFloat. The TypeRestriction must have been proven by the VM. If the semantic value only has a boxed form, generate code to unbox it.

Link copied to clipboard
fun readInt(semanticUnboxed: L2SemanticUnboxedInt, onFailure: L2BasicBlock): L2ReadIntOperand

Return an L2ReadIntOperand for the given L2SemanticUnboxedInt. The TypeRestriction must have been proven by the VM. If the semantic value only has a boxed form, generate code to unbox it.

Link copied to clipboard
fun simplyVisualize(): String

Pass-through to L2ControlFlowGraph.

Link copied to clipboard
fun startBlock(    block: L2BasicBlock,     generatePhis: Boolean = true,     regenerator: L2Regenerator? = null)

Start code generation for the given L2BasicBlock. Unless this is a loop head, ensure all predecessor blocks have already finished generation.

Link copied to clipboard
fun unboxedIntConstant(value: Int): L2ReadIntOperand

Generate code to move the given int constant into an unboxed int register, if it's not already known to be in such a register. Answer an L2ReadIntOperand to retrieve this value.

Link copied to clipboard
fun unreachablePcOperand(): L2PcOperand

Answer an L2PcOperand that targets an L2BasicBlock which should never actually be dynamically reached.

Link copied to clipboard
fun visualize(): String

Pass-through to L2ControlFlowGraph.

Properties

Link copied to clipboard
val codeName: String

The descriptive name of the code being translated.

Link copied to clipboard
var contingentValues: A_Set

All contingent values for which changes should cause the current Level Two chunk to be invalidated.

Link copied to clipboard
val controlFlowGraph: L2ControlFlowGraph

The control flow graph being generated.

Link copied to clipboard
var currentManifest: L2ValueManifest

Use this L2ValueManifest to track which L2Register holds which L2SemanticValue at the current code generation point.

Link copied to clipboard
val optimizationLevel: OptimizationLevel

The amount of effort to apply to the current optimization attempt.

Link copied to clipboard

An EnumMap from symbolic SpecialBlock to optional L2BasicBlock.

Link copied to clipboard
val topFrame: Frame

The topmost Frame for translation.