[Scummvm-cvs-logs] SF.net SVN: scummvm:[50635] tools/branches/gsoc2010-decompiler/decompiler
pidgeot at users.sourceforge.net
pidgeot at users.sourceforge.net
Sat Jul 3 23:57:56 CEST 2010
Revision: 50635
http://scummvm.svn.sourceforge.net/scummvm/?rev=50635&view=rev
Author: pidgeot
Date: 2010-07-03 21:57:56 +0000 (Sat, 03 Jul 2010)
Log Message:
-----------
Add detection of if and else, including test
Still need to find a proper way of detecting when an else ends
Fix incorrect while detection
Modified Paths:
--------------
tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
tools/branches/gsoc2010-decompiler/decompiler/graph.h
tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
Modified: tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp 2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/control_flow.cpp 2010-07-03 21:57:56 UTC (rev 50635)
@@ -232,12 +232,15 @@
// Undetermined block that ends with conditional jump
if (out_degree(*v, _g) == 2 && gr->_type == kNormal) {
InEdgeRange ier = boost::in_edges(*v, _g);
+ bool isWhile = false;
for (InEdgeIterator e = ier.first; e != ier.second; ++e) {
Group *sourceGr = GET(boost::source(*e, _g));
// Block has ingoing edge from block later in the code that isn't a do-while condition
if (sourceGr->_start->_address > gr->_start->_address && sourceGr->_type != kDoWhileCond)
- gr->_type = kWhileCond;
+ isWhile = true;
}
+ if (isWhile)
+ gr->_type = kWhileCond;
}
}
}
@@ -301,5 +304,35 @@
}
void ControlFlow::detectIf() {
+ VertexRange vr = boost::vertices(_g);
+ for (VertexIterator v = vr.first; v != vr.second; ++v) {
+ Group *gr = GET(*v);
+ // if: Undetermined block with conditional jump
+ if (gr->_type == kNormal && out_degree(*v, _g) == 2) {
+ gr->_type = kIfCond;
+
+ OutEdgeRange oer = boost::out_edges(*v, _g);
+ GraphVertex target;
+ uint32 maxAddress = 0;
+ Group *targetGr;
+ // Find jump target
+ for (OutEdgeIterator oe = oer.first; oe != oer.second; ++oe) {
+ targetGr = GET(boost::target(*oe, _g));
+ if (targetGr->_start->_address > maxAddress) {
+ target = boost::target(*oe, _g);
+ maxAddress = targetGr->_start->_address;
+ }
+ }
+ targetGr = GET(target);
+ // else: Jump target of if immediately preceded by an unconditional jump...
+ if (targetGr->_prev->_end->_type != kJump && targetGr->_prev->_end->_type != kJumpRel)
+ continue;
+ // ...to later in the code
+ OutEdgeIterator toe = boost::out_edges(find(targetGr->_prev->_start->_address), _g).first;
+ Group *targetTargetGr = GET(boost::target(*toe, _g));
+ if (targetTargetGr->_start->_address > targetGr->_prev->_end->_address) {
+ targetGr->_else = true;
+ }
+ }
+ }
}
-
Modified: tools/branches/gsoc2010-decompiler/decompiler/graph.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/graph.h 2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/graph.h 2010-07-03 21:57:56 UTC (rev 50635)
@@ -53,7 +53,7 @@
InstIterator _end; ///< Last instruction in the group.
int _stackLevel; ///< Level of the stack upon entry.
GroupType _type; ///< Type of the group.
- bool _else; ///< Group is start of an else.
+ bool _else; ///< Group is start of an else block.
Group *_prev; ///< Pointer to the previous group, when ordered by address. Used for short-circuit analysis.
Group *_next; ///< Pointer to the next group, when ordered by address.
Modified: tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h 2010-07-03 21:41:08 UTC (rev 50634)
+++ tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h 2010-07-03 21:57:56 UTC (rev 50635)
@@ -280,4 +280,83 @@
delete c;
delete engine;
}
+
+ void testIfDetection() {
+ Scumm::v6::Engine *engine = new Scumm::v6::Engine();
+ Disassembler *d = engine->getDisassembler();
+ d->open("decompiler/test/if.dmp");
+ std::vector<Instruction> insts = d->disassemble();
+ delete d;
+ ControlFlow *c = new ControlFlow(insts, engine);
+ c->createGroups();
+ Graph g = c->analyze();
+ VertexRange range = boost::vertices(g);
+ for (VertexIterator it = range.first; it != range.second; ++it) {
+ Group *gr = GET(*it);
+ if (gr->_start->_address == 0x0)
+ TS_ASSERT(gr->_type == kIfCond);
+ }
+ delete c;
+
+ d = engine->getDisassembler();
+ d->open("decompiler/test/break-do-while.dmp");
+ insts = d->disassemble();
+ delete d;
+ c = new ControlFlow(insts, engine);
+ c->createGroups();
+ g = c->analyze();
+ range = boost::vertices(g);
+ for (VertexIterator it = range.first; it != range.second; ++it) {
+ Group *gr = GET(*it);
+ if (gr->_start->_address == 0x0)
+ TS_ASSERT(gr->_type == kIfCond);
+ }
+ delete c;
+
+ d = engine->getDisassembler();
+ d->open("decompiler/test/break-do-while2.dmp");
+ insts = d->disassemble();
+ delete d;
+ c = new ControlFlow(insts, engine);
+ c->createGroups();
+ g = c->analyze();
+ range = boost::vertices(g);
+ for (VertexIterator it = range.first; it != range.second; ++it) {
+ Group *gr = GET(*it);
+ if (gr->_start->_address == 0x3)
+ TS_ASSERT(gr->_type == kIfCond);
+ }
+ delete c;
+
+ d = engine->getDisassembler();
+ d->open("decompiler/test/continue-do-while.dmp");
+ insts = d->disassemble();
+ delete d;
+ c = new ControlFlow(insts, engine);
+ c->createGroups();
+ g = c->analyze();
+ range = boost::vertices(g);
+ for (VertexIterator it = range.first; it != range.second; ++it) {
+ Group *gr = GET(*it);
+ if (gr->_start->_address == 0x0)
+ TS_ASSERT(gr->_type == kIfCond);
+ }
+ delete c;
+
+ d = engine->getDisassembler();
+ d->open("decompiler/test/continue-do-while2.dmp");
+ insts = d->disassemble();
+ delete d;
+ c = new ControlFlow(insts, engine);
+ c->createGroups();
+ g = c->analyze();
+ range = boost::vertices(g);
+ for (VertexIterator it = range.first; it != range.second; ++it) {
+ Group *gr = GET(*it);
+ if (gr->_start->_address == 0x3)
+ TS_ASSERT(gr->_type == kIfCond);
+ }
+ delete c;
+ delete engine;
+ }
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list