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
The OptimizationLevel for controlling code generation.
The topmost Frame for code generation.
The descriptive name of the code being translated.
Types
A class for finding the highest numbered register of each time.
An enumeration of symbolic names of key blocks of the controlFlowGraph. These are associated with optional L2BasicBlocks within the generator's specialBlocks.
Functions
Record the fact that the chunk being created depends on the given A_ChunkDependable. If that A_ChunkDependable changes, the chunk will be invalidated.
Add an L2Instruction.
Create and add an L2Instruction with the given L2Operation and variable number of L2Operands.
Add an instruction that's not supposed to be reachable.
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.
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.
Allocate a new L2BoxedRegister. Answer an L2WriteBoxedOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.
Return the L2Chunk previously created via createChunk.
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.
Generate a Level Two chunk from the control flow graph. Store it in the L2Generator, from which it can be retrieved via chunk.
Create an L2BasicBlock, and mark it as a loop head.
Cause a tuple to be constructed from the given L2ReadBoxedOperands.
Answer the current L2BasicBlock being generated.
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.
Given a register that holds the function to invoke, answer either the A_RawFunction it will be known to run, or null.
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.
Given a register containing a function and a parameter index, emit code to extract the parameter type at runtime from the actual function.
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.
Allocate a new L2FloatRegister. Answer an L2WriteFloatOperand that writes to it as the given L2SemanticValue, restricting it with the given TypeRestriction.
Allocate a new L2FloatRegister. Answer an L2WriteFloatOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.
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.
Allocate a new L2IntRegister. Answer an L2WriteIntOperand that writes to it as the given L2SemanticValues, restricted with the given TypeRestriction.
Allocate a new L2IntRegister. Answer an L2WriteIntOperand that writes to it as a new temporary L2SemanticValue, restricting it with the given TypeRestriction.
Generate a conditional branch to either passBlock or failBlock, based on whether the given register equals the given constant value.
Generate code to test the value in valueRead against the constant expectedType, jumping to passedCheck if it conforms, or failedCheck otherwise.
Emit an instruction to jump to the specified L2BasicBlock.
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.
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.
Create a new L2SemanticValue to use as a temporary value.
Answer the next value from the unique counter. This is only used to distinguish registers for visual debugging.
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.
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.
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.
Pass-through to L2ControlFlowGraph.
Start code generation for the given L2BasicBlock. Unless this is a loop head, ensure all predecessor blocks have already finished generation.
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.
Answer an L2PcOperand that targets an L2BasicBlock which should never actually be dynamically reached.
Pass-through to L2ControlFlowGraph.
Properties
All contingent values for which changes should cause the current Level Two chunk to be invalidated.
Use this L2ValueManifest to track which L2Register holds which L2SemanticValue at the current code generation point.
The amount of effort to apply to the current optimization attempt.
An EnumMap from symbolic SpecialBlock to optional L2BasicBlock.