summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-11-08 18:13:08 +0000
committerPaul Phillips <paulp@improving.org>2010-11-08 18:13:08 +0000
commit942bf86c7bb28c7d9aeae82204ae060ae330d9b6 (patch)
treeb88f130c5294617439949d77858b3e4538eb223f /src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
parent8009f723b905509e9dfa22d8746787ebb0cd11a2 (diff)
downloadscala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.tar.gz
scala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.tar.bz2
scala-942bf86c7bb28c7d9aeae82204ae060ae330d9b6.zip
This is work on -Ycheck:icode.
distribution can now be built with that option, with or without optimization, and almost all tests cases can. (Those which can't are due to different -Ycheck: issues.) Major changes of interest are as follows: * LOAD_EXCEPTION and THROW are parameterized on the throwable symbol. * Does not squash all traits down to AnyRef, but instead deals with issues as they arise. By observation the cases where one needs a "Foo with Product" to manifest as both a "Foo" and a "Product" at different places are quite rare, so we need not throw out the whole baby. * Exception handlers now have positions. * The remaining checker failures removed, such as CALL_METHOD wanting to pop a value off the stack after calling a constructor. * Many multiply defined values such as REFERENCE(ObjectClass) put in one place (ICodes.scala) and reused. * -Ycheck:icode output (if also given -Ydebug) worthy of Michelangelo. Here is a class and the -Ycheck:icode -Ydebug output for f's block. class A { def f(x: Int, y: String) = try println(x + y.length) catch { case x: NullPointerException => () } } ** Checking Block 4 [S: 3, 2] [P: 1] <closed> 1-> REF(singleton class Predef) 3 + LOAD_MODULE object Predef 2-> INT 3 + LOAD_LOCAL(value x) 3-> REF(class String) 3 + LOAD_LOCAL(value y) 2<- REF(class String) 3 - CALL_METHOD java.lang.String.length (dynamic) 3-> INT 3 + CALL_METHOD java.lang.String.length (dynamic) 2<- INT 3 - CALL_PRIMITIVE(Arithmetic(ADD,INT)) 1<- INT 3 - """ 2-> INT 3 + CALL_PRIMITIVE(Arithmetic(ADD,INT)) 1<- INT 3 - BOX INT 2-> REF(class Integer) 3 + BOX INT 1<- REF(class Integer) 3 - CALL_METHOD scala.Predef.println (dynamic) 0<- REF(singleton class Predef) 3 - CALL_METHOD scala.Predef.println (dynamic) Review by dragos (I marked the specific spots I thought of interest with "PP to ID" which makes it sound like I'm talking to my primal self. Next week on programmer theater: "PP to SUPEREGO.")
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala50
1 files changed, 30 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index c09851fa86..45d1916ca9 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -256,7 +256,7 @@ trait BasicBlocks {
* put into ignore mode so we hear about it if there's a problem.
*/
instr match {
- case JUMP(_) | RETURN(_) | THROW() | SCOPE_EXIT(_) => // ok
+ case JUMP(_) | RETURN(_) | THROW(_) | SCOPE_EXIT(_) => // ok
case STORE_LOCAL(local) if isExceptionResultName(local.sym.name) => // ok
case x => log("Ignoring instruction, possibly at our peril, at " + pos + ": " + x)
}
@@ -373,7 +373,7 @@ trait BasicBlocks {
case CZJUMP(succ, fail, _, _) => fail :: succ :: Nil
case SWITCH(_, labels) => labels
case RETURN(_) => Nil
- case THROW() => Nil
+ case THROW(_) => Nil
case _ =>
if (closed) {
dump
@@ -422,40 +422,50 @@ trait BasicBlocks {
private def succString = if (successors.isEmpty) "[S: N/A]" else successors.distinct.mkString("[S: ", ", ", "]")
private def predString = if (predecessors.isEmpty) "[P: N/A]" else predecessors.distinct.mkString("[P: ", ", ", "]")
- def fullString: String = List("Block", label, succString, predString) mkString " "
override def toString(): String = "" + label
- def flagsString: String =
- ("block " + label + (
- if (hasFlag(LOOP_HEADER)) " <loopheader> "
- else if (hasFlag(IGNORING)) " <ignore> "
- else if (hasFlag(EX_HEADER)) " <exheader> "
- else if (hasFlag(CLOSED)) " <closed> "
- else if (hasFlag(DIRTYSUCCS)) " <dirtysuccs> "
- else if (hasFlag(DIRTYPREDS)) " <dirtypreds> "
- else ""
- ))
- }
+ def blockContents = {
+ def posStr(p: Position) = if (p.isDefined) p.line.toString else "<??>"
+ val xs = this.toList map (instr => posStr(instr.pos) + "\t" + instr)
+ xs.mkString(fullString + " {\n ", "\n ", "\n}")
+ }
+ def predContents = predecessors.map(_.blockContents).mkString(predecessors.size + " preds:\n", "\n", "\n")
+ def succContents = successors.map(_.blockContents).mkString(successors.size + " succs:\n", "\n", "\n")
+ def fullString: String = List("Block", label, succString, predString, flagsString) mkString " "
+ def flagsString: String = BBFlags.flagsToString(flags)
+ }
}
object BBFlags {
+ val flagMap = Map[Int, String](
+ LOOP_HEADER -> "loopheader",
+ IGNORING -> "ignore",
+ EX_HEADER -> "exheader",
+ CLOSED -> "closed",
+ DIRTYSUCCS -> "dirtysuccs",
+ DIRTYPREDS -> "dirtypreds"
+ )
+ def flagsToString(flags: Int) = {
+ flagMap collect { case (bit, name) if (bit & flags) != 0 => "<" + name + ">" } mkString " "
+ }
+
/** This block is a loop header (was translated from a while). */
- final val LOOP_HEADER = 0x00000001
+ final val LOOP_HEADER = (1 << 0)
/** Ignoring mode: emit instructions are dropped. */
- final val IGNORING = 0x00000002
+ final val IGNORING = (1 << 1)
/** This block is the header of an exception handler. */
- final val EX_HEADER = 0x00000004
+ final val EX_HEADER = (1 << 2)
/** This block is closed. No new instructions can be added. */
- final val CLOSED = 0x00000008
+ final val CLOSED = (1 << 3)
/** Code has been changed, recompute successors. */
- final val DIRTYSUCCS = 0x00000010
+ final val DIRTYSUCCS = (1 << 4)
/** Code has been changed, recompute predecessors. */
- final val DIRTYPREDS = 0x00000020
+ final val DIRTYPREDS = (1 << 5)
}