Skip to content

Commit

Permalink
Ensure EtsIR is more three-address-like (#245)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lipen authored Aug 2, 2024
1 parent 864759b commit 4164b3c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 37 deletions.
62 changes: 29 additions & 33 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.jacodb.ets.base.EtsDivExpr
import org.jacodb.ets.base.EtsEntity
import org.jacodb.ets.base.EtsEqExpr
import org.jacodb.ets.base.EtsExpExpr
import org.jacodb.ets.base.EtsExpr
import org.jacodb.ets.base.EtsFieldRef
import org.jacodb.ets.base.EtsGotoStmt
import org.jacodb.ets.base.EtsGtEqExpr
Expand Down Expand Up @@ -126,7 +127,12 @@ class EtsMethodBuilder(
val etsMethod = EtsMethodImpl(signature, localsCount, modifiers)

private val currentStmts: MutableList<EtsStmt> = mutableListOf()
private var freeLocal: Int = 0

private var freeTempLocal: Int = 0

private fun newTempLocal(type: EtsType): EtsLocal {
return EtsLocal("_tmp${freeTempLocal++}", type)
}

private fun loc(): EtsInstLocation {
return EtsInstLocation(etsMethod, currentStmts.size)
Expand All @@ -142,6 +148,24 @@ class EtsMethodBuilder(
return etsMethod
}

private fun ensureOneAddress(entity: EtsEntity): EtsValue {
// TODO: think about whether 'CastExpr' should be considered "one-address". This would require changing the return type of this function to `EtsEntity`.
// if (entity is EtsCastExpr) return entity

if (entity is EtsExpr || entity is EtsFieldRef || entity is EtsArrayAccess) {
val newLocal = newTempLocal(entity.type)
currentStmts += EtsAssignStmt(
location = loc(),
lhv = newLocal,
rhv = entity,
)
return newLocal
} else {
check(entity is EtsValue)
return entity
}
}

fun convertToEtsStmt(stmt: StmtDto): EtsStmt {
return when (stmt) {
is UnknownStmtDto -> object : EtsStmt {
Expand All @@ -161,7 +185,7 @@ class EtsMethodBuilder(
is AssignStmtDto -> EtsAssignStmt(
location = loc(),
lhv = convertToEtsEntity(stmt.left) as EtsValue,
rhv = convertToEtsEntity(stmt.right),
rhv = ensureOneAddress(convertToEtsEntity(stmt.right)),
)

is CallStmtDto -> EtsCallStmt(
Expand All @@ -170,21 +194,9 @@ class EtsMethodBuilder(
)

is ReturnStmtDto -> {
val etsEntity = convertToEtsEntity(stmt.arg)
val etsValue = if (etsEntity is EtsValue) {
etsEntity
} else {
val newLocal = EtsLocal("_tmp${freeLocal++}", EtsUnknownType)
currentStmts += EtsAssignStmt(
location = loc(),
lhv = newLocal,
rhv = etsEntity,
)
newLocal
}
EtsReturnStmt(
location = loc(),
returnValue = etsValue,
returnValue = ensureOneAddress(convertToEtsEntity(stmt.arg)),
)
}

Expand Down Expand Up @@ -353,30 +365,14 @@ class EtsMethodBuilder(
instance = convertToEtsEntity(value.instance),
method = convertToEtsMethodSignature(value.method),
args = value.args.map {
val etsEntity = convertToEtsEntity(it)
if (etsEntity is EtsValue) return@map etsEntity
val newLocal = EtsLocal("_tmp${freeLocal++}", EtsUnknownType)
currentStmts += EtsAssignStmt(
location = loc(),
lhv = newLocal,
rhv = etsEntity,
)
newLocal
ensureOneAddress(convertToEtsEntity(it))
},
)

is StaticCallExprDto -> EtsStaticCallExpr(
method = convertToEtsMethodSignature(value.method),
args = value.args.map {
val etsEntity = convertToEtsEntity(it)
if (etsEntity is EtsValue) return@map etsEntity
val newLocal = EtsLocal("_tmp${freeLocal++}", EtsUnknownType)
currentStmts += EtsAssignStmt(
location = loc(),
lhv = newLocal,
rhv = etsEntity,
)
newLocal
ensureOneAddress(convertToEtsEntity(it))
},
)

Expand Down
8 changes: 4 additions & 4 deletions jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFileTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ class EtsFileTest {
fun `test etsFile on TypeMismatch`() {
val etsFile = load("etsir/samples/TypeMismatch")
etsFile.classes.forEach { cls ->
cls.methods.forEach { etsMethod ->
when (etsMethod.name) {
cls.methods.forEach { method ->
when (method.name) {
"add" -> {
Assertions.assertEquals(9, etsMethod.cfg.instructions.size)
Assertions.assertEquals(11, method.cfg.instructions.size)
}

"main" -> {
Assertions.assertEquals(4, etsMethod.cfg.instructions.size)
Assertions.assertEquals(5, method.cfg.instructions.size)
}
}
}
Expand Down

0 comments on commit 4164b3c

Please sign in to comment.