Class AbstractControlFlowAsmGenerator

java.lang.Object
org.ek9lang.compiler.backend.jvm.AbstractAsmGenerator
org.ek9lang.compiler.backend.jvm.AbstractControlFlowAsmGenerator
Direct Known Subclasses:
GuardedAssignmentAsmGenerator, LogicalOperationAsmGenerator, QuestionOperatorAsmGenerator

abstract class AbstractControlFlowAsmGenerator extends AbstractAsmGenerator
Abstract base class for control flow bytecode generators. Provides common patterns for: - Label creation with consistent naming - Condition evaluation processing - Result variable copying - Stack frame validation helpers

All control flow generators (question operator, if/else, switch, loops, try/catch) extend this class to reuse common logic and ensure consistent stack frame handling.

Stack Frame Invariant: All helper methods maintain the invariant that the JVM operand stack is empty before and after their execution. Results are always stored in local variables, never left on the stack. This ensures correct stack frame balancing at control flow merge points.

  • Constructor Details

    • AbstractControlFlowAsmGenerator

      protected AbstractControlFlowAsmGenerator(ConstructTargetTuple constructTargetTuple, OutputVisitor outputVisitor, org.objectweb.asm.ClassWriter classWriter)
  • Method Details

    • createControlFlowLabel

      protected org.objectweb.asm.Label createControlFlowLabel(String prefix, String uniqueId)
      Generate unique label for control flow construct. Pattern: prefix_uniqueId
      Parameters:
      prefix - Label prefix identifying the construct type (e.g., "qop", "if", "switch")
      uniqueId - Unique identifier from IR (e.g., result variable name, scope ID)
      Returns:
      JVM Label for bytecode generation
    • processConditionEvaluation

      protected void processConditionEvaluation(List<IRInstr> conditionEvaluation)
      Process condition evaluation instructions via recursive visiting. All instructions leave stack empty (results stored in variables).

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty (all results in local variables)

      Parameters:
      conditionEvaluation - List of IR instructions to evaluate condition
    • processBodyEvaluation

      protected void processBodyEvaluation(List<IRInstr> bodyEvaluation)
      Process body evaluation instructions via recursive visiting. All instructions leave stack empty (results stored in variables).

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty (all results in local variables)

      Parameters:
      bodyEvaluation - List of IR instructions for case/branch body
    • branchIfFalse

      protected void branchIfFalse(String primitiveCondition, org.objectweb.asm.Label falseLabel)
      Load primitive condition (int) and branch if false (0).

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty (IFEQ consumes the int)

      Control Flow: If condition is 0 (false), jumps to falseLabel. Otherwise, execution continues to next instruction.

      Parameters:
      primitiveCondition - Variable name holding primitive int (0 or 1)
      falseLabel - Label to jump to if condition is false (0)
    • branchIfTrue

      protected void branchIfTrue(String primitiveCondition, org.objectweb.asm.Label trueLabel)
      Load primitive condition (int) and branch if true (non-zero).

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty (IFNE consumes the int)

      Control Flow: If condition is non-zero (true), jumps to trueLabel. Otherwise, execution continues to next instruction.

      Used by logical OR operator for short-circuit optimization: If left operand is true, skip right evaluation and return left.

      Parameters:
      primitiveCondition - Variable name holding primitive int (0 or 1)
      trueLabel - Label to jump to if condition is true (non-zero)
    • copyResultVariable

      protected void copyResultVariable(String sourceVar, String destVar)
      Copy result from source variable to destination variable (object reference).

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty

      Bytecode: ALOAD source_index, ASTORE dest_index

      Parameters:
      sourceVar - Variable holding the result to copy
      destVar - Variable to store the result into
    • jumpTo

      protected void jumpTo(org.objectweb.asm.Label label)
      Generate unconditional jump to label.

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: control transferred (stack irrelevant after GOTO)

      Control Flow: Execution continues at the target label. Stack at target must match stack at GOTO (empty in our convention).

      Parameters:
      label - Target label for unconditional jump
    • placeLabel

      protected void placeLabel(org.objectweb.asm.Label label)
      Place label at current bytecode position.

      Stack Frame Invariant: Pre-condition: stack state depends on incoming control flow paths Post-condition: stack state unchanged (label is just a position marker)

      CRITICAL: All control flow paths reaching this label MUST have the same stack depth. In our convention, all paths arrive with empty stack.

      Parameters:
      label - Label to place at current position
    • processConditionCase

      protected void processConditionCase(ConditionCaseDetails conditionCase, org.objectweb.asm.Label nextCaseLabel, org.objectweb.asm.Label endLabel, String resultVar)
      Process a condition case: evaluate condition, branch, execute body. Common pattern used by question operator, if/else, switch.

      Stack Frame Invariant: Pre-condition: stack is empty Post-condition: stack is empty at both nextCaseLabel and after GOTO

      Control Flow: 1. Evaluate condition → result in variable, stack empty 2. Branch to nextCaseLabel if false → stack empty at label 3. Execute body → result in variable, stack empty 4. Copy result to overall result → stack empty 5. Jump to endLabel → stack empty at label 6. Place nextCaseLabel → stack empty (from branch in step 2)

      Parameters:
      conditionCase - IR details for this case
      nextCaseLabel - Label to jump if condition is false
      endLabel - Label to jump after body execution
      resultVar - Overall result variable (null if no result)