Skip to content

Commit

Permalink
Respect expected type as upper bound when merging blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
errikos committed Aug 19, 2020
1 parent 98c7082 commit 237e427
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,12 @@ final class MergeProcessor(insts: Array[Inst],
case (s, v) =>
s.materialize(v)
}
val name = mergeFresh()
val paramty = Sub.lub(materialized.map(_.ty))
val name = mergeFresh()
val bound = params.headOption match {
case Some(local) => local.ty
case None => Type.Ref(Global.Top("java.lang.Object"))
}
val paramty = Sub.lub(materialized.map(_.ty), bound)
val param = Val.Local(name, paramty)
mergePhis += MergePhi(param, names.zip(materialized))
param
Expand Down Expand Up @@ -398,14 +402,15 @@ final class MergeProcessor(insts: Array[Inst],
// If the discovered blocks contain more than one,
// we must merge them together using a synthetic block.
if (inline && retMergeBlocks.size > 1) {
val retTy = Sub.lub(retMergeBlocks.map { block =>
val tys = retMergeBlocks.map { block =>
val Inst.Ret(v) = block.cf
implicit val state = block.end
v match {
case InstanceRef(ty) => ty
case _ => v.ty
}
})
}
val retTy = Sub.lub(tys, Type.Ref(Global.Top("java.lang.Object")))

// Create synthetic label and block where all returning blocks
// are going tojump to. Synthetics names must be fresh relative
Expand Down
2 changes: 1 addition & 1 deletion tools/src/main/scala/scala/scalanative/interflow/Opt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ trait Opt { self: Interflow =>
val retty = rets match {
case Seq() => Type.Nothing
case Seq(ty) => ty
case tys => Sub.lub(tys)
case tys => Sub.lub(tys, Type.Ref(Global.Top("java.lang.Object")))
}

// Interflow usually infers better types on our erased type system
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ trait PolyInline { self: Interflow =>
emit.jump(Next.Label(mergeLabel, Seq(res)))
}

val result = Val.Local(fresh(), Sub.lub(rettys))
val result = Val.Local(
fresh(),
Sub.lub(rettys, Type.Ref(Global.Top("java.lang.Object"))))
emit.label(mergeLabel, Seq(result))

result
Expand Down
17 changes: 10 additions & 7 deletions tools/src/main/scala/scala/scalanative/linker/Sub.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,17 @@ object Sub {
}
}

def lub(tys: Seq[Type])(implicit linked: linker.Result): Type = {
def lub(tys: Seq[Type], bound: Type)(implicit linked: linker.Result): Type = {
tys match {
case Seq() =>
unreachable
case head +: tail =>
tail.foldLeft[Type](head)(lub)
tail.foldLeft[Type](head)(lub(_, _, bound))
}
}

def lub(lty: Type, rty: Type)(implicit linked: linker.Result): Type = {
def lub(lty: Type, rty: Type, bound: Type)(
implicit linked: linker.Result): Type = {
(lty, rty) match {
case _ if lty == rty =>
lty
Expand All @@ -89,19 +90,20 @@ object Sub {
case (lty: Type.RefKind, rty: Type.RefKind) =>
val ScopeRef(linfo) = lty
val ScopeRef(rinfo) = rty
val lubinfo = lub(linfo, rinfo)
val ScopeRef(binfo) = bound
val lubinfo = lub(linfo, rinfo, binfo)
val exact =
lubinfo.name == rinfo.name && rty.isExact &&
lubinfo.name == linfo.name && lty.isExact
val nullable =
lty.isNullable || rty.isNullable
Type.Ref(lub(linfo, rinfo).name, exact, nullable)
Type.Ref(lubinfo.name, exact, nullable)
case _ =>
util.unsupported(s"lub(${lty.show}, ${rty.show})")
}
}

def lub(linfo: ScopeInfo, rinfo: ScopeInfo)(
def lub(linfo: ScopeInfo, rinfo: ScopeInfo, boundInfo: ScopeInfo)(
implicit linked: linker.Result): ScopeInfo = {
if (linfo == rinfo) {
linfo
Expand All @@ -110,7 +112,8 @@ object Sub {
} else if (rinfo.is(linfo)) {
linfo
} else {
val candidates = linfo.linearized.filter(i => rinfo.is(i))
val candidates =
linfo.linearized.filter(i => rinfo.is(i) && i.is(boundInfo))

candidates match {
case Seq() =>
Expand Down

0 comments on commit 237e427

Please sign in to comment.