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