summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/icode/ICodes.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/ICodes.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/ICodes.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala47
1 files changed, 23 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index 65b558b230..dc31edc569 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -14,9 +14,9 @@ package icode
import java.io.PrintWriter
-import scala.collection.mutable.HashMap
+import scala.collection.{ mutable, immutable, generic }
import scala.tools.nsc.symtab._
-import analysis.{Liveness, ReachingDefinitions}
+import analysis.{ Liveness, ReachingDefinitions }
import scala.tools.nsc.symtab.classfile.ICodeReader
/** Glue together ICode parts.
@@ -36,26 +36,23 @@ abstract class ICodes extends AnyRef
with Repository
{
val global: Global
+ import global.{ definitions, settings }
/** The ICode representation of classes */
- var classes: HashMap[global.Symbol, IClass] = new HashMap()
+ val classes = new mutable.HashMap[global.Symbol, IClass]
/** Debugging flag */
- var isCheckerDebug: Boolean = global.settings.checkDebug.value
- def checkerDebug(msg: String) = if (isCheckerDebug) println(msg)
+ def shouldCheckIcode = settings.check contains global.genicode.phaseName
+ def checkerDebug(msg: String) = if (shouldCheckIcode && global.opt.debug) println(msg)
/** The ICode linearizer. */
- val linearizer: Linearizer =
- if (global.settings.Xlinearizer.value == "rpo")
- new ReversePostOrderLinearizer()
- else if (global.settings.Xlinearizer.value == "dfs")
- new DepthFirstLinerizer()
- else if (global.settings.Xlinearizer.value == "normal")
- new NormalLinearizer();
- else if (global.settings.Xlinearizer.value == "dump")
- new DumpLinearizer()
- else
- global.abort("Unknown linearizer: " + global.settings.Xlinearizer.value)
+ val linearizer: Linearizer = settings.Xlinearizer.value match {
+ case "rpo" => new ReversePostOrderLinearizer()
+ case "dfs" => new DepthFirstLinerizer()
+ case "normal" => new NormalLinearizer()
+ case "dump" => new DumpLinearizer()
+ case x => global.abort("Unknown linearizer: " + x)
+ }
/** Have to be careful because dump calls around, possibly
* re-entering methods which initiated the dump (like foreach
@@ -79,7 +76,7 @@ abstract class ICodes extends AnyRef
for (b <- m.code.blocks)
if (!b.closed) {
m.dump
- global.abort("Open block: " + b.flagsString)
+ global.abort("Open block: " + b + " " + b.flagsString)
}
}
@@ -91,9 +88,13 @@ abstract class ICodes extends AnyRef
val global: ICodes.this.global.type = ICodes.this.global
}
- lazy val ObjectReference: TypeKind = REFERENCE(global.definitions.ObjectClass)
- lazy val ThrowableReference: TypeKind = REFERENCE(global.definitions.ThrowableClass)
- lazy val AnyRefReference: TypeKind = REFERENCE(global.definitions.AnyRefClass)
+ lazy val AnyRefReference: TypeKind = REFERENCE(definitions.AnyRefClass)
+ lazy val BoxedUnitReference: TypeKind = REFERENCE(definitions.BoxedUnitClass)
+ lazy val NothingReference: TypeKind = REFERENCE(definitions.NothingClass)
+ lazy val NullReference: TypeKind = REFERENCE(definitions.NullClass)
+ lazy val ObjectReference: TypeKind = REFERENCE(definitions.ObjectClass)
+ lazy val StringReference: TypeKind = REFERENCE(definitions.StringClass)
+ lazy val ThrowableReference: TypeKind = REFERENCE(definitions.ThrowableClass)
object icodeReader extends ICodeReader {
lazy val global: ICodes.this.global.type = ICodes.this.global
@@ -102,10 +103,8 @@ abstract class ICodes extends AnyRef
/** A phase which works on icode. */
abstract class ICodePhase(prev: Phase) extends global.GlobalPhase(prev) {
override def erasedTypes = true
-
- override def apply(unit: global.CompilationUnit) {
- unit.icode foreach { c => apply(c) }
- }
+ override def apply(unit: global.CompilationUnit): Unit =
+ unit.icode foreach apply
def apply(cls: global.icodes.IClass): Unit
}