All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalanative.interflow.MergeBlock.scala Maven / Gradle / Ivy

There is a newer version: 0.5.5
Show newest version
package scala.scalanative
package interflow

import scala.collection.mutable
import scalanative.nir._

final class MergeBlock(val label: Inst.Label, val name: Local) {
  var incoming = mutable.Map.empty[Local, (Seq[Val], State)]
  var outgoing = mutable.Map.empty[Local, MergeBlock]
  var phis: Seq[MergePhi] = _
  var start: State = _
  var end: State = _
  var cf: Inst.Cf = _
  var invalidations: Int = 0
  implicit def cfPos: Position = {
    if (cf != null) cf.pos
    else label.pos
  }

  def toInsts(): Seq[Inst] = {
    val block = this
    val result = new nir.Buffer()(Fresh(0))
    def mergeNext(next: Next.Label): Next.Label = {
      val nextBlock = outgoing(next.name)
      val mergeValues = nextBlock.phis.flatMap {
        case MergePhi(_, incoming) =>
          incoming.collect {
            case (name, value) if name == block.label.name =>
              value
          }
      }
      Next.Label(nextBlock.name, mergeValues)
    }
    def mergeUnwind(next: Next): Next = next match {
      case Next.None =>
        next
      case Next.Unwind(exc, next: Next.Label) =>
        Next.Unwind(exc, mergeNext(next))
      case _ =>
        util.unreachable
    }
    val params = block.phis.map(_.param)
    result.label(block.name, params)
    result ++= block.end.emit
    block.cf match {
      case ret: Inst.Ret =>
        result += ret
      case Inst.Jump(next: Next.Label) =>
        result.jump(mergeNext(next))
      case Inst.If(cond, thenNext: Next.Label, elseNext: Next.Label) =>
        result.branch(cond, mergeNext(thenNext), mergeNext(elseNext))
      case Inst.Switch(scrut, defaultNext: Next.Label, cases) =>
        val mergeCases = cases.map {
          case Next.Case(v, next: Next.Label) =>
            Next.Case(v, mergeNext(next))
          case _ =>
            util.unreachable
        }
        result.switch(scrut, mergeNext(defaultNext), mergeCases)
      case Inst.Throw(v, unwind) =>
        result.raise(v, mergeUnwind(unwind))
      case Inst.Unreachable(unwind) =>
        result.unreachable(mergeUnwind(unwind))
      case unknown =>
        throw BailOut(s"MergeUnwind unknown Inst: ${unknown.show}")
    }
    result.toSeq
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy