From adb9706f4f7e7344da8ea076847297e580e87596 Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Mon, 18 Aug 2025 16:23:11 +0300 Subject: [PATCH 1/2] Add method body with cfg and locals --- .../main/kotlin/org/jacodb/ets/dto/Convert.kt | 14 ++++++++--- .../kotlin/org/jacodb/ets/model/Method.kt | 25 +++++++++++++++---- .../org/jacodb/ets/test/EtsCfgDslTest.kt | 2 +- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt index a56c44ccc..0cc797562 100644 --- a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt +++ b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt @@ -143,15 +143,22 @@ class EtsMethodBuilder( typeParameters: List = emptyList(), modifiers: EtsModifiers = EtsModifiers.EMPTY, decorators: List = emptyList(), + locals: List = emptyList(), ) { - private val method = EtsMethodImpl(signature, typeParameters, modifiers, decorators) + private val locals = locals.toMutableList() + + private val method = EtsMethodImpl(signature, typeParameters, modifiers, decorators).also { + it.body.locals = this.locals + } private lateinit var currentStmts: MutableList private var freeTempLocal: Int = 0 private fun newTempLocal(): EtsLocal { - return EtsLocal("_tmp${freeTempLocal++}") + val local = EtsLocal("_tmp${freeTempLocal++}") + this@EtsMethodBuilder.locals += local + return local } private fun loc(): EtsStmtLocation { @@ -163,7 +170,7 @@ class EtsMethodBuilder( fun build(cfgDto: CfgDto): EtsMethod { require(!built) { "Method has already been built" } val cfg = cfgDto.toEtsCfg() - method._cfg = cfg + method.body.cfg = cfg built = true return method } @@ -682,6 +689,7 @@ fun MethodDto.toEtsMethod(): EtsMethod { typeParameters = typeParameters, modifiers = modifiers, decorators = decorators, + locals = body.locals.map { it.toEtsLocal() }, ) return builder.build(body.cfg) } else { diff --git a/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Method.kt b/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Method.kt index 0697dbd09..ecc17848e 100644 --- a/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Method.kt +++ b/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Method.kt @@ -23,7 +23,7 @@ import org.jacodb.api.common.CommonMethod interface EtsMethod : Base, CommonMethod { val signature: EtsMethodSignature val typeParameters: List - val cfg: EtsBlockCfg + val body: EtsMethodBody val enclosingClass: EtsClass? @@ -36,21 +36,36 @@ interface EtsMethod : Base, CommonMethod { override val returnType: EtsType get() = signature.returnType + val cfg: EtsBlockCfg + get() = body.cfg + + val locals: List + get() = body.locals + override fun flowGraph(): EtsBytecodeGraph { return cfg } } +class EtsMethodBody( + var cfg: EtsBlockCfg = EtsBlockCfg.EMPTY, + var locals: List = emptyList(), +) + class EtsMethodImpl( override val signature: EtsMethodSignature, override val typeParameters: List = emptyList(), override val modifiers: EtsModifiers = EtsModifiers.EMPTY, override val decorators: List = emptyList(), ) : EtsMethod { - var _cfg: EtsBlockCfg? = null - - override val cfg: EtsBlockCfg - get() = _cfg ?: EtsBlockCfg.EMPTY + override val body: EtsMethodBody = EtsMethodBody() + + @Deprecated("Use body.cfg instead", ReplaceWith("body.cfg")) + var _cfg: EtsBlockCfg + get() = body.cfg + set(value) { + body.cfg = value + } override var enclosingClass: EtsClass? = null diff --git a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt index dea711876..28a825c3d 100644 --- a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt +++ b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt @@ -79,6 +79,6 @@ class EtsCfgDslTest { val etsCfg = etsBlockCfg.linearize() println("etsCfg:\n${etsCfg.toDot()}") - method._cfg = etsBlockCfg + method.body.cfg = etsBlockCfg } } From acfc88051d9dbbfd036a0993a28b05819a059b5d Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Tue, 19 Aug 2025 15:39:31 +0300 Subject: [PATCH 2/2] Set locals --- .../kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt index 28a825c3d..32ccca607 100644 --- a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt +++ b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsCfgDslTest.kt @@ -24,8 +24,10 @@ import org.jacodb.ets.dsl.param import org.jacodb.ets.dsl.program import org.jacodb.ets.dsl.toBlockCfg import org.jacodb.ets.dsl.toDot +import org.jacodb.ets.model.EtsAssignStmt import org.jacodb.ets.model.EtsClassSignature import org.jacodb.ets.model.EtsFileSignature +import org.jacodb.ets.model.EtsLocal import org.jacodb.ets.model.EtsMethodImpl import org.jacodb.ets.model.EtsMethodParameter import org.jacodb.ets.model.EtsMethodSignature @@ -35,6 +37,8 @@ import org.jacodb.ets.utils.linearize import org.jacodb.ets.utils.toDot import org.jacodb.ets.utils.toEtsBlockCfg import org.junit.jupiter.api.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals class EtsCfgDslTest { @Test @@ -80,5 +84,14 @@ class EtsCfgDslTest { println("etsCfg:\n${etsCfg.toDot()}") method.body.cfg = etsBlockCfg + method.body.locals = etsBlockCfg.stmts + .filterIsInstance() + .mapNotNull { it.lhv as? EtsLocal } + .distinct() + + assertEquals(method.locals, listOf( + EtsLocal("i", EtsUnknownType), + EtsLocal("_tmp0", EtsUnknownType), + )) } }