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 + -
显示快捷键?