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

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

Link copied to clipboard

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

Properties

Link copied to clipboard

The descriptive name of the code being translated.

Link copied to clipboard

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

Link copied to clipboard

The control flow graph being generated.

Link copied to clipboard

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

Link copied to clipboard

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

Link copied to clipboard
Link copied to clipboard

The topmost Frame for translation.

Functions

Link copied to clipboard

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

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

Link copied to clipboard

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

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

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

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

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

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

Link copied to clipboard

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

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

Link copied to clipboard

Cause a tuple to be constructed from the given L2ReadBoxedOperands.

Link copied to clipboard

Answer the current L2BasicBlock being generated.

Link copied to clipboard

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

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

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

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

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, forceRegister: L2FloatRegister? = null): 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

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

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, forceRegister: L2IntRegister? = null): 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

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, optionalName: String? = null)

Emit an instruction to jump to the specified L2BasicBlock.

Link copied to clipboard

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

Create a new L2SemanticValue to use as a temporary value.

Link copied to clipboard

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

Link copied to clipboard

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

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

Link copied to clipboard

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
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

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

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

Link copied to clipboard

Pass-through to L2ControlFlowGraph.