genicode.scala

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

SCALA
1,653
字号
              val dims = arr.dimensions              var elemKind = arr.elementKind              if (args.length > dims)                unit.error(tree.pos, "too many arguments for array constructor: found " + args.length +                   " but array has only " + dims + " dimension(s)")              if (args.length != dims)                for (i <- args.length until dims) elemKind = ARRAY(elemKind)              ctx1.bb.emit(CREATE_ARRAY(elemKind, args.length), tree.pos)            case rt @ REFERENCE(cls) =>              if (settings.debug.value)                assert(ctor.owner == cls,                       "Symbol " + ctor.owner.fullNameString + " is different than " + tpt)              val nw = NEW(rt)              ctx1.bb.emit(nw, tree.pos)              ctx1.bb.emit(DUP(generatedType))              ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)              val init = CALL_METHOD(ctor, Static(true))              nw.init = init              ctx1.bb.emit(init, tree.pos)            case _ =>              abort("Cannot instantiate " + tpt + "of kind: " + generatedType)          }          ctx1        case Apply(fun @ _, List(expr)) if (definitions.isBox(fun.symbol)) =>          if (settings.debug.value)            log("BOX : " + fun.symbol.fullNameString);          val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe))          val nativeKind = toTypeKind(expr.tpe)          if (settings.Xdce.value) {            // we store this boxed value to a local, even if not really needed.            // boxing optimization might use it, and dead code elimination will             // take care of unnecessary stores            var loc1 = ctx.makeLocal(tree.pos, expr.tpe, "boxed")            ctx1.bb.emit(STORE_LOCAL(loc1))            ctx1.bb.emit(LOAD_LOCAL(loc1))          }          ctx1.bb.emit(BOX(nativeKind), expr.pos)          generatedType = toTypeKind(fun.symbol.tpe.resultType)          ctx1        case Apply(fun @ _, List(expr)) if (definitions.isUnbox(fun.symbol)) =>          if (settings.debug.value)            log("UNBOX : " + fun.symbol.fullNameString)          val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe))          val boxType = toTypeKind(fun.symbol.owner.linkedClassOfClass.tpe)          generatedType = boxType          ctx1.bb.emit(UNBOX(boxType), expr.pos)          ctx1        case Apply(fun, args) =>          val sym = fun.symbol          if (sym.isLabel) {  // jump to a label            val label = ctx.labels.get(sym) match {              case Some(l) => l              // it is a forward jump, scan for labels              case None =>                log("Performing scan for label because of forward jump.")                scanForLabels(ctx.defdef, ctx)                ctx.labels.get(sym) match {                  case Some(l) =>                     log("Found label: " + l)                    l                  case _       =>                    abort("Unknown label target: " + sym +                          " at: " + (fun.pos) + ": ctx: " + ctx)                }            }            val ctx1 = genLoadLabelArguments(args, label, ctx)            if (label.anchored)              ctx1.bb.emit(JUMP(label.block), tree.pos)            else              ctx1.bb.emit(PJUMP(label), tree.pos)            ctx1.bb.close            ctx1.newBlock          } else if (isPrimitive(sym)) { // primitive method call            val Select(receiver, _) = fun            val code = scalaPrimitives.getPrimitive(sym, receiver.tpe)            var ctx1 = ctx            if (scalaPrimitives.isArithmeticOp(code)) {              ctx1 = genArithmeticOp(tree, ctx1, code)            } else if (code == scalaPrimitives.CONCAT) {              ctx1 = genStringConcat(tree, ctx1)              generatedType = STRING            } else if (scalaPrimitives.isArrayOp(code)) {              ctx1 = genArrayOp(tree, ctx1, code)            } else if (scalaPrimitives.isLogicalOp(code) ||                       scalaPrimitives.isComparisonOp(code)) {              val trueCtx = ctx1.newBlock              val falseCtx = ctx1.newBlock              val afterCtx = ctx1.newBlock              genCond(tree, ctx1, trueCtx, falseCtx)              trueCtx.bb.emit(CONSTANT(Constant(true)), tree.pos)              trueCtx.bb.emit(JUMP(afterCtx.bb))              trueCtx.bb.close              falseCtx.bb.emit(CONSTANT(Constant(false)), tree.pos)              falseCtx.bb.emit(JUMP(afterCtx.bb))              falseCtx.bb.close              generatedType = BOOL              ctx1 = afterCtx            } else if (code == scalaPrimitives.SYNCHRONIZED) {              val monitor = ctx.makeLocal(tree.pos, definitions.ObjectClass.tpe, "monitor")               ctx1 = genLoadQualifier(fun, ctx1)              ctx1.bb.emit(DUP(ANY_REF_CLASS))              ctx1.bb.emit(STORE_LOCAL(monitor))              ctx1.bb.emit(MONITOR_ENTER(), tree.pos)              ctx1.enterSynchronized(monitor)              if (settings.debug.value)                log("synchronized block start");              ctx1 = ctx1.Try(                bodyCtx => {                  val ctx1 = genLoad(args.head, bodyCtx, expectedType /* toTypeKind(tree.tpe.resultType) */)                  ctx1.bb.emit(LOAD_LOCAL(monitor))                  ctx1.bb.emit(MONITOR_EXIT(), tree.pos)                  ctx1                }, List(                  // tree.tpe / fun.tpe is object, which is no longer true after this transformation                  (NoSymbol, expectedType, exhCtx => {                  exhCtx.bb.emit(LOAD_LOCAL(monitor))                  exhCtx.bb.emit(MONITOR_EXIT(), tree.pos)                  exhCtx.bb.emit(THROW())                  exhCtx.bb.enterIgnoreMode                  exhCtx                })), EmptyTree);              if (settings.debug.value)                log("synchronized block end with block " + ctx1.bb +                    " closed=" + ctx1.bb.isClosed);              ctx1.exitSynchronized(monitor)            } else if (scalaPrimitives.isCoercion(code)) {              ctx1 = genLoad(receiver, ctx1, toTypeKind(receiver.tpe))              genCoercion(tree, ctx1, code)              generatedType = scalaPrimitives.generatedKind(code)            } else              abort("Primitive operation not handled yet: " + sym.fullNameString + "(" +                    fun.symbol.simpleName + ") " + " at: " + (tree.pos));            ctx1          } else {  // normal method call            if (settings.debug.value)              log("Gen CALL_METHOD with sym: " + sym + " isStaticSymbol: " + isStaticSymbol(sym));            var invokeStyle =              if (isStaticSymbol(sym))                Static(false)              else if (sym.hasFlag(Flags.PRIVATE) || sym.isClassConstructor)                Static(true)              else                Dynamic            var ctx1 =              if (invokeStyle.hasInstance) genLoadQualifier(fun, ctx)              else ctx            ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx1)            val hostClass = fun match {              case Select(qualifier, _)              if (qualifier.tpe.typeSymbol != definitions.ArrayClass) =>                qualifier.tpe.typeSymbol              case _ => sym.owner            }            if (settings.debug.value && hostClass != sym.owner)              log("Set more precise host class for " + sym.fullNameString + " host: " + hostClass);            ctx1.bb.emit(CALL_METHOD(sym, invokeStyle) setHostClass hostClass, tree.pos)            if (sym == ctx1.method.symbol) {              ctx1.method.recursive = true            }            generatedType =              if (sym.isClassConstructor) UNIT              else toTypeKind(sym.info.resultType);            ctx1          }        case This(qual) =>          assert(tree.symbol == ctx.clazz.symbol || tree.symbol.isModuleClass,                 "Trying to access the this of another class: " +                 "tree.symbol = " + tree.symbol + ", ctx.clazz.symbol = " + ctx.clazz.symbol + " compilation unit:"+unit)          if (tree.symbol.isModuleClass && tree.symbol != ctx.clazz.symbol) {            if (settings.debug.value)              log("LOAD_MODULE from 'This': " + tree.symbol);            assert(!tree.symbol.isPackageClass, "Cannot use package as value: " + tree)            ctx.bb.emit(LOAD_MODULE(tree.symbol), tree.pos)            generatedType = REFERENCE(tree.symbol)          } else {            ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos)            if (tree.symbol == definitions.ArrayClass)              generatedType = REFERENCE(definitions.BoxedAnyArrayClass)            else              generatedType = REFERENCE(ctx.clazz.symbol)          }          ctx        case Select(Ident(nme.EMPTY_PACKAGE_NAME), module) =>          if (settings.debug.value) {            assert(tree.symbol.isModule,                   "Selection of non-module from empty package: " + tree.toString() +                   " sym: " + tree.symbol +                   " at: " + (tree.pos))            log("LOAD_MODULE from Select(<emptypackage>): " + tree.symbol);          }          assert(!tree.symbol.isPackageClass, "Cannot use package as value: " + tree)          ctx.bb.emit(LOAD_MODULE(tree.symbol), tree.pos)          ctx        case Select(qualifier, selector) =>          val sym = tree.symbol          generatedType = toTypeKind(sym.info)          if (sym.isModule) {            if (settings.debug.value)              log("LOAD_MODULE from Select(qualifier, selector): " + sym);            assert(!tree.symbol.isPackageClass, "Cannot use package as value: " + tree)            ctx.bb.emit(LOAD_MODULE(sym), tree.pos);            ctx          } else if (isStaticSymbol(sym)) {            ctx.bb.emit(LOAD_FIELD(sym, true), tree.pos)            ctx          } else {            val ctx1 = genLoadQualifier(tree, ctx)            ctx1.bb.emit(LOAD_FIELD(sym, false), tree.pos)            ctx1          }        case Ident(name) =>          if (!tree.symbol.isPackage) {            if (tree.symbol.isModule) {              if (settings.debug.value)                log("LOAD_MODULE from Ident(name): " + tree.symbol);              assert(!tree.symbol.isPackageClass, "Cannot use package as value: " + tree)              ctx.bb.emit(LOAD_MODULE(tree.symbol), tree.pos)              generatedType = toTypeKind(tree.symbol.info)            } else {              try {                val Some(l) = ctx.method.lookupLocal(tree.symbol)                ctx.bb.emit(LOAD_LOCAL(l), tree.pos)                generatedType = l.kind              } catch {                case ex: MatchError =>                   throw new Error("symbol " + tree.symbol +                                  " does not exist in " + ctx.method)              }            }          }          ctx        case Literal(value) =>          if (value.tag != UnitTag) (value.tag, expectedType) match {            case (IntTag, LONG) =>              ctx.bb.emit(CONSTANT(Constant(value.longValue)), tree.pos);              generatedType = LONG            case (FloatTag, DOUBLE) =>              ctx.bb.emit(CONSTANT(Constant(value.doubleValue)), tree.pos);              generatedType = DOUBLE            case (NullTag, _) =>              ctx.bb.emit(CONSTANT(value), tree.pos);              generatedType = SCALA_ALLREF            case _ =>              ctx.bb.emit(CONSTANT(value), tree.pos);              generatedType = toTypeKind(value.tpe)          }          ctx        case Block(stats, expr) =>          ctx.enterScope          var ctx1 = genStat(stats, ctx)          ctx1 = genLoad(expr, ctx1, expectedType)          ctx1.exitScope          ctx1        case Typed(expr, _) =>          genLoad(expr, ctx, expectedType)        case Assign(_, _) =>           generatedType = UNIT          genStat(tree, ctx)        case ArrayValue(tpt @ TypeTree(), elems) =>          var ctx1 = ctx          val elmKind = toTypeKind(tpt.tpe)          generatedType = ARRAY(elmKind)          ctx1.bb.emit(CONSTANT(new Constant(elems.length)), tree.pos)          ctx1.bb.emit(CREATE_ARRAY(elmKind, 1))          // inline array literals          var i = 0          while (i < elems.length) {            ctx1.bb.emit(DUP(generatedType), tree.pos)            ctx1.bb.emit(CONSTANT(new Constant(i)))            ctx1 = genLoad(elems(i), ctx1, elmKind)            ctx1.bb.emit(STORE_ARRAY_ITEM(elmKind))            i = i + 1          }          ctx1        case Match(selector, cases) =>          if (settings.debug.value)            log("Generating SWITCH statement.");          var ctx1 = genLoad(selector, ctx, INT)          val afterCtx = ctx1.newBlock          var caseCtx: Context  = null          generatedType = toTypeKind(tree.tpe)          var targets: List[BasicBlock] = Nil          var tags: List[Int] = Nil          var default: BasicBlock = afterCtx.bb          for (caze <- cases) caze match {            case CaseDef(Literal(value), EmptyTree, body) =>              tags = value.intValue :: tags              val tmpCtx = ctx1.newBlock              targets = tmpCtx.bb :: targets              caseCtx = genLoad(body, tmpCtx , generatedType)              caseCtx.bb.emit(JUMP(afterCtx.bb), caze.pos)              caseCtx.bb.close            case CaseDef(Ident(nme.WILDCARD), EmptyTree, body) =>              val tmpCtx = ctx1.newBlock              default = tmpCtx.bb              caseCtx = genLoad(body, tmpCtx , generatedType)              caseCtx.bb.emit(JUMP(afterCtx.bb), caze.pos)

⌨️ 快捷键说明

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