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