genmsil.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,568 行 · 第 1/5 页

SCALA
1,568
字号
      def lastBasicBlock: BasicBlock//      def getExceptionBlock(exh: ExceptionHandler): Option[ExceptionBlock]      def close(): Unit/*      protected def findExceptionBlock(list: List[Block], exh: ExceptionHandler): Option[ExceptionBlock] = {        var res: Option[ExceptionBlock] = None        var i: Int = 0        while (i < list.length && res == None) {          val b = list(i)          val exB = b.getExceptionBlock(exh)          exB match {            case some: Some[ExceptionBlock] => res = some            case None => ()          }          i = i + 1        }        res      } */    }    case class CodeBlock(parent: BlockList0) extends Block {      var basicBlocks: List[BasicBlock] = Nil      def isEmpty = basicBlocks.isEmpty      override def firstBasicBlock: BasicBlock = {        if(isEmpty) null        else {          if (closed) basicBlocks.head          else basicBlocks.last        }      }      override def lastBasicBlock: BasicBlock = {        if(isEmpty) null        else {          if (closed) basicBlocks.last          else basicBlocks.head        }      }      override def parentBlockList = Some(parent)//      override def getExceptionBlock(exh: ExceptionHandler): Option[ExceptionBlock] = None      override def close() {        basicBlocks = basicBlocks.reverse        closed = true      }      override def toString() = {        var res = ""        res = res + TopBlock.indent + "CodeBlock(" + basicBlocks + ")\n"        res      }    }    abstract class BlockList0 extends Block {      var blocks: List[Block] = Nil      override def firstBasicBlock: BasicBlock = {        if(blocks.isEmpty) null        else {          if (closed) blocks.head.firstBasicBlock          else blocks.last.firstBasicBlock        }      }      override def lastBasicBlock: BasicBlock = {        if(blocks.isEmpty) null        else {          if (closed) blocks.last.lastBasicBlock          else blocks.head.lastBasicBlock        }      }/*      override def getExceptionBlock(exh: ExceptionHandler): Option[ExceptionBlock] = {        findExceptionBlock(blocks, exh)      } */      def addExceptionBlock(exh: ExceptionHandler) = {        if (settings.debug.value)          log("new exc block with " + exh + " to " + this)        val e = new ExceptionBlock(this, exh)        blocks = e :: blocks        e      }      def addBasicBlock(bb: BasicBlock) = {        if (settings.debug.value)          log("adding bb " + bb + " to " + this)        var cb: CodeBlock = if (!blocks.isEmpty) {          blocks.head match {            case blk: CodeBlock => blk            case _ => null          }        } else null        if (cb == null) {          cb = new CodeBlock(this)          blocks = cb :: blocks        }        cb.basicBlocks = bb :: cb.basicBlocks      }      override def close() {        blocks.foreach(_.close)        blocks = blocks.reverse        closed = true      }      override def toString() = {        var res = ""        res = res + TopBlock.indent + "BlockList0:\n"        TopBlock.indent = TopBlock.indent + "  "        for (b <- blocks)          res = res + b + "\n"        TopBlock.indent = TopBlock.indent.substring(0,TopBlock.indent.length-2)        res      }    }    case class BlockList(parent: Block) extends BlockList0 {      override def parentBlockList: Option[BlockList0] = {        if (parent == TopBlock)          Some(TopBlock)        else parent match {          case bl: BlockList => Some(bl)          case cb: CatchBlock => Some(cb)          case _ => parent.parentBlockList        }      }      override def toString() = {        var res = ""        res = res + TopBlock.indent + "BlockList:\n"        res = res + super.toString()        res      }    }    case class ExceptionBlock(parent: Block, handler: ExceptionHandler) extends Block {      var tryBlock: BlockList = new BlockList(this)      var catchBlocks: List[CatchBlock] = Nil      var finallyBlock: BlockList = new BlockList(this)      override def firstBasicBlock = {        tryBlock.firstBasicBlock      }      override def lastBasicBlock = {        if (!finallyBlock.blocks.isEmpty)          finallyBlock.lastBasicBlock        else if(!catchBlocks.isEmpty) {          if (closed) catchBlocks.last.lastBasicBlock          else catchBlocks.head.lastBasicBlock        } else {          tryBlock.lastBasicBlock        }      }      override def parentBlockList: Option[BlockList0] = {        if (parent == TopBlock)          Some(TopBlock)        else parent match {          case bl: BlockList => Some(bl)          case cb: CatchBlock => Some(cb)          case _ => parent.parentBlockList        }      }/*      override def getExceptionBlock(exh: ExceptionHandler): Option[ExceptionBlock] = {        if (exh == handler) Some(this)        else {          val t = if (tryBlock == null) Nil else List(tryBlock)          val f = if (finallyBlock == null) Nil else List(finallyBlock)          findExceptionBlock(t ::: catchBlocks ::: f, exh)        }      }*/      def addCatchBlock(exSym: Symbol): CatchBlock = {        if (settings.debug.value)          log("new catch block with " + exSym + " to " + this)        val c = new CatchBlock(this, exSym)        catchBlocks = c :: catchBlocks        c      }      override def close() {        tryBlock.close        catchBlocks.foreach(_.close)        catchBlocks = catchBlocks.reverse        finallyBlock.close        closed = true      }      override def toString() = {        var res = ""        res = res + TopBlock.indent + "ExceptionBlock, handler: " + handler + "\n"        res = res + TopBlock.indent + "  " + "try:\n"        TopBlock.indent = TopBlock.indent + "    "        res = res + tryBlock + "\n"        TopBlock.indent = TopBlock.indent.substring(0,TopBlock.indent.length-4)        res = res + TopBlock.indent + "  " + "catch:\n"        TopBlock.indent = TopBlock.indent + "    "        for (b <- catchBlocks)          res = res + b + "\n"        TopBlock.indent = TopBlock.indent.substring(0,TopBlock.indent.length-4)        res = res + TopBlock.indent + "  " + "finally:\n"        TopBlock.indent = TopBlock.indent + "    "        res = res + finallyBlock + "\n"        TopBlock.indent = TopBlock.indent.substring(0,TopBlock.indent.length-4)        res      }    }    case class CatchBlock(parent: ExceptionBlock, exSym: Symbol) extends BlockList0 {      override def parentBlockList: Option[BlockList0] = {        parent.parentBlockList      }      override def toString() = {        var res = ""        res = res + TopBlock.indent + "CatchBlock:\n"        res = res + super.toString()        res      }    }    case object TopBlock extends BlockList0 {      var indent = ""      override def parentBlockList = None      override def toString() = {        var res = ""        res = res + TopBlock.indent + "TopBlock:\n"        res = res + super.toString()        res      }    }    // for every basic block, a list of ExHInstructions to be executed:    //   - Begin_ are executed before the block    //   - EndExceptionBlock is executed after the block    val bb2exHInstructions: HashMap[BasicBlock, List[ExHInstruction]] = new HashMap()    // at the end of a try, catch or finally block, the jumps must not be emitted,    // the automatically generated leave (or endfinally) will do the job.    val omitJumpBlocks: HashSet[BasicBlock] = new HashSet()    // suposes that finalizers are the same for different handlers    // covering the same blocks    def orderBlocksForExh(blocks: List[BasicBlock], exH: List[ExceptionHandler]): List[BasicBlock] = {      var blocksToPut: List[BasicBlock] = blocks      var nextBlock: BasicBlock = null      var untreatedHandlers: List[ExceptionHandler] = exH      TopBlock.blocks = Nil      var currentBlock: BlockList0 = TopBlock      def addBlocks(b: List[BasicBlock]):Unit = b match {        case Nil => if (settings.debug.value) log("adding " + b)        case x :: xs =>          if (settings.debug.value) log("adding " + b)          // problem: block may already be added, and and needs to be moved.          // if nextblock NOT in b: check if nextblock in blocksToPut, if NOT, check if movable, else don't put          if (nextBlock != null && b.contains(nextBlock)) {            val blocksToAdd = nextBlock :: (b - nextBlock)            nextBlock = null            addBlocks(blocksToAdd)          }          else if (untreatedHandlers.forall(h => !(h.covers(x)))) {            if (settings.debug.value) log(" no new handler for " + x)            if (untreatedHandlers.forall(h => !(h.blocks.contains(x) ||                                                (h.finalizer != null &&                                                 h.finalizer.covers(x)))))              {                // the block is not part of some catch or finally code                currentBlock.addBasicBlock(x)                blocksToPut = blocksToPut - x                if (settings.debug.value) log(" -> addBlocks(" + xs + ")")                addBlocks(xs)              } else {                if (settings.debug.value) log("x is part of catch or finally block")                // check if the covered code of the handler x belongs to is empty                // this check is not needed for finalizers: empty try with finalizer                // is optimized by compiler (no try left)                if(untreatedHandlers.forall(h =>                  (!h.blocks.contains(x) || h.covered.isEmpty))) {                    blocksToPut = blocksToPut - x                    addBlocks(xs)                  } else                    addBlocks(xs ::: List(x))              }          } else { // there are new handlers for this block            var firstBlockAfter: HashMap[ExceptionHandler,BasicBlock] = new HashMap()            val savedCurrentBlock = currentBlock            /**             * the output blocks of this method are changed so that:             *  - only one block has a successor outside the set of blocks             *  - this block is the last of the reusulting list             *             * side-effect: it stores the successor in the hashMap             *  firstBlockAfter, which has to be emitted first after try/catch/finally,             *  because the target of the Leave-instruction will always be the first             *  instruction after EndExceptionBlock             *             * returns: the output blocks plus an Option containing the possibly created             * new block             **/            def adaptBlocks(blocks: List[BasicBlock], exh: ExceptionHandler): (List[BasicBlock], Option[BasicBlock]) = {              def outsideTargets(block: BasicBlock, blocks: List[BasicBlock]) = {                /* The catch block of the ExceptionHandler is always a successor of any block inside the try                 * (see successors method in BasicBlocks.scala)                 * Thus, this successor does not correspond to a jump outside the exception handler                 * and has to be ignored when computing the list of blocks leaving the exception handler.  */                val res = block.successors.filter(scc => !blocks.contains(scc) && scc != exh.startBlock)                if (settings.debug.value) log("outside of " + block + " = " + res + " succ " + block.successors)                res              }              // get leaving blocks and their outside targets              def leavingBlocks(blocks: List[BasicBlock]): List[(BasicBlock, List[BasicBlock])] = {                for {b <- blocks                     val t = outsideTargets(b, blocks)                     if t.length != 0 } yield (b, t)              }              def replaceOutJumps(blocks: List[BasicBlock], leaving: List[(BasicBlock, List[BasicBlock])], exh: ExceptionHandler): (List[BasicBlock], Option[BasicBlock]) = {                def replaceJump(block: BasicBlock, from: BasicBlock, to: BasicBlock) = block.lastInstruction match {                  case JUMP(whereto) =>                    //assert(from == whereto)                    block.replaceInstruction(block.lastInstruction, JUMP(to))                  case CJUMP(success, failure, cond, kind) =>                    if (from == success)                      block.replaceInstruction(block.lastInstruction, CJUMP(to, failure, cond, kind))                    else                      //assert(from == failure)                    if (from == failure)                      block.replaceInstruction(block.lastInstruction, CJUMP(success, to, cond, kind))                  case CZJUMP(success, failure, cond, kind) =>                    if (from == success)                      block.replaceInstruction(block.lastInstruction, CZJUMP(to, failure, cond, kind))                    else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?