Move PromisedValue to a separate file

This commit is contained in:
pyos
2019-04-04 14:08:17 +02:00
committed by max-kammerer
parent e249c3c594
commit 96e2eb6fa1
2 changed files with 80 additions and 70 deletions
@@ -100,73 +100,6 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label)
// A value that may not have been fully constructed yet. The ability to "roll back" code generation
// is useful for certain optimizations.
abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type) {
// If this value is immaterial, construct an object on the top of the stack. This
// must always be done before generating other values or emitting raw bytecode.
abstract fun materialize()
}
// A value that *has* been fully constructed.
class MaterialValue(codegen: ExpressionCodegen, type: Type) : PromisedValue(codegen, type) {
override fun materialize() {}
}
// A value that can be branched on. JVM has certain branching instructions which can be used
// to optimize these.
abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, Type.BOOLEAN_TYPE) {
abstract fun jumpIfFalse(target: Label)
abstract fun jumpIfTrue(target: Label)
override fun materialize() {
val const0 = Label()
val end = Label()
jumpIfFalse(const0)
codegen.mv.iconst(1)
codegen.mv.goTo(end)
codegen.mv.mark(const0)
codegen.mv.iconst(0)
codegen.mv.mark(end)
}
}
// Same as materialize(), but return a representation of the result.
val PromisedValue.materialized: MaterialValue
get() {
materialize()
return MaterialValue(codegen, type)
}
// Materialize and disregard this value. Materialization is forced because, presumably,
// we only wanted the side effects anyway.
fun PromisedValue.discard(): MaterialValue {
materialize()
if (type !== Type.VOID_TYPE)
AsmUtil.pop(codegen.mv, type)
return MaterialValue(codegen, Type.VOID_TYPE)
}
// On materialization, cast the value to a different type.
fun PromisedValue.coerce(target: Type) = when (target) {
Type.VOID_TYPE -> discard()
type -> this
else -> object : PromisedValue(codegen, target) {
// TODO remove dependency
override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, codegen.mv)
}
}
// Same as above, but with a return type that allows conditional jumping.
fun PromisedValue.coerceToBoolean() = when (val coerced = coerce(Type.BOOLEAN_TYPE)) {
is BooleanValue -> coerced
else -> object : BooleanValue(codegen) {
override fun jumpIfFalse(target: Label) = coerced.materialize().also { codegen.mv.ifeq(target) }
override fun jumpIfTrue(target: Label) = coerced.materialize().also { codegen.mv.ifne(target) }
override fun materialize() = coerced.materialize()
}
}
class ExpressionCodegen(
val irFunction: IrFunction,
val frame: IrFrameMap,
@@ -212,9 +145,6 @@ class ExpressionCodegen(
val IrExpression.onStack: MaterialValue
get() = MaterialValue(this@ExpressionCodegen, asmType)
val voidValue: MaterialValue
get() = MaterialValue(this@ExpressionCodegen, Type.VOID_TYPE)
private fun markNewLabel() = Label().apply { mv.visitLabel(this) }
private fun IrElement.markLineNumber(startOffset: Boolean) {
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
// A value that may not have been fully constructed yet. The ability to "roll back" code generation
// is useful for certain optimizations.
abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type) {
// If this value is immaterial, construct an object on the top of the stack. This
// must always be done before generating other values or emitting raw bytecode.
abstract fun materialize()
}
// A value that *has* been fully constructed.
class MaterialValue(codegen: ExpressionCodegen, type: Type) : PromisedValue(codegen, type) {
override fun materialize() {}
}
// A value that can be branched on. JVM has certain branching instructions which can be used
// to optimize these.
abstract class BooleanValue(codegen: ExpressionCodegen) : PromisedValue(codegen, Type.BOOLEAN_TYPE) {
abstract fun jumpIfFalse(target: Label)
abstract fun jumpIfTrue(target: Label)
override fun materialize() {
val const0 = Label()
val end = Label()
jumpIfFalse(const0)
codegen.mv.iconst(1)
codegen.mv.goTo(end)
codegen.mv.mark(const0)
codegen.mv.iconst(0)
codegen.mv.mark(end)
}
}
// Same as materialize(), but return a representation of the result.
val PromisedValue.materialized: MaterialValue
get() {
materialize()
return MaterialValue(codegen, type)
}
// Materialize and disregard this value. Materialization is forced because, presumably,
// we only wanted the side effects anyway.
fun PromisedValue.discard(): MaterialValue {
materialize()
if (type !== Type.VOID_TYPE)
AsmUtil.pop(codegen.mv, type)
return MaterialValue(codegen, Type.VOID_TYPE)
}
// On materialization, cast the value to a different type.
fun PromisedValue.coerce(target: Type) = when (target) {
type -> this
else -> object : PromisedValue(codegen, target) {
// TODO remove dependency
override fun materialize() = StackValue.coerce(this@coerce.materialized.type, type, codegen.mv)
}
}
// Same as above, but with a return type that allows conditional jumping.
fun PromisedValue.coerceToBoolean() = when (val coerced = coerce(Type.BOOLEAN_TYPE)) {
is BooleanValue -> coerced
else -> object : BooleanValue(codegen) {
override fun jumpIfFalse(target: Label) = coerced.materialize().also { codegen.mv.ifeq(target) }
override fun jumpIfTrue(target: Label) = coerced.materialize().also { codegen.mv.ifne(target) }
override fun materialize() = coerced.materialize()
}
}
val ExpressionCodegen.voidValue: MaterialValue
get() = MaterialValue(this, Type.VOID_TYPE)