diff options
Diffstat (limited to 'sources/scala/tools/scalac/icode/ICode.scala')
-rw-r--r-- | sources/scala/tools/scalac/icode/ICode.scala | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/sources/scala/tools/scalac/icode/ICode.scala b/sources/scala/tools/scalac/icode/ICode.scala deleted file mode 100644 index 514c15e0e5..0000000000 --- a/sources/scala/tools/scalac/icode/ICode.scala +++ /dev/null @@ -1,492 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -import scalac.{Global => scalac_Global} - -import scala.collection.mutable.HashMap; -import scala.collection.mutable.HashSet; - -import scalac.symtab._; -import scalac.atree._; -import scalac.util.Debug; - -package scala.tools.scalac.icode { - - - -/** This class represents the intermediate code of a method*/ -class ICode(label: String, global: scalac_Global) { - - //################################################## - // Public fields - - /* The set of all blocks */ - val blocks: HashSet[IBasicBlock] = new HashSet; - - /* The start block of the method */ - var startBlock : IBasicBlock = null; - - /* The stack produced by this method */ - var producedStack : ICTypeStack = null; - - //################################################## - // Private fields - private var currentLabel : int = 0; - - private var aTreeLabels : HashMap[Symbol, IBasicBlock] = new HashMap; - - //################################################## - // Constructor code - - startBlock = newBlock; - startBlock.initStack(new ICTypeStack); - - //################################################## - // Public methods - - /** This method produce the intermediate code for - * the given ATree */ - def generate(acode : ACode) = { - val ctx = gen(acode, new GenContext(startBlock, null)); - - ctx.emit(RETURN()); // ??? RETURN instruction rather come from ATree - genTypeStack; - - producedStack = ctx.currentBlock.endStack; - } - - def icTraverse(f: IBasicBlock => unit) = icTraverseFeedBack((bb: IBasicBlock, hm: HashMap[IBasicBlock, boolean]) => f(bb)); - - /* This method applies the given function to all the block */ - def icTraverseFeedBack(f: (IBasicBlock, HashMap[IBasicBlock, boolean]) => unit) = { - // ?? Define order (actually preorder) - val visited : HashMap[IBasicBlock, boolean] = new HashMap; - visited ++= blocks.elements.map(x => Pair(x, false)); - - var blockToVisit : List[IBasicBlock] = startBlock::Nil; - - while (blockToVisit != Nil) { - blockToVisit match { - case b::xs => { - if (!visited(b)) { - f(b, visited); - blockToVisit = b.successors:::xs; - visited += b -> true; - } else - blockToVisit = xs; - } - } - } - } - - - /** This methods returns a string representation of the ICode */ - override def toString() : String = "ICode '"+label+"'"; // - - //################################################## - // Public method - printing (for debug use) - - /** This method print the code */ - def print() : unit = print(System.out); - - def print(out: java.io.PrintStream) : unit = { - icTraverse((bb: IBasicBlock) => { - out.println("Block #"+bb.label); - out.println("Substituable variables : "); - if (bb.substituteVars != null) - bb.substituteVars.foreach(out.print); - else - out.println(" {Empty} "); - out.println("Instructions:"); - bb.bbTraverse((ici: ICInstruction) => - out.println(" "+ici.toString())); - out.print ("Successors: "); - bb.successors.foreach((bb: IBasicBlock) => out.print(bb.label+", ")); - out.println (""); // ?? Del - out.println (); - }); - } - - - def logType = { - global.log ("// Typing "+toString()); - this.icTraverse((bb: IBasicBlock) => { - global.log ("Typing block #"+bb.label); - var typer = new ICTypeStack; - bb.bbTraverse((ic: ICInstruction) => { - typer = typer.eval(ic); - global.log(ic.toString()+" -> "+typer.toString()); - }); - - }); - } - - //################################################## - // Private methods - - /* Compute a unique new label */ - private def nextLabel = { - currentLabel = currentLabel + 1; - currentLabel; - } - - /* This method : - * 1/ create a new block - * 2/ add the new block to the set - * 3/ return the new block - */ - private def newBlock : IBasicBlock = { - val block = new IBasicBlock(nextLabel); - blocks += block; - block; - } - - /* Generate the code from a given ATree */ - private def gen(aCode: ACode, ctx: GenContext) : GenContext = - aCode match { - case ACode.Void => { - global.log ("ICodeGenerator::emit: Void node found"); - ctx; - } - - case ACode$This(clasz) => - ctx.emit(THIS(clasz)); - - case ACode$Constant(c) => - ctx.emit(CONSTANT(c)); - - case ACode$Load(ALocation$Module(_)) => { - global.log ("ICodeGenerator::emit: Load(Module) node found"); - ctx; - } - - case ACode$Load(ALocation$Field(obj, field ,isStatic)) => { - var ctx1 = gen(obj, ctx); - ctx.emit(LOAD_FIELD(field, isStatic)); - } - - case ACode$Load(ALocation$Local(local,isArgument)) => - ctx.emit(LOAD_LOCAL(local, isArgument)); - - case ACode$Load(ALocation$ArrayItem(array, index)) => { - var ctx1 = gen(array, ctx); - ctx1 = gen(index, ctx1); - ctx1.emit(LOAD_ARRAY_ITEM()); - } - - case ACode$Store(ALocation$Module(_),_) => { - global.log ("ICodeGenerator::emit: Store(Module(_)) node found"); - ctx; - } - - case ACode$Store(ALocation$Field(obj, field, isStatic), value) => { - var ctx1 = gen(obj, ctx); - ctx1 = gen(value, ctx1); - ctx1.emit(STORE_FIELD(field, isStatic)); - } - - case ACode$Store(ALocation$Local(local, isArgument), value) => { - val ctx1 = gen(value, ctx); - ctx1.emit(STORE_LOCAL(local, isArgument)); - } - - case ACode$Store(ALocation$ArrayItem(array, index), value) => { - var ctx1 = gen(array, ctx); - ctx1 = gen(index, ctx1); - ctx1 = gen(value, ctx1); - ctx1.emit(STORE_ARRAY_ITEM()); - } - - case ACode$Apply(AFunction$Method(_,sym,AInvokeStyle.New),_,vargs) => { - val vargs_it = Iterator.fromArray(vargs); - // !!! Depend the backend in use - ctx.emit(NEW(sym.owner())); - ctx.emit(DUP(sym.owner().getType())); - var ctx1 = ctx; - vargs_it.foreach((varg: ACode) => ctx1 = gen(varg, ctx1)); - ctx1.emit(CALL_METHOD(sym,AInvokeStyle.StaticInstance)); - } - - case ACode$Apply(AFunction$Method(obj,sym,style),_,vargs) => { - val vargs_it = Iterator.fromArray(vargs); - var ctx1 = ctx; - style match { - case AInvokeStyle.StaticClass => - ; // NOP - case _ => - ctx1 = gen(obj, ctx1); - } - vargs_it.foreach((varg: ACode) => ctx1 = gen(varg, ctx1)); - ctx1.emit(CALL_METHOD(sym,style)); - } - - case ACode$Apply(AFunction$Primitive(p),_,vargs) => { - val vargs_it = Iterator.fromArray(vargs); - var ctx1 = ctx; - - vargs_it.foreach((varg: ACode) => ctx1 = gen(varg, ctx1)); - ctx1.emit(CALL_PRIMITIVE(p)); - } - - case ACode$Apply(AFunction$NewArray(element),_,vargs) => { - var ctx1 = gen(vargs(0), ctx); // The size is given as first argument - ctx1.emit(CREATE_ARRAY(element)); - } - - case ACode$IsAs(value,typ,false) => { - var ctx1 = gen(value, ctx); - ctx1.emit(IS_INSTANCE(typ)); - } - - case ACode$IsAs(value,typ,true) => { - var ctx1 = gen(value, ctx); - ctx1.emit(CHECK_CAST(typ)); - } - - case ACode$If(test, success, failure) => { - genAlt(test, success, failure, ctx, newBlock); - } - - case ACode$Switch(test,tags,bodies) => { - - val switchBodies = List.fromArray(bodies, 0, bodies.length); - var switchBlocks: List[IBasicBlock] = Nil; - for (val i : ACode <- switchBodies) switchBlocks = newBlock::switchBlocks; - val switchPairs = switchBodies.zip(switchBlocks); - - val nextBlock = newBlock; - - var ctx1 = gen(test, ctx); - ctx1.emit(SWITCH(tags, switchBlocks)); - //ctx1.currentBlock.addSuccessors(switchBlocks); - - switchPairs.foreach((p: Pair[ACode, IBasicBlock]) => { - val code = p._1; - val block = p._2; - - val ctx2 = gen(code, new GenContext(block, nextBlock)); - ctx2.closeBlock; - }); - - ctx1.changeBlock(nextBlock); - } - - case ACode$Synchronized(lock, value) => { - var ctx1 = gen(lock, ctx); - ctx1.emit(MONITOR_ENTER()); - ctx1 = gen(value,ctx); - ctx1 = gen(lock, ctx); - ctx1.emit(MONITOR_EXIT()); - } - - case ACode$Block(_,statements,value) => { - val statements_it = Iterator.fromArray(statements); - var ctx1 = ctx; - statements_it.foreach((st: ACode) => ctx1 = gen(st, ctx1)); - ctx1 = gen(value, ctx1); - ctx1; - } - - case ACode$Label(label, locals, value) => { - global.log("Add new label: "+label); - - val loopBlock = newBlock; - var ctx1 = ctx.changeBlock(loopBlock); - ctx.nextBlock = loopBlock; - ctx.closeBlock; - - aTreeLabels += label -> loopBlock; - - loopBlock.substituteVars = List.fromIterator(Iterator.fromArray(locals)); - gen(value, ctx1); - } - - case ACode$Goto(label,vargs) => { - - val vargs_it = Iterator.fromArray(vargs); - global.log("Current label mapping: "+aTreeLabels.keys.foreach((s: Symbol) => global.log(s.toString()))); - global.log("Looking for sym: "+label); - val gotoBlock = aTreeLabels(label); - var ctx1 = ctx; - - // Stack-> : - vargs_it.foreach((varg: ACode) => ctx1 = gen(varg, ctx1)); - - // Stack-> :varg0:varg1:...:vargn - // We should have the same number of varg that substitute vars - - gotoBlock.substituteVars.reverse.foreach( - (varg: Symbol) => ctx1.emit(STORE_LOCAL(varg, false)) // ?? false - ); - ctx1.nextBlock = gotoBlock; - ctx1.closeBlock; - - ctx1; - } - - case ACode$Return(_,value) => { - var ctx1 = gen(value, ctx); - ctx1.emit(RETURN()); - } - case ACode$Throw(value) => { - var ctx1 = gen(value, ctx); - ctx1.emit(THROW()); - } - - case ACode$Drop(value, typ) => { - var ctx1 = gen(value, ctx); - //global.log("Type de Drop: "+typ+" = unboxed:"+typ.unbox() ); - if (! typ.isSameAs(global.definitions.void_TYPE())) - typ.unbox() match { // !!! Hack - case Type$UnboxedType(TypeTags.UNIT) => - global.log("it matches UNIT !"); // debug ; // NOP - case _ => - ctx1.emit(DROP(typ)); - } - else - global.log("it matches SCALAC_UNIT :-("); - ctx1; - } - } - - /* This method genrates an alternative. In the case of an if instruction - * It looks at the kind of alternatives and creates new basic blocks - * - * @param nextBlock : represents the block where alternatives meet again*/ - private def genAlt (cond : ACode, success: ACode, failure: ACode, ctx: GenContext, nextBlock: IBasicBlock) : GenContext = { - val successBlock = success match { - case ACode.Void => nextBlock; - - case ACode$If(test, innerSuccess, innerFailure) => { - val ctx1 = new GenContext(newBlock, null); - val ctx2 = genAlt(test, innerSuccess, innerFailure, ctx1, nextBlock); - //ctx2.closeBlock; // or close when CJUMP is emitted - ctx1.currentBlock; - } - - case _ => { - val ctx1 = new GenContext(newBlock, nextBlock); - val ctx2 = gen(success, ctx1); - ctx2.closeBlock; - ctx1.currentBlock; - } - } - - val failureBlock = failure match { - case ACode.Void => nextBlock; - - case ACode$If(test, innerSuccess, innerFailure) => { - val ctx1 = new GenContext(newBlock, null); - val ctx2 = genAlt(test, innerSuccess, innerFailure, ctx1, nextBlock); - //ctx2.closeBlock; // or close when CJUMP is emitted - ctx1.currentBlock; - } - - case _ => { - val ctx1 = new GenContext(newBlock, nextBlock); - val ctx2 = gen(failure, ctx1); - ctx2.closeBlock; - ctx1.currentBlock; - } - } - - var ctx1 = genCond(cond, successBlock, failureBlock, ctx); - ctx1.changeBlock(nextBlock); - } - - /* This methods generate the test and the jump instruction */ - private def genCond(cond: ACode, successBlock: IBasicBlock, failureBlock: IBasicBlock, ctx: GenContext) : GenContext= { - var ctx1 = ctx; - cond match { - case ACode$Apply(AFunction$Primitive(APrimitive$Test(op,_,zero)),_, vargs) => { - ctx1 = gen(vargs(0),ctx1); - if (zero) - ctx1.emit(CZJUMP(successBlock, failureBlock, op)); - else { - ctx1 = gen(vargs(1), ctx1); - ctx1.emit(CJUMP(successBlock, failureBlock, op)); - } - //ctx1.currentBlock.addSuccessors(failureBlock::successBlock::Nil); - } - - case ACode$Apply(AFunction$Primitive(APrimitive$Negation(_)),_,vargs) => - ctx1 = genCond(vargs(0), failureBlock, successBlock, ctx1); - // ??? Test with TestOp opposite ? - case _ => { - ctx1 = gen(cond, ctx1); - //ctx1.emit(CONSTANT(AConstant.INT(1))); - // We have a boolean value - ctx1.emit(CZJUMP(successBlock, failureBlock, ATestOp.NE)); - //ctx1.currentBlock.addSuccessors(failureBlock::successBlock::Nil); - } - } - ctx1; - } - - /* This method generate the type stacks of all the blocks - * of this method.*/ - private def genTypeStack = { - icTraverse((bb: IBasicBlock) => { - global.log("// Typing block #"+bb.label); - global.log("\t-> "+bb.endStack); - bb.typeBlock; - // !!! Here we must test if all the meeting blocks have the - // !!! same stack. - bb.successors.foreach((suc: IBasicBlock) => suc.initStack(bb.endStack)); - }); - } - -} - - /* This class represents the context of generating icode */ - class GenContext(current: IBasicBlock, next: IBasicBlock) { - - // ################################################## - // Public fields - - /* The block in which we add instructions */ - val currentBlock = current; - - /* The block were we jump at the end of the current block - * It can be the *null* value */ - var nextBlock = next; - - // ################################################## - // Constructor code - - assert(current != null, "No current block"); - - // ################################################## - // Public methods - - /* append an instruction at the end of the current block */ - def emit(instr: ICInstruction) : GenContext = { - currentBlock.emit(instr); - this; - } - - /* Split the current block. The next block is still the same */ - def changeBlock(bb: IBasicBlock) = { - new GenContext(bb, next); - } - - /* Close the current block. If there's a known next block - * It append a jump instruction to the block. - * This method do something only the first time it's called */ - def closeBlock = { - if (!currentBlock.isClosedBlock) { - if (nextBlock != null) { - emit(JUMP(nextBlock)); - //currentBlock.addSuccessor(nextBlock); - } - currentBlock.close; - } - } - } - -} // package |