From 525018c3cab1aaeb6644e9dacae2ab36ffa28d13 Mon Sep 17 00:00:00 2001 From: michelou Date: Mon, 4 Dec 2006 14:40:02 +0000 Subject: removed leading/trailing tabs/blanks in backend... removed leading/trailing tabs/blanks in backend/icode/*.scala --- .../tools/nsc/backend/icode/BasicBlocks.scala | 265 +++++++++++---------- .../tools/nsc/backend/icode/CheckerError.scala | 8 +- .../backend/icode/analysis/CompleteLattice.scala | 21 +- .../backend/icode/analysis/DataFlowAnalysis.scala | 60 +++-- .../nsc/backend/icode/analysis/Liveness.scala | 73 +++--- .../nsc/backend/icode/analysis/LubError.scala | 11 +- .../backend/icode/analysis/TypeFlowAnalysis.scala | 237 +++++++++--------- .../scala/tools/nsc/doc/DocGenerator.scala | 2 +- 8 files changed, 363 insertions(+), 314 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 4946ed13d8..1e1fe8f629 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -1,20 +1,20 @@ -/* NSC -- new scala compiler - * Copyright 2005 LAMP/EPFL +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */ // $Id$ -package scala.tools.nsc.backend.icode; +package scala.tools.nsc.backend.icode -import compat.StringBuilder; -import scala.tools.nsc.ast._; -import scala.collection.mutable.Map; -import scala.tools.nsc.util.Position; -import scala.tools.nsc.backend.icode.analysis.ProgramPoint; +import compat.StringBuilder +import scala.tools.nsc.ast._ +import scala.collection.mutable.Map +import scala.tools.nsc.util.Position +import scala.tools.nsc.backend.icode.analysis.ProgramPoint trait BasicBlocks requires ICodes { - import opcodes._; + import opcodes._ /** This class represents a basic block. Each * basic block contains a list of instructions that are @@ -26,37 +26,37 @@ trait BasicBlocks requires ICodes { with ProgramPoint[BasicBlock] { /** The label of the block */ - val label = theLabel; + val label = theLabel - /** When set, the 'emit' methods will be ignored. */ - var ignore: Boolean = false; + /** When set, the emit methods will be ignored. */ + var ignore: Boolean = false - var preds: List[BasicBlock] = null; + var preds: List[BasicBlock] = null /** Is this block the head of a while? */ - var loopHeader = false; + var loopHeader = false /** ICode instructions, used as temporary storage while emitting code. * Once closed is called, only the `instrs' array should be used. */ - private var instructionList: List[Instruction] = Nil; + private var instructionList: List[Instruction] = Nil - private var _lastInstruction: Instruction = null; + private var _lastInstruction: Instruction = null - private var closed: boolean = false; + private var closed: boolean = false - private var instrs: Array[Instruction] = _; - private var touched = false; + private var instrs: Array[Instruction] = _ + private var touched = false def toList: List[Instruction] = { if (closed && touched) - instructionList = List.fromArray(instrs); + instructionList = List.fromArray(instrs) instructionList } def fromList(is: List[Instruction]): Unit = { - instrs = toInstructionArray(is); - closed = true; + instrs = toInstructionArray(is) + closed = true } // public: @@ -66,7 +66,7 @@ trait BasicBlocks requires ICodes { */ def indexOf(inst: Instruction): Int = { assert(closed) - var i = 0; + var i = 0 while (i < instrs.length) { if (instrs(i) eq inst) return i i = i + 1 @@ -80,14 +80,14 @@ trait BasicBlocks requires ICodes { /** Apply a function to all the instructions of the block. */ def traverse(f: Instruction => unit) = { if (!closed) { - dump; - global.abort("Traversing an open block!: " + label); + dump + global.abort("Traversing an open block!: " + label) } - instrs foreach f; + instrs foreach f } def traverseBackwards(f: Instruction => Unit) = { - var i = instrs.length - 1; + var i = instrs.length - 1 while (i >= 0) { f(instrs(i)); i = i - 1 @@ -97,19 +97,19 @@ trait BasicBlocks requires ICodes { /** The number of instructions in this basic block so far. */ def size: Int = if (isClosed) - instrs.length; + instrs.length else - instructionList.length; + instructionList.length /** Return the index of the instruction which produced the value * consumed by the given instruction. */ def findDef(pos: Int): Option[Int] = { - assert(closed); - var i = pos; - var d = 0; + assert(closed) + var i = pos + var d = 0 while (i > 0) { - i = i - 1; + i = i - 1 val prod = instrs(i).produced if (prod > 0 && d == 0) return Some(i) @@ -119,12 +119,11 @@ trait BasicBlocks requires ICodes { } /** Return the n-th instruction. */ - def apply(n: Int): Instruction = { + def apply(n: Int): Instruction = if (closed) instrs(n) else instructionList.reverse(n) - } ///////////////////// Substitutions /////////////////////// @@ -133,10 +132,10 @@ trait BasicBlocks requires ICodes { * they are anchored. It retains the position of the previous instruction. */ def replaceInstruction(pos: Int, instr: Instruction): Boolean = { - assert(closed, "Instructions can be replaced only after the basic block is closed"); + assert(closed, "Instructions can be replaced only after the basic block is closed") - instr.pos = instrs(pos).pos; - instrs(pos) = instr; + instr.pos = instrs(pos).pos + instrs(pos) = instr true } @@ -146,42 +145,46 @@ trait BasicBlocks requires ICodes { * It retains the position of the previous instruction. */ def replaceInstruction(oldInstr: Instruction, newInstr: Instruction): Boolean = { - assert(closed, "Instructions can be replaced only after the basic block is closed"); + assert(closed, "Instructions can be replaced only after the basic block is closed") - var i = 0; - var changed = false; + var i = 0 + var changed = false while (i < instrs.length && !changed) { if (instrs(i) == oldInstr) { - newInstr.pos = oldInstr.pos; - instrs(i) = newInstr; - changed = true; + newInstr.pos = oldInstr.pos + instrs(i) = newInstr + changed = true } - i = i + 1; + i = i + 1 } changed } - /** Replaces iold with 'is'. It does not update the position field in the newly - * inserted instrucitons, so it behaves differently than the one-instruction - * versions of this function. + /** Replaces iold with is. It does not update + * the position field in the newly inserted instrucitons, so it behaves + * differently than the one-instruction versions of this function. + * + * @param iold .. + * @param is .. + * @return .. */ def replaceInstruction(iold: Instruction, is: List[Instruction]): Boolean = { - assert(closed, "Instructions can be replaced only after the basic block is closed"); + assert(closed, "Instructions can be replaced only after the basic block is closed") - var i = 0; - var changed = false; + var i = 0 + var changed = false while (i < instrs.length && (instrs(i) ne iold)) i = i + 1; if (i < instrs.length) { val newInstrs = new Array[Instruction](instrs.length + is.length - 1); - changed = true; - Array.copy(instrs, 0, newInstrs, 0, i); - var j = i; + changed = true + Array.copy(instrs, 0, newInstrs, 0, i) + var j = i for (val x <- is) { - newInstrs(j) = x; - j = j + 1; + newInstrs(j) = x + j = j + 1 } if (i + 1 < instrs.length) Array.copy(instrs, i + 1, newInstrs, j, instrs.length - i - 1) @@ -191,33 +194,39 @@ trait BasicBlocks requires ICodes { changed } - /** Remove instructions found at the given positions. */ + /** Removes instructions found at the given positions. + * + * @param positions ... + */ def removeInstructionsAt(positions: Int*): Unit = { - assert(closed); - val removed = positions.toList; - val newInstrs = new Array[Instruction](instrs.length - positions.length); - var i = 0; - var j = 0; + assert(closed) + val removed = positions.toList + val newInstrs = new Array[Instruction](instrs.length - positions.length) + var i = 0 + var j = 0 while (i < instrs.length) { if (!removed.contains(i)) { - newInstrs(j) = instrs(i); - j = j + 1; + newInstrs(j) = instrs(i) + j = j + 1 } - i = i + 1; + i = i + 1 } - instrs = newInstrs; + instrs = newInstrs } - /** Replace all instructions found in the map. */ - def subst(map: Map[Instruction, Instruction]) = + /** Replaces all instructions found in the map. + * + * @param map ... + */ + def subst(map: Map[Instruction, Instruction]): Unit = if (!closed) substOnList(map) else { - var i = 0; + var i = 0 while (i < instrs.length) { map get instrs(i) match { - case Some(instr) => touched = replaceInstruction(i, instr); - case None => (); + case Some(instr) => touched = replaceInstruction(i, instr) + case None => () } - i = i + 1; + i = i + 1 } } @@ -226,12 +235,12 @@ trait BasicBlocks requires ICodes { case Nil => Nil case x :: xs => map.get(x) match { - case Some(newInstr) => newInstr :: subst(xs); - case None => x :: subst(xs); + case Some(newInstr) => newInstr :: subst(xs) + case None => x :: subst(xs) } } - instructionList = subst(instructionList); + instructionList = subst(instructionList) } ////////////////////// Emit ////////////////////// @@ -240,59 +249,58 @@ trait BasicBlocks requires ICodes { /** Add a new instruction at the end of the block, * using the same source position as the last emitted instruction */ - def emit(instr: Instruction): Unit = { + def emit(instr: Instruction): Unit = if (!instructionList.isEmpty) - emit(instr, instructionList.head.pos); + emit(instr, instructionList.head.pos) else - emit(instr, Position.NOPOS); - } + emit(instr, Position.NOPOS) def emit(instr: Instruction, pos: Int) = { if (closed) { - print(); + print() Console.println("trying to emit: " + instr) } - assert (!closed || ignore, "BasicBlock closed"); + assert (!closed || ignore, "BasicBlock closed") if (!ignore) { - touched = true; - instr.pos = pos; - instructionList = instr :: instructionList; - _lastInstruction = instr; + touched = true + instr.pos = pos + instructionList = instr :: instructionList + _lastInstruction = instr } } /** Close the block */ def close = { assert(instructionList.length > 0, - "Empty block."); - closed = true; - instructionList = instructionList.reverse; - instrs = toInstructionArray(instructionList); + "Empty block.") + closed = true + instructionList = instructionList.reverse + instrs = toInstructionArray(instructionList) } def open = { - closed = false; - ignore = false; + closed = false + ignore = false } def clear: Unit = { - instructionList = Nil; - instrs = null; - preds = null; + instructionList = Nil + instrs = null + preds = null } - def isEmpty: Boolean = instructionList.isEmpty; + def isEmpty: Boolean = instructionList.isEmpty /** Enter ignore mode: new 'emit'ted instructions will not be - * added to this basic block. It makes the generation of THROW - * and RETURNs easier. + * added to this basic block. It makes the generation of THROW + * and RETURNs easier. */ - def enterIgnoreMode = ignore = true; + def enterIgnoreMode = ignore = true def exitIgnoreMode = { - assert(ignore, "Exit ignore mode when not in ignore mode."); - ignore = false; + assert(ignore, "Exit ignore mode when not in ignore mode.") + ignore = false } /** Return the last instruction of this basic block. */ @@ -300,40 +308,40 @@ trait BasicBlocks requires ICodes { if (closed) instrs(instrs.length - 1) else - instructionList.head; + instructionList.head def firstInstruction = if (closed) instrs(0) else - instructionList.last; + instructionList.last /** Convert the list to an array */ def toInstructionArray(l: List[Instruction]): Array[Instruction] = { - var array = new Array[Instruction](l.length); - var i: Int = 0; + var array = new Array[Instruction](l.length) + var i: Int = 0 - l foreach (x => { array(i) = x; i = i + 1 }); + l foreach (x => { array(i) = x; i = i + 1 }) array } - def isClosed = closed; + def isClosed = closed // TODO: Take care of exception handlers! def successors : List[BasicBlock] = if (isEmpty) Nil else lastInstruction match { - case JUMP (where) => List(where); - case CJUMP(success, failure, _, _) => success :: failure :: Nil; - case CZJUMP(success, failure, _, _) => success :: failure :: Nil; - case SWITCH(_,labels) => labels; - case RETURN(_) => Nil; - case THROW() => Nil; + case JUMP (where) => List(where) + case CJUMP(success, failure, _, _) => success :: failure :: Nil + case CZJUMP(success, failure, _, _) => success :: failure :: Nil + case SWITCH(_,labels) => labels + case RETURN(_) => Nil + case THROW() => Nil case _ => if (isClosed) { - dump; - global.abort("The last instruction is not a control flow instruction: " + lastInstruction); + dump + global.abort("The last instruction is not a control flow instruction: " + lastInstruction) } - else Nil; + else Nil } /** Returns the precessors of this block, in the current 'code' chunk. @@ -341,36 +349,35 @@ trait BasicBlocks requires ICodes { * in different code 'chunks' than the rest of the method. */ def predecessors: List[BasicBlock] = { - preds = code.blocks.elements.filter (.successors.contains(this)).toList; + preds = code.blocks.elements.filter (.successors.contains(this)).toList preds } - override def equals(other: Any): Boolean = ( + override def equals(other: Any): Boolean = other.isInstanceOf[BasicBlock] && other.asInstanceOf[BasicBlock].label == label && other.asInstanceOf[BasicBlock].code == code - ); // Instead of it, rather use a printer - def print() : unit = print(java.lang.System.out); + def print() : unit = print(java.lang.System.out) def print(out: java.io.PrintStream) : unit = { - out.println("block #"+label+" :"); - toList.foreach(i => out.println(" " + i)); - out.print("Successors: "); - successors.foreach((x: BasicBlock) => out.print(" "+x.label.toString())); - out.println(); + out.println("block #"+label+" :") + toList.foreach(i => out.println(" " + i)) + out.print("Successors: ") + successors.foreach((x: BasicBlock) => out.print(" "+x.label.toString())) + out.println() } def fullString: String = { - val buf = new StringBuilder(); - buf.append("Block ").append(label.toString()); - buf.append("\nSuccessors: ").append(successors); - buf.append("\nPredecessors: ").append(predecessors); + val buf = new StringBuilder() + buf.append("Block ").append(label.toString()) + buf.append("\nSuccessors: ").append(successors) + buf.append("\nPredecessors: ").append(predecessors) buf.toString() } - override def toString(): String = "" + label; + override def toString(): String = "" + label } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/CheckerError.scala b/src/compiler/scala/tools/nsc/backend/icode/CheckerError.scala index da1232b6e9..cf3b764dd3 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/CheckerError.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/CheckerError.scala @@ -1,11 +1,11 @@ -/* NSC -- new scala compiler - * Copyright 2005 LAMP/EPFL +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */ // $Id$ -package scala.tools.nsc.backend.icode; +package scala.tools.nsc.backend.icode -class CheckerError(s: String) extends Exception(s); +class CheckerError(s: String) extends Exception(s) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala index 36e10d6366..3e0aa892d8 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CompleteLattice.scala @@ -1,19 +1,26 @@ -package scala.tools.nsc.backend.icode.analysis; +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ + +// $Id$ + +package scala.tools.nsc.backend.icode.analysis /** A complete lattice. */ trait CompleteLattice { - type Elem; + type Elem - /** Return the least upper bound of `a' and `b' */ - def lub2(a: Elem, b: Elem): Elem; + /** Return the least upper bound of a and b */ + def lub2(a: Elem, b: Elem): Elem /** Return the top element. */ - def top: Elem; + def top: Elem /** Return the bottom element. */ - def bottom: Elem; + def bottom: Elem /** Compute the least upper bound of a list of elements. */ - def lub(xs: List[Elem]): Elem = if (xs == Nil) bottom else xs reduceLeft lub2; + def lub(xs: List[Elem]): Elem = if (xs == Nil) bottom else xs reduceLeft lub2 } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala index b8d4a1e92c..8ab7007967 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala @@ -1,40 +1,49 @@ -package scala.tools.nsc.backend.icode.analysis; +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ + +// $Id$ -import scala.collection.mutable.{Map, HashMap, Set, HashSet}; +package scala.tools.nsc.backend.icode.analysis + +import scala.collection.mutable.{Map, HashMap, Set, HashSet} /** A generic framework for data flow analysis. */ trait DataFlowAnalysis[L <: CompleteLattice] { /** A type for program points. */ - type P <: ProgramPoint[P]; - val lattice: L; + type P <: ProgramPoint[P] + val lattice: L - val worklist: Set[P] = new HashSet; + val worklist: Set[P] = new HashSet - val in: Map[P, lattice.Elem] = new HashMap; - val out: Map[P, lattice.Elem] = new HashMap; - val visited: HashSet[P] = new HashSet; + val in: Map[P, lattice.Elem] = new HashMap + val out: Map[P, lattice.Elem] = new HashMap + val visited: HashSet[P] = new HashSet /* Implement this function to initialize the worklist. */ def init(f: => Unit): Unit = { in.clear; out.clear; worklist.clear; visited.clear; - f; + f } - def run: Unit; + def run: Unit - /** Implement forward dataflow analysis: the transfer function is - * applied when inputs to a Program point change, to obtain the new - * output value. + /** Implements forward dataflow analysis: the transfer function is + * applied when inputs to a Program point change, to obtain the new + * output value. + * + * @param f ... */ - def forwardAnalysis(f: (P, lattice.Elem) => lattice.Elem): Unit = { + def forwardAnalysis(f: (P, lattice.Elem) => lattice.Elem): Unit = while (!worklist.isEmpty) { val point = worklist.elements.next; worklist -= point; visited += point; - val output = f(point, in(point)); + val output = f(point, in(point)) if ((lattice.bottom == out(point)) || output != out(point)) { - out(point) = output; - val succs = point.successors; + out(point) = output + val succs = point.successors succs foreach { p => if (!worklist.contains(p)) worklist += p; @@ -42,22 +51,25 @@ trait DataFlowAnalysis[L <: CompleteLattice] { } } } - } - def backwardAnalysis(f: (P, lattice.Elem) => lattice.Elem): Unit = { + /** ... + * + * @param f ... + */ + def backwardAnalysis(f: (P, lattice.Elem) => lattice.Elem): Unit = while (!worklist.isEmpty) { - val point = worklist.elements.next; worklist -= point; + val point = worklist.elements.next; worklist -= point - out(point) = lattice.lub(point.successors map in.apply); - val input = f(point, out(point)); + out(point) = lattice.lub(point.successors map in.apply) + val input = f(point, out(point)) if ((lattice.bottom == in(point)) || input != in(point)) { - in(point) = input; + in(point) = input point.predecessors foreach { p => if (!worklist.contains(p)) worklist += p; } } } - } + } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala index a2b3d94736..abb79ef3e5 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala @@ -1,4 +1,11 @@ -package scala.tools.nsc.backend.icode.analysis; +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ + +// $Id$ + +package scala.tools.nsc.backend.icode.analysis import compat.StringBuilder import scala.collection.mutable.{HashMap, Map} @@ -8,68 +15,68 @@ import scala.collection.immutable.{Set, ListSet} * Compute liveness information for local variables. */ abstract class Liveness { - val global: Global; - import global._; - import icodes._; + val global: Global + import global._ + import icodes._ /** The lattice for this analysis. */ object livenessLattice extends CompleteLattice { - type Elem = Set[Local]; + type Elem = Set[Local] val top: Elem = new ListSet[Local]() { - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]; + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } val bottom: Elem = new ListSet[Local]() { - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]; + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] } - def lub2(a: Elem, b: Elem): Elem = a incl b; + def lub2(a: Elem, b: Elem): Elem = a incl b } final class LivenessAnalysis extends DataFlowAnalysis[livenessLattice.type] { - type P = BasicBlock; - val lattice = livenessLattice; + type P = BasicBlock + val lattice = livenessLattice - var method: IMethod = _; + var method: IMethod = _ - val gen: Map[BasicBlock, Set[Local]] = new HashMap(); - val kill:Map[BasicBlock, Set[Local]] = new HashMap(); + val gen: Map[BasicBlock, Set[Local]] = new HashMap() + val kill:Map[BasicBlock, Set[Local]] = new HashMap() def init(m: IMethod): Unit = { - this.method = m; + this.method = m for (val b <- m.code.blocks.toList; val Pair(g, k) = genAndKill(b)) { - gen += b -> g; - kill += b -> k; + gen += b -> g + kill += b -> k } init { - worklist ++= m.code.blocks.toList; + worklist ++= m.code.blocks.toList m.code.blocks.foreach { b => - in(b) = lattice.bottom; - out(b) = lattice.bottom; + in(b) = lattice.bottom + out(b) = lattice.bottom } } } - import opcodes._; + import opcodes._ /** Return the gen and kill sets for this block. */ def genAndKill(b: BasicBlock): Pair[Set[Local], Set[Local]] = { - var genSet = new ListSet[Local]; - var killSet = new ListSet[Local]; + var genSet = new ListSet[Local] + var killSet = new ListSet[Local] for (val i <- b.toList) i match { - case LOAD_LOCAL(local) if (!killSet(local)) => genSet = genSet + local; - case STORE_LOCAL(local) => killSet = killSet + local; - case _ => (); + case LOAD_LOCAL(local) if (!killSet(local)) => genSet = genSet + local + case STORE_LOCAL(local) => killSet = killSet + local + case _ => () } Pair(genSet, killSet) } override def run: Unit = { - backwardAnalysis(blockTransfer); + backwardAnalysis(blockTransfer) if (settings.debug.value) { linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) assert(in(b) != lattice.bottom, @@ -82,17 +89,17 @@ abstract class Liveness { /** Abstract interpretation for one instruction. */ def interpret(out: lattice.Elem, i: Instruction): lattice.Elem = { - var in = out; + var in = out if (settings.debug.value) { - log("- " + i); - log("out: " + out); - log("\n"); + log("- " + i) + log("out: " + out) + log("\n") } i match { - case LOAD_LOCAL(l) => in = in + l; - case STORE_LOCAL(l) => in = in - l; + case LOAD_LOCAL(l) => in = in + l + case STORE_LOCAL(l) => in = in - l case _ => () } @@ -100,7 +107,7 @@ abstract class Liveness { } /* def interpret */ override def toString(): String = { - val buf = new StringBuilder(); + val buf = new StringBuilder() for (val b <- method.code.blocks.toList) { buf.append("\nlive-in(" + b + ")=" + in(b) + "\nlive-out(" + b + ")=" + out(b)); } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/LubError.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/LubError.scala index 0271f8ebea..40d8be1b8a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/LubError.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/LubError.scala @@ -1,5 +1,12 @@ -package scala.tools.nsc.backend.icode.analysis; +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ + +// $Id$ + +package scala.tools.nsc.backend.icode.analysis class LubError(a: Any, b: Any, msg: String) extends Exception { - override def toString() = "Lub error: " + msg + a + b; + override def toString() = "Lub error: " + msg + a + b } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index f873ae44d7..fcb369615e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -1,39 +1,48 @@ -package scala.tools.nsc.backend.icode.analysis; +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ + +// $Id$ + +package scala.tools.nsc.backend.icode.analysis -import scala.collection.mutable.{Map, HashMap}; +import scala.collection.mutable.{Map, HashMap} /** A data-flow analysis on types, that works on ICode. + * + * @author Iulian Dragos */ abstract class TypeFlowAnalysis { - val global: Global; - import global._; + val global: Global + import global._ /** The lattice of ICode types. */ object typeLattice extends CompleteLattice { - type Elem = icodes.TypeKind; + type Elem = icodes.TypeKind - val Object = icodes.REFERENCE(global.definitions.ObjectClass); - val All = icodes.REFERENCE(global.definitions.AllClass); + val Object = icodes.REFERENCE(global.definitions.ObjectClass) + val All = icodes.REFERENCE(global.definitions.AllClass) - def top = Object; - def bottom = All; + def top = Object + def bottom = All def lub2(a: Elem, b: Elem) = if (a eq bottom) b else if (b eq bottom) a - else icodes.lub(a, b); + else icodes.lub(a, b) } /** The lattice of type stacks. It is a straight forward extension of * the type lattice (lub is pairwise lub of the list elements). */ object typeStackLattice extends CompleteLattice { - import icodes._; - type Elem = TypeStack; + import icodes._ + type Elem = TypeStack - override val top = new TypeStack; - override val bottom = new TypeStack; + override val top = new TypeStack + override val bottom = new TypeStack def lub2(s1: TypeStack, s2: TypeStack) = { if (s1 eq bottom) s2 @@ -54,7 +63,7 @@ abstract class TypeFlowAnalysis { } def this(o: VarBinding) = { - this(); + this() this ++= o } } @@ -63,30 +72,30 @@ abstract class TypeFlowAnalysis { * names to types and a type stack. */ object typeFlowLattice extends CompleteLattice { - import icodes._; + import icodes._ type Elem = Pair[VarBinding, icodes.TypeStack] override val top = new Pair(new VarBinding, typeStackLattice.top) { - override def equals(that: Any) = (this eq that.asInstanceOf[AnyRef]); + override def equals(that: Any) = (this eq that.asInstanceOf[AnyRef]) } override val bottom = new Pair(new VarBinding, typeStackLattice.bottom) { - override def equals(that: Any) = (this eq that.asInstanceOf[AnyRef]); + override def equals(that: Any) = (this eq that.asInstanceOf[AnyRef]) } def lub2(a: Elem, b: Elem) = { - val Pair(env1, s1) = a; - val Pair(env2, s2) = b; + val Pair(env1, s1) = a + val Pair(env2, s2) = b - val resultingLocals = new VarBinding; + val resultingLocals = new VarBinding for (val binding1 <- env1.elements) { - val tp2 = env2(binding1._1); - resultingLocals += binding1._1 -> typeLattice.lub2(binding1._2, tp2); + val tp2 = env2(binding1._1) + resultingLocals += binding1._1 -> typeLattice.lub2(binding1._2, tp2) } for (val binding2 <- env2.elements; resultingLocals(binding2._1) eq typeLattice.bottom) { - val tp1 = env1(binding2._1); - resultingLocals += binding2._1 -> typeLattice.lub2(binding2._2, tp1); + val tp1 = env1(binding2._1) + resultingLocals += binding2._1 -> typeLattice.lub2(binding2._2, tp1) } Pair(resultingLocals, typeStackLattice.lub2(a._2, b._2)) @@ -94,42 +103,42 @@ abstract class TypeFlowAnalysis { } class MethodTFA extends DataFlowAnalysis[typeFlowLattice.type] { - import icodes._; - import icodes.opcodes._; + import icodes._ + import icodes.opcodes._ - type P = BasicBlock; - val lattice = typeFlowLattice; + type P = BasicBlock + val lattice = typeFlowLattice - val STRING = icodes.REFERENCE(TypeFlowAnalysis.this.global.definitions.StringClass); - var method: IMethod = _; + val STRING = icodes.REFERENCE(TypeFlowAnalysis.this.global.definitions.StringClass) + var method: IMethod = _ /** Initialize the in/out maps for the analysis of the given method. */ def init(m: icodes.IMethod): Unit = { - this.method = m; + this.method = m init { - worklist += m.code.startBlock; - worklist ++= (m.exh map (.startBlock)); + worklist += m.code.startBlock + worklist ++= (m.exh map (.startBlock)) m.code.blocks.foreach { b => - in(b) = typeFlowLattice.bottom; - out(b) = typeFlowLattice.bottom; + in(b) = typeFlowLattice.bottom + out(b) = typeFlowLattice.bottom } m.exh foreach { e => - val stack = new TypeStack; + val stack = new TypeStack stack.push( - REFERENCE(if (e.cls eq NoSymbol) definitions.ObjectClass else e.cls)); - in(e.startBlock) = Pair(in(e.startBlock)._1, stack); + REFERENCE(if (e.cls eq NoSymbol) definitions.ObjectClass else e.cls)) + in(e.startBlock) = Pair(in(e.startBlock)._1, stack) } } } def this(m: icodes.IMethod) = { - this(); + this() init(m) } def run = { - forwardAnalysis(blockTransfer); + forwardAnalysis(blockTransfer) if (settings.debug.value) { linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) assert(visited.contains(b), @@ -137,15 +146,14 @@ abstract class TypeFlowAnalysis { } } - def blockTransfer(b: BasicBlock, in: lattice.Elem): lattice.Elem = { + def blockTransfer(b: BasicBlock, in: lattice.Elem): lattice.Elem = b.toList.foldLeft(in)(interpret) - } /** Abstract interpretation for one instruction. */ def interpret(in: typeFlowLattice.Elem, i: Instruction): typeFlowLattice.Elem = { - val out = Pair(new VarBinding(in._1), new TypeStack(in._2)); - val bindings = out._1; - val stack = out._2; + val out = Pair(new VarBinding(in._1), new TypeStack(in._2)) + val bindings = out._1 + val stack = out._2 /* if (settings.debug.value) { Console.println("Stack: " + stack); @@ -154,103 +162,104 @@ abstract class TypeFlowAnalysis { i match { case THIS(clasz) => - stack push toTypeKind(clasz.tpe); + stack push toTypeKind(clasz.tpe) case CONSTANT(const) => - stack push toTypeKind(const.tpe); + stack push toTypeKind(const.tpe) case LOAD_ARRAY_ITEM(kind) => - val Pair(INT, ARRAY(elem)) = stack.pop2; - stack.push(elem); + val Pair(INT, ARRAY(elem)) = stack.pop2 + stack.push(elem) case LOAD_LOCAL(local) => - val t = bindings(local); - stack push (if (t == typeLattice.bottom) local.kind else t); + val t = bindings(local) + stack push (if (t == typeLattice.bottom) local.kind else t) case LOAD_FIELD(field, isStatic) => if (!isStatic) - stack.pop; - stack push toTypeKind(field.tpe); + stack.pop + stack push toTypeKind(field.tpe) case LOAD_MODULE(module) => - stack push toTypeKind(module.tpe); + stack push toTypeKind(module.tpe) case STORE_ARRAY_ITEM(kind) => - stack.pop3; + stack.pop3 case STORE_LOCAL(local) => - val t = stack.pop; - bindings += local -> t; + val t = stack.pop + bindings += local -> t case STORE_FIELD(field, isStatic) => if (isStatic) stack.pop else - stack.pop2; + stack.pop2 case CALL_PRIMITIVE(primitive) => - primitive match { - case Negation(kind) => stack.pop; stack.push(kind); + primitive match { + case Negation(kind) => + stack.pop; stack.push(kind) case Test(_, kind, zero) => - stack.pop; - if (!zero) stack.pop; + stack.pop + if (!zero) stack.pop stack push BOOL; case Comparison(_, _) => - stack.pop2; - stack push INT; + stack.pop2 + stack push INT case Arithmetic(op, kind) => - stack.pop; + stack.pop if (op != NOT) - stack.pop; - stack push kind; + stack.pop + stack push kind - case Logical(op, kind) => - stack.pop2; - stack push kind; + case Logical(op, kind) => + stack.pop2 + stack push kind - case Shift(op, kind) => - stack.pop2; - stack push kind; + case Shift(op, kind) => + stack.pop2 + stack push kind - case Conversion(src, dst) => - stack.pop; - stack push dst; + case Conversion(src, dst) => + stack.pop + stack push dst - case ArrayLength(kind) => - stack.pop; - stack push INT; + case ArrayLength(kind) => + stack.pop + stack push INT - case StartConcat => - stack.push(ConcatClass); + case StartConcat => + stack.push(ConcatClass) - case EndConcat => - stack.pop; - stack.push(STRING); + case EndConcat => + stack.pop + stack.push(STRING) - case StringConcat(el) => - stack.pop2; - stack push ConcatClass; + case StringConcat(el) => + stack.pop2 + stack push ConcatClass } case CALL_METHOD(method, style) => style match { case Dynamic => - stack.pop(1 + method.info.paramTypes.length); - stack.push(toTypeKind(method.info.resultType)); + stack.pop(1 + method.info.paramTypes.length) + stack.push(toTypeKind(method.info.resultType)) case Static(onInstance) => if (onInstance) { - stack.pop(1 + method.info.paramTypes.length); + stack.pop(1 + method.info.paramTypes.length) if (!method.isConstructor) stack.push(toTypeKind(method.info.resultType)); } else { - stack.pop(method.info.paramTypes.length); - stack.push(toTypeKind(method.info.resultType)); + stack.pop(method.info.paramTypes.length) + stack.push(toTypeKind(method.info.resultType)) } case SuperCall(mix) => - stack.pop(1 + method.info.paramTypes.length); - stack.push(toTypeKind(method.info.resultType)); + stack.pop(1 + method.info.paramTypes.length) + stack.push(toTypeKind(method.info.resultType)) } case BOX(kind) => @@ -262,57 +271,57 @@ abstract class TypeFlowAnalysis { stack.push(kind) case NEW(kind) => - stack.push(kind); + stack.push(kind) case CREATE_ARRAY(elem) => - stack.pop; - stack.push(ARRAY(elem)); + stack.pop + stack.push(ARRAY(elem)) case IS_INSTANCE(tpe) => - stack.pop - stack.push(BOOL); + stack.pop + stack.push(BOOL) case CHECK_CAST(tpe) => - stack.pop; - stack.push(tpe); + stack.pop + stack.push(tpe) case SWITCH(tags, labels) => - stack.pop; + stack.pop case JUMP(where) => - () + () case CJUMP(success, failure, cond, kind) => - stack.pop2; + stack.pop2 case CZJUMP(success, failure, cond, kind) => - stack.pop; + stack.pop case RETURN(kind) => if (kind != UNIT) stack.pop; case THROW() => - stack.pop; + stack.pop case DROP(kind) => - stack.pop; + stack.pop case DUP(kind) => - stack.push(stack.head); + stack.push(stack.head) case MONITOR_ENTER() => - stack.pop; + stack.pop case MONITOR_EXIT() => - stack.pop; + stack.pop case _ => - dump; - abort("Unknown instruction: " + i); + dump + abort("Unknown instruction: " + i) } out - } + } // interpret } } diff --git a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala index b591b499bb..7b2f4f059f 100644 --- a/src/compiler/scala/tools/nsc/doc/DocGenerator.scala +++ b/src/compiler/scala/tools/nsc/doc/DocGenerator.scala @@ -843,7 +843,7 @@ abstract class DocGenerator extends Models { - + A B C -- cgit v1.2.3