L2_PHI_PSEUDO_OPERATION

The L2_PHI_PSEUDO_OPERATION occurs at the start of a L2BasicBlock. It's a convenient fiction that allows an L2ControlFlowGraph to be in Static Single Assignment form (SSA), where each L2Register has exactly one instruction that writes to it.

The vector of source registers are in the same order as the corresponding predecessors of the containing L2BasicBlock. The runtime effect would be to select from that vector, based on the predecessor from which control arrives, and move that register's value to the destination register. However, that's a fiction, and the phi operation is instead removed during the transition of the control flow graph out of SSA, being replaced by move instructions along each incoming edge.

Author

Mark van Gulik

Parameters

readOperandType

The L2NamedOperandType that describes the read source of this move.

writeOperandType

The L2NamedOperandType that describes the write destination of this move.

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
open override fun appendToWithWarnings(    instruction: L2Instruction,     desiredTypes: Set<L2OperandType>,     builder: StringBuilder,     warningStyleChange: (Boolean) -> Unit)

Produce a sensible textual rendition of the specified L2Instruction.

Link copied to clipboard
fun <W : L2WriteOperand<R>> destinationRegisterWrite(instruction: L2Instruction): W

Answer the L2WriteOperand from this phi function. This should only be used when generating phi moves (which takes the L2ControlFlowGraph out of Static Single Assignment form).

Link copied to clipboard
open override fun emitTransformedInstruction(transformedOperands: Array<L2Operand>, regenerator: L2Regenerator)

Write the given L2Operation's equivalent effect through the given L2Regenerator, with the given already-transformed L2Operands.

Link copied to clipboard
open fun extractFunctionOuter(    instruction: L2Instruction,     functionRegister: L2ReadBoxedOperand,     outerIndex: Int,     outerType: A_Type,     generator: L2Generator): L2ReadBoxedOperand

Emit code to extract the specified outer value from the function produced by this instruction. The new code is appended to the provided list of instructions, which may be at a code generation position unrelated to the receiver. The extracted outer variable will be written to the provided target register.

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

Produce an L2ReadBoxedOperand that provides the specified index of the tuple in the given register. If the source of that index is not readily available, generate code to produce it from the tuple, and answer the resulting L2ReadBoxedOperand.

Link copied to clipboard
fun generatePhi(    generator: L2Generator,     relatedSemanticValues: List<L2SemanticValue>,     forcePhiCreation: Boolean,     typeRestriction: TypeRestriction,     sourceManifests: List<L2ValueManifest>)

Generate an L2_PHI_PSEUDO_OPERATION and any additional moves to ensure the given set of related L2SemanticValues are populated with values from the given sources.

Link copied to clipboard
open override fun generateReplacement(instruction: L2Instruction, regenerator: L2Regenerator)

We don't need to do anything for phi instructions, since the generator framework itself handles it. This includes forcing creation of phi instructions when an L2SemanticValue is present in every incoming edge.

Link copied to clipboard
open fun getConstantCodeFrom(instruction: L2Instruction): A_RawFunction?

Extract the constant A_RawFunction that's enclosed by the function produced or passed along by this instruction.

Link copied to clipboard
open fun hasSideEffect(instruction: L2Instruction): Boolean

Answer whether the given L2Instruction (whose operation must be the receiver) changes the state of the interpreter in any way other than by writing to its destination registers. Most operations are computational and don't have side effects.

Link copied to clipboard
open override fun instructionWasAdded(instruction: L2Instruction, manifest: L2ValueManifest)

This is the operation for the given instruction, which was just added to its basic block. Do any post-processing appropriate for having added the instruction. Its operands have already had their instruction fields set to the given instruction.

Link copied to clipboard
fun instructionWasInserted(instruction: L2Instruction)

This is the operation for the given instruction, which was just inserted into its basic block as part of an optimization pass. Do any post-processing appropriate for having inserted the instruction.

Link copied to clipboard
open fun isEntryPoint(instruction: L2Instruction): Boolean

Is the enclosing L2Instruction an entry point into its L2Chunk?

Link copied to clipboard
fun operandTypes(): Array<out L2NamedOperandType>

Answer the named operand types that this L2Operation operation expects.

Link copied to clipboard
fun predecessorBlocksForUseOf(instruction: L2Instruction, usedRegister: L2Register): List<L2BasicBlock>

Examine the instruction and answer the predecessor L2BasicBlocks that supply a value from the specified register.

Link copied to clipboard
open fun primitiveResultRegister(instruction: L2Instruction): L2WriteBoxedOperand?

If this instruction is an attempt to execute a primitive, answer the register into which the primitive's result will be written if successful. Otherwise answer null.

Link copied to clipboard
open override fun shouldEmit(instruction: L2Instruction): Boolean

Answer whether an instruction using this operation should be emitted during final code generation. For example, a move between registers with the same finalIndex can be left out during code generation, although it can't actually be removed before then.

Link copied to clipboard
fun simpleAppendTo(instruction: L2Instruction, builder: StringBuilder)

Output the instruction compactly to the builder.

Link copied to clipboard
fun sourceRegisterReads(instruction: L2Instruction): List<RR>

Answer the List of L2ReadOperands for this phi function. The order is correlated to the instruction's blocks predecessorEdges.

Link copied to clipboard
open fun targetEdges(instruction: L2Instruction): List<L2PcOperand>

Extract the operands which are L2PcOperands. These are what lead to other L2BasicBlocks. They also carry an edge-specific array of slots, and edge-specific TypeRestrictions for registers.

Link copied to clipboard
open override fun toString(): String
Link copied to clipboard
open override fun translateToJVM(    translator: JVMTranslator,     method: MethodVisitor,     instruction: L2Instruction)

Translate the specified L2Instruction into corresponding JVM instructions.

Link copied to clipboard
fun updateLoopHeadPhi(predecessorManifest: L2ValueManifest, instruction: L2Instruction)

Update an L2_PHI_PSEUDO_OPERATION instruction that's in a loop head basic block.

Link copied to clipboard
fun withoutIndex(instruction: L2Instruction, inputIndex: Int): L2Instruction

One of this phi function's predecessors has been removed because it's dead code. Clean up its vector of inputs by removing the specified index.

Properties

Link copied to clipboard
open val altersControlFlow: Boolean

Answer whether execution of this instruction can divert the flow of control from the next instruction. An L2Operation either always falls through or always alters control.

Link copied to clipboard
open val goesMultipleWays: Boolean

Answer true if this instruction leads to multiple targets, multiple of which can be reached. This is not the same as a branch, in which only one will be reached for any circumstance of reaching this instruction. In particular, an L2_SAVE_ALL_AND_PC_TO_INT instruction jumps to its fall-through label, but after reification has saved the live register state, it gets restored again and winds up traversing the other edge.

Link copied to clipboard
open val hasSideEffect: Boolean

Answer whether this L2Operation changes the state of the interpreter in any way other than by writing to its destination registers. Most operations are computational and don't have side effects.

Link copied to clipboard
open val isMove: Boolean

Answer whether this operation is a move between (compatible) registers.

Link copied to clipboard
open override val isPhi: Boolean

Answer whether this operation is a phi-function. This is a convenient fiction that allows control flow to merge while in SSA form.

Link copied to clipboard
open val isPlaceholder: Boolean

Answer whether this operation is a placeholder, and should be replaced using the L2Regenerator. Placeholder instructions (like L2_VIRTUAL_CREATE_LABEL) are free to be moved through much of the control flow graph, even though the subgraphs they eventually get replaced by would be too complex to move. The mobility of placeholder instructions is essential to postponing stack reification and label creation into off-ramps (reification Zones) as much as possible.

Link copied to clipboard
open val isUnconditionalJump: Boolean

Answer whether this operation causes unconditional control flow jump to another L2BasicBlock.

Link copied to clipboard
open val isVariableGet: Boolean

Answer whether execution of this instruction causes a variable to be read.

Link copied to clipboard
open val isVariableSet: Boolean

Answer whether execution of this instruction causes a variable to be written.

Link copied to clipboard
val moveOperation: L2_MOVE<R, RR, WR, RV>

The L2_MOVE operation to substitute for this instruction on incoming split edges.

Link copied to clipboard
val name: String

Initialize the name from the constructor argument, or produce a default if it was unspecified or null.

Link copied to clipboard
val namedOperandTypes: Array<out L2NamedOperandType>

The named operand types that this operation expects.

Link copied to clipboard
var readsHiddenVariablesMask: Int = 0

The bitwise-or of the masks of HiddenVariables that are read by L2Instructions using this operation. Note that all reads are considered to happen before all writes.

Link copied to clipboard
var writesHiddenVariablesMask: Int = 0

The bitwise-or of the masks of HiddenVariables that are overwritten by L2Instructions using this operation. Note that all reads are considered to happen before all writes.