@@ -39,6 +39,52 @@ class RegularNode(
3939
4040}
4141
42+ class BlockEntryNode (
43+ override var prev : CFGNode ? ,
44+ override var next : CFGNode ?
45+ ) : SingleInput, SingleOutput {
46+ override val uuid = UUID .randomUUID().toString().replace(" -" , " " )
47+
48+ override fun equals (other : Any? ): Boolean {
49+ if (this == = other) return true
50+ if (javaClass != other?.javaClass) return false
51+
52+ other as RegularNode
53+
54+ if (uuid != other.uuid) return false
55+
56+ return true
57+ }
58+
59+ override fun hashCode (): Int {
60+ return uuid.hashCode()
61+ }
62+
63+ }
64+
65+ class BlockExitNode (
66+ override var prev : CFGNode ? ,
67+ override var next : CFGNode ?
68+ ) : SingleInput, SingleOutput {
69+ override val uuid = UUID .randomUUID().toString().replace(" -" , " " )
70+
71+ override fun equals (other : Any? ): Boolean {
72+ if (this == = other) return true
73+ if (javaClass != other?.javaClass) return false
74+
75+ other as RegularNode
76+
77+ if (uuid != other.uuid) return false
78+
79+ return true
80+ }
81+
82+ override fun hashCode (): Int {
83+ return uuid.hashCode()
84+ }
85+
86+ }
87+
4288class ConditionalNode (
4389 override var prev : CFGNode ? ,
4490 var truePath : CFGNode ? ,
@@ -428,36 +474,38 @@ fun constructCFG(block: IRBlock?, info: CFGCreationInfo): CFG? {
428474 when {
429475 block == null -> return null
430476 block.fieldDeclarations.isNotEmpty() -> {
477+ val entry = BlockEntryNode (null , null )
478+ var pt: SingleOutput = entry
431479 val fields = block.fieldDeclarations
432- var node = DeclarationNode (null , null , fields[0 ])
433- val entry = node
434- var pt = node
435- for (field in fields.subList(1 , fields.size)) {
436- node = DeclarationNode (null , pt, field)
480+ for (field in fields) {
481+ val node = DeclarationNode (null , pt, field)
437482 pt.next = node
438483 pt = node
439484 }
440- var npt: SingleOutput = pt
485+ var npt = pt
441486 for (statement in block.statements) {
442487 val cfg = constructCFG(statement, info)
443488 npt.next = cfg.entry
444489 cfg.entry.prev = npt
445490 npt = cfg.exit
446491 }
447- return CFG (entry, npt)
492+ val end = BlockExitNode (npt, null )
493+ npt.next = end
494+ return CFG (entry, end)
448495 }
449496 block.statements.isNotEmpty() -> {
497+ val entry = BlockEntryNode (null , null )
498+ var pt = entry as SingleOutput
450499 val statements = block.statements
451- var cfg = constructCFG(statements[0 ], info)
452- val entry = cfg.entry
453- var pt = cfg.exit
454- for (statement in statements.subList(1 , statements.size)) {
455- cfg = constructCFG(statement, info)
500+ for (statement in statements) {
501+ val cfg = constructCFG(statement, info)
456502 pt.next = cfg.entry
457503 cfg.entry.prev = pt
458504 pt = cfg.exit
459505 }
460- return CFG (entry, pt)
506+ val end = BlockExitNode (pt, null )
507+ pt.next = end
508+ return CFG (entry, end)
461509 }
462510 else -> return null
463511 }
@@ -529,6 +577,8 @@ private fun cfgNodeLabel(node: CFGNode): String {
529577 is DeclarationNode -> irToString(node.declaration)
530578 is EntryNoOpNode -> " Xin"
531579 is ExitNoOpNode -> " Xout"
580+ is BlockEntryNode -> " ENTER"
581+ is BlockExitNode -> " EXIT"
532582 else -> throw IllegalArgumentException (" I don't know this variant of node" )
533583 }
534584}
@@ -545,7 +595,7 @@ fun dotFileFromCFG(cfg: CFG): String {
545595 if (label.last() == ' \n ' ) label = label.removeRange(label.length - 1 , label.length)
546596 label = label.replace(" \" " , " \\\" " )
547597 val shape = when (node) {
548- is RegularNode , is DeclarationNode -> " box"
598+ is RegularNode , is DeclarationNode , is BlockEntryNode , is BlockExitNode -> " box"
549599 is ConditionalNode -> " diamond"
550600 is BreakNode , is ContinueNode , is ReturnNode -> " parallelogram"
551601 is NoOpNode -> " circle"
0 commit comments