Skip to content

Commit

Permalink
Merge pull request #336 from scala-native/topic/implicit-basic-blocks
Browse files Browse the repository at this point in the history
Implicit basic blocks
  • Loading branch information
densh committed Oct 19, 2016
2 parents 17b1afe + b0eab4e commit da891ce
Show file tree
Hide file tree
Showing 41 changed files with 1,108 additions and 1,150 deletions.
2 changes: 1 addition & 1 deletion javalib/src/main/scala/java/lang/reflect/Array.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package java.lang.reflect

import scalanative.runtime._
import scalanative.runtime.{Array => _, _}
import java.lang._Class

object Array {
Expand Down
7 changes: 0 additions & 7 deletions nir/src/main/scala/scala/scalanative/nir/Block.scala

This file was deleted.

2 changes: 1 addition & 1 deletion nir/src/main/scala/scala/scalanative/nir/Defns.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object Defn {
final case class Define(attrs: Attrs,
name: Global,
ty: Type,
blocks: Seq[Block])
insts: Seq[Inst])
extends Defn
final case class Struct(attrs: Attrs, name: Global, tys: Seq[Type])
extends Defn
Expand Down
207 changes: 77 additions & 130 deletions nir/src/main/scala/scala/scalanative/nir/Focus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,149 +5,83 @@ import scala.collection.mutable
import Shows._
import util.sh

final case class Focus(
val blocks: Seq[Block],
val name: Local,
val params: Seq[Val.Local],
val insts: Seq[Inst],
val value: Val,
val isComplete: Boolean
)(implicit _fresh: Fresh) {
def fresh = _fresh

def appendBlocks(blocks: Seq[Block]) =
copy(blocks = this.blocks ++ blocks)

def prependBlocks(blocks: Seq[Block]) =
copy(blocks = blocks ++ this.blocks)

private def assertMergeable(): Unit =
if (!isComplete) ()
else throw Focus.NotMergeable(this)

def withValue(newvalue: Val): Focus = {
assertMergeable()
copy(value = newvalue)
}
final class Focus private (
private val _labeled: Boolean = false,
private val _insts: Seq[Inst] = Seq(),
private val _value: Val = Val.Unit)(implicit fresh: Fresh) {
private def copy(_labeled: Boolean = this._labeled,
_insts: Seq[Inst] = this._insts,
_value: Val = this._value) =
new Focus(_labeled, _insts, _value)

def value: Val = _value

def finish(end: Inst.Cf): Seq[Inst] =
withInst(end)._insts

def withValue(v: Val): Focus =
copy(_value = v)

def withOp(op: Op): Focus = {
assertMergeable()
val name = fresh()
copy(insts = insts :+ Inst(name, op), value = Val.Local(name, op.resty))
withInst(Inst.Let(name, op)).withValue(Val.Local(name, op.resty))
}

def finish(cf: Cf): Focus =
if (isComplete) this
else Focus.complete(blocks :+ Block(name, params, insts, cf))

private def wrapBranch(merge: Local,
f: Focus => Focus,
params: Seq[Val.Local] = Seq()) = {
val entry = Focus.entry(params)
val end = f(entry)
val finalized =
if (end.isComplete) end
else end.finish(Cf.Jump(Next.Label(merge, Seq(end.value))))
(entry.name, end.isComplete, finalized.blocks)
}
def withRet(value: Val): Focus =
withInst(Inst.Ret(value))

def branchIf(cond: Val,
retty: Type,
thenf: Focus => Focus,
elsef: Focus => Focus): Focus = {
val merge = fresh()
val param = Val.Local(fresh(), retty)
val (thenname, thencompl, thenblocks) = wrapBranch(merge, thenf)
val (elsename, elsecompl, elseblocks) = wrapBranch(merge, elsef)
val blocks =
finish(
Cf.If(cond,
Next.Label(thenname, Seq()),
Next.Label(elsename, Seq()))).blocks
if (thencompl && elsecompl)
Focus.complete(blocks ++ thenblocks ++ elseblocks)
else
Focus(blocks ++ thenblocks ++ elseblocks,
merge,
Seq(param),
Seq(),
param,
isComplete = false)
}
def withThrow(value: Val): Focus =
withInst(Inst.Throw(value))

def branchSwitch(scrut: Val,
retty: Type,
defaultf: Focus => Focus,
casevals: Seq[Val],
casefs: Seq[Focus => Focus]): Focus = {
val merge = fresh()
val param = Val.Local(fresh(), retty)
val (defaultname, defaultcompl, defaultblocks) =
wrapBranch(merge, defaultf)
val cases = casefs.map(wrapBranch(merge, _))
val casenames = cases.map(_._1)
val casecompl = cases.map(_._2)
val caseblockss = cases.map(_._3)
val blocks = finish(
Cf.Switch(scrut,
Next.Label(defaultname, Seq()),
casevals.zip(casenames).map {
case (v, n) => Next.Case(v, n)
})).blocks
Focus(blocks ++ defaultblocks ++ caseblockss.flatten,
merge,
Seq(param),
Seq(),
param,
isComplete = false)
}
def withJump(to: Local, values: Val*): Focus =
withInst(Inst.Jump(Next.Label(to, values)))

def withIf(cond: Val, thenp: Next, elsep: Next): Focus =
withInst(Inst.If(cond, thenp, elsep))

def branchTry(retty: Type,
normal: Focus => Focus,
exc: (Val, Focus) => Focus): Focus = {
val merge = fresh()
val excparam = Val.Local(fresh(), Rt.Object)
val param = Val.Local(fresh(), retty)

val (normname, normcompl, normblocks) = wrapBranch(merge, normal)
val (excname, exccompl, excblocks) =
wrapBranch(merge, exc(excparam, _), Seq(excparam))
val blocks = finish(Cf.Try(Next.Succ(normname), Next.Fail(excname))).blocks

if (normcompl && exccompl)
Focus.complete(blocks ++ normblocks ++ excblocks)
else
Focus(blocks ++ normblocks ++ excblocks,
merge,
Seq(param),
Seq(),
param,
isComplete = false)
def withLabel(name: Local, params: Val.Local*): Focus =
withInst(Inst.Label(name, params))

def withSwitch(scrut: Val,
default: Local,
casevals: Seq[Val],
casetos: Seq[Local]): Focus = {
val cases = casevals.zip(casetos).map {
case (v, to) =>
Next.Case(v, to)
}
withInst(Inst.Switch(scrut, Next(default), cases))
}

def branchBlock(name: Local,
params: Seq[Val.Local],
values: Seq[Val]): Focus = {
val blocks = finish(Cf.Jump(Next.Label(name, values))).blocks
Focus.entry(name, params).prependBlocks(blocks)
def withTry(succ: Local, fail: Local) =
withInst(Inst.Try(Next.Succ(succ), Next.Fail(fail)))

def withInst(inst: Inst): Focus = inst match {
case _: Inst.Label =>
if (_labeled) {
copy(_labeled = true, _insts = _insts :+ Inst.Unreachable :+ inst)
} else {
copy(_labeled = true, _insts = _insts :+ inst)
}
case _: Inst.Cf =>
if (_labeled) {
copy(_labeled = false, _insts = _insts :+ inst)
} else {
val label = Inst.Label(fresh(), Seq())
copy(_labeled = false, _insts = _insts :+ label :+ inst)
}
case _ =>
if (_labeled) {
copy(_labeled = true, _insts = _insts :+ inst)
} else {
val label = Inst.Label(fresh(), Seq())
copy(_labeled = true, _insts = _insts :+ label :+ inst)
}
}
}
object Focus {
final case class NotMergeable(focus: Focus) extends Exception
private val empty = Local("", -1)

def entry(implicit fresh: Fresh): Focus =
entry(fresh(), Seq())

def entry(params: Seq[Val.Local])(implicit fresh: Fresh): Focus =
entry(fresh(), params)

def entry(name: Local, params: Seq[Val.Local])(
implicit fresh: Fresh): Focus =
Focus(Seq(), name, params, Seq(), Val.Unit, isComplete = false)

def complete(blocks: Seq[Block])(implicit fresh: Fresh) =
Focus(blocks, empty, Seq(), Seq(), Val.Unit, isComplete = true)
object Focus {
def start()(implicit fresh: Fresh) = new Focus()

def sequenced[T](elems: Seq[T], focus: Focus)(
f: (T, Focus) => Focus): Seq[Focus] = {
Expand All @@ -159,4 +93,17 @@ object Focus {
}
focs.toSeq
}

def merged(ty: nir.Type, focus: Focus, branches: Seq[Focus => Focus])(
implicit fresh: Fresh): Focus = {
val mergen = fresh()
var lastfocus = focus
branches.foreach { branch =>
lastfocus = branch(lastfocus)
lastfocus = lastfocus.withJump(mergen, lastfocus.value)
}

val mergev = Val.Local(fresh(), ty)
lastfocus.withLabel(mergen, mergev).withValue(mergev)
}
}
7 changes: 0 additions & 7 deletions nir/src/main/scala/scala/scalanative/nir/Inst.scala

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
package scala.scalanative
package nir

sealed abstract class Cf
object Cf {
// low-level control
sealed abstract class Inst
object Inst {
sealed abstract class Cf extends Inst

// empty instruction
final case object None extends Inst

// basic block label
final case class Label(name: Local, params: Seq[Val.Local]) extends Inst

// single static assignment
final case class Let(name: Local, op: Op) extends Inst
object Let {
def apply(op: Op)(implicit fresh: Fresh): Let = Let(fresh(), op)
}

// low-level control-flow
final case object Unreachable extends Cf
final case class Ret(value: Val) extends Cf
final case class Jump(next: Next) extends Cf
Expand All @@ -17,7 +31,7 @@ object Cf {
fail: Next)
extends Cf

// high-level control
// high-level control-flow
final case class Throw(value: Val) extends Cf
final case class Try(succ: Next, fail: Next) extends Cf
}

0 comments on commit da891ce

Please sign in to comment.