genmsil.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,568 行 · 第 1/5 页
SCALA
1,568 行
//assert(from == failure) if (from == failure) block.replaceInstruction(block.lastInstruction, CZJUMP(success, to, cond, kind)) case SWITCH(tags, labels) => // labels: List[BasicBlock] val newLabels = labels.map(b => if (b == from) to else b) assert(newLabels.contains(to)) block.replaceInstruction(block.lastInstruction, SWITCH(tags, newLabels)) /* case RETURN(kind) => if (kind != UNIT) { returnVal } block.replaceInstruction(block.lastInstructionm JUMP(to)) */ case _ => () //abort("expected branch at the end of block " + block) } val jumpOutBlock = blocks.last.code.newBlock jumpOutBlock.emit(JUMP(firstBlockAfter(exh))) jumpOutBlock.close leaving.foreach(p => { val lBlock = p._1 val target = p._2(0) // the elemets of p._2 are all the same, checked before replaceJump(lBlock, target, jumpOutBlock) if (settings.debug.value) log("replacing " + lBlock + " target " + target + " jump out " + jumpOutBlock) }) (blocks ::: List(jumpOutBlock), Some(jumpOutBlock)) } val leaving = leavingBlocks(blocks) if (settings.debug.value) log("leaving " + leaving) if (leaving.length == 0) (blocks, None) else if (leaving.length == 1) { val outside = leaving(0)._2 //assert(outside.forall(b => b == outside(0)), "exception-block leaving to multiple targets") if (!firstBlockAfter.isDefinedAt(exh)) firstBlockAfter(exh) = outside(0) //else () //assert(firstBlockAfter(exh) == outside(0), "try/catch leaving to multiple targets: " + firstBlockAfter(exh) + ", new: " + outside(0)) val last = leaving(0)._1 ((blocks - last) ::: List(last), None) } else { val outside = leaving.flatMap(p => p._2) //assert(outside.forall(b => b == outside(0)), "exception-block leaving to multiple targets") if (!firstBlockAfter.isDefinedAt(exh)) firstBlockAfter(exh) = outside(0) //else //assert(firstBlockAfter(exh) == outside(0), "try/catch leaving to multiple targets") replaceOutJumps(blocks, leaving, exh) } } var affectedHandlers: List[ExceptionHandler] = Nil untreatedHandlers.foreach( (h) => { if (h.covers(x)){ affectedHandlers = h :: affectedHandlers } }) // shorter try-catch-finally last (the ones contained in another) affectedHandlers = affectedHandlers.sort({(h1, h2) => h1.covered.length > h2.covered.length}) affectedHandlers = affectedHandlers.filter(h => {h.covered.length == affectedHandlers(0).covered.length}) untreatedHandlers = untreatedHandlers -- affectedHandlers // more than one catch produces more than one exh, but we only need one var singleAffectedHandler: ExceptionHandler = affectedHandlers(0) // List[ExceptionHandler] = Nil var exceptionBlock: Option[ExceptionBlock] = None if (settings.debug.value) log("affected handlers " + affectedHandlers) affectedHandlers.foreach(h1 => { val (adaptedBlocks, newBlock) = adaptBlocks(blocksToPut.intersect(h1.blocks), singleAffectedHandler) newBlock match { case Some(block) => blocksToPut = blocksToPut ::: List(block) h1.addBlock(block) case None => () } val orderedCatchBlocks = h1.startBlock :: (adaptedBlocks - h1.startBlock) exceptionBlock match { case Some(excBlock) => val catchBlock = excBlock.addCatchBlock(h1.cls) currentBlock = catchBlock addBlocks(orderedCatchBlocks) case None => val excBlock = currentBlock.addExceptionBlock(singleAffectedHandler) exceptionBlock = Some(excBlock) val (tryBlocks, newBlock) = adaptBlocks(blocksToPut.intersect(singleAffectedHandler.covered), singleAffectedHandler) newBlock match { case Some(block) => blocksToPut = blocksToPut ::: List(block) singleAffectedHandler.addCoveredBlock(block) case None => () } currentBlock = excBlock.tryBlock if (settings.debug.value) log("adding try blocks " + tryBlocks) addBlocks(tryBlocks) if (singleAffectedHandler.finalizer != null && singleAffectedHandler.finalizer != NoFinalizer) { val (blocks0, newBlock) = adaptBlocks(blocksToPut.intersect(singleAffectedHandler.finalizer.blocks), singleAffectedHandler) newBlock match { case Some(block) => blocksToPut = blocksToPut ::: List(block) singleAffectedHandler.finalizer.addBlock(block) case None => () } val blocks = singleAffectedHandler.finalizer.startBlock :: (blocks0 - singleAffectedHandler.finalizer.startBlock) currentBlock = excBlock.finallyBlock addBlocks(blocks) } val catchBlock = excBlock.addCatchBlock(singleAffectedHandler.cls) currentBlock = catchBlock addBlocks(orderedCatchBlocks) } if (firstBlockAfter.isDefinedAt(singleAffectedHandler)) nextBlock = firstBlockAfter(singleAffectedHandler) else nextBlock = null }) currentBlock = savedCurrentBlock if (settings.debug.value) log(" -> addBlocks(" + xs.intersect(blocksToPut) + ")") addBlocks(xs.intersect(blocksToPut)) } } // begin method orderBlocksForExh if (settings.debug.value) log("before: " + blocks) // some blocks may have been removed by linearization untreatedHandlers.foreach(h => { h.blocks = h.blocks.intersect(blocksToPut) h.covered = h.covered.intersect(blocksToPut) if (h.finalizer != null && h.finalizer != NoFinalizer) h.finalizer.blocks = h.finalizer.blocks.intersect(blocksToPut) }) addBlocks(blocks) TopBlock.close() if (settings.debug.value) log("TopBlock tree is: ") if (settings.debug.value) log(TopBlock) bb2exHInstructions.clear def addExHInstruction(b: BasicBlock, ehi: ExHInstruction) = { if (settings.debug.value) log("adding exhinstr: " + b + " -> " + ehi) if (bb2exHInstructions.contains(b)){ bb2exHInstructions(b) = ehi :: bb2exHInstructions(b) } else { bb2exHInstructions(b) = List(ehi) } } omitJumpBlocks.clear def omitJump(blk: BasicBlock) = { omitJumpBlocks += blk } var orderedBlocks: List[BasicBlock] = Nil def flatten(block: Block) { if (block == TopBlock) { for (b <- TopBlock.blocks) flatten(b) } else block match { case cb: CodeBlock => orderedBlocks = orderedBlocks ::: cb.basicBlocks case bl: BlockList => for (b <- bl.blocks) flatten(b) case cb: CatchBlock => for (b <- cb.blocks) flatten(b) case eb: ExceptionBlock => val handler = eb.handler if (settings.debug.value) { log("new exception block " + eb) log("try: " + eb.tryBlock) } addExHInstruction(eb.tryBlock.firstBasicBlock, new BeginExceptionBlock(handler)) omitJump(eb.tryBlock.lastBasicBlock) flatten(eb.tryBlock) for (c <- eb.catchBlocks) { val t: MsilType = (if (c.exSym == NoSymbol) EXCEPTION else getType(c.exSym)) addExHInstruction(c.firstBasicBlock, new BeginCatchBlock(handler, t)) omitJump(c.lastBasicBlock) flatten(c) } if (handler.finalizer != null && handler.finalizer != NoFinalizer) { addExHInstruction(eb.finallyBlock.firstBasicBlock, new BeginFinallyBlock(handler)) flatten(eb.finallyBlock) addExHInstruction(eb.finallyBlock.lastBasicBlock, new EndExceptionBlock(handler)) omitJump(eb.finallyBlock.lastBasicBlock) } else { addExHInstruction(eb.catchBlocks.last.lastBasicBlock, new EndExceptionBlock(handler)) } } } flatten(TopBlock) assert(untreatedHandlers.forall((h) => h.covered.isEmpty), "untreated exception handlers left: " + untreatedHandlers) // remove catch blocks from empty handlers (finally-blocks remain) untreatedHandlers.foreach((h) => { orderedBlocks = orderedBlocks -- h.blocks }) // take care of order in which exHInstructions are executed (BeginExceptionBlock as last) bb2exHInstructions.keys.foreach((b) => { bb2exHInstructions(b).sort((i1, i2) => (!i1.isInstanceOf[BeginExceptionBlock])) }) if (settings.debug.value){ log("after: " + orderedBlocks) log(" exhInstr: " + bb2exHInstructions) } orderedBlocks } var currentBlock: BasicBlock = _ var lastBlock: BasicBlock = _ var nextBlock: BasicBlock = _ def genBlocks(l: List[BasicBlock]) { l match { case Nil => () case x :: Nil => currentBlock = x; nextBlock = null; genBlock(x) case x :: y :: ys => currentBlock = x; nextBlock = y; genBlock(x); genBlocks(y :: ys) } } var ignoreNextDup: Boolean = false val excResultLocals: Stack[LocalBuilder] = new Stack() def genBlock(b: BasicBlock) { // at begin of the first block, there's nothing to save => // lastBlock != null is secure def saveResult(resType: MsilType) = if (resType != MVOID && lastBlock != null) { lastBlock.lastInstruction match { case THROW() => () case _ => val lb: LocalBuilder = excResultLocals.top mcode.Emit(OpCodes.Stloc, lb) } } if (bb2exHInstructions.contains(b)){ bb2exHInstructions(b).foreach((i) => i match { case BeginExceptionBlock(handler) => if (settings.debug.value) log("begin ex blk: " + handler) mcode.BeginExceptionBlock() val resType = msilType(handler.resultKind) if (resType != MVOID) { val l = mcode.DeclareLocal(resType) l.SetLocalSymInfo("$exhResult") excResultLocals.push(l) } case BeginCatchBlock(handler, exType) => if (settings.debug.value) log("begin catch blk: " + handler + ", tpe: " + exType) saveResult(msilType(handler.resultKind)) mcode.BeginCatchBlock(exType) case BeginFinallyBlock(handler) => saveResult(msilType(handler.resultKind)) mcode.BeginFinallyBlock() case EndExceptionBlock(handler) => () case _ => abort("unknown case: " + i) }) } mcode.MarkLabel(labels(b)) if (settings.debug.value) log("Generating code for block: " + b) var lastLineNr: Int = 0 b traverse ( instr => { needAdditionalRet = false val currentLineNr = (instr.pos).line match { case Some(line) => line case None => log("Warning: wrong position in: " + method) lastLineNr } // if getting line number fails if (currentLineNr != lastLineNr) { mcode.setPosition(currentLineNr) lastLineNr = currentLineNr } instr match { case THIS(clasz) => mcode.Emit(OpCodes.Ldarg_0) case CONSTANT(const) => const.tag match { case UnitTag => () case BooleanTag => mcode.Emit(if (const.booleanValue) OpCodes.Ldc_I4_1 else OpCodes.Ldc_I4_0) case ByteTag => loadI4(const.byteValue, mcode) case ShortTag => loadI4(const.shortValue, mcode) case CharTag => loadI4(const.charValue, mcode) case IntTag => loadI4(const.intValue, mcode) case LongTag => mcode.Emit(OpCodes.Ldc_I8, const.longValue) case FloatTag => mcode.Emit(OpCodes.Ldc_R4, const.floatValue) case DoubleTag => mcode.Emit(OpCodes.Ldc_R8, const.doubleValue) case StringTag => mcode.Emit(OpCodes.Ldstr, const.stringValue)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?