[Scummvm-cvs-logs] SF.net SVN: scummvm:[49954] tools/branches/gsoc2010-decompiler/decompiler
pidgeot at users.sourceforge.net
pidgeot at users.sourceforge.net
Fri Jun 18 00:12:38 CEST 2010
Revision: 49954
http://scummvm.svn.sourceforge.net/scummvm/?rev=49954&view=rev
Author: pidgeot
Date: 2010-06-17 22:12:38 +0000 (Thu, 17 Jun 2010)
Log Message:
-----------
Add some test cases for CFG generation and SCUMMv6 _stackChange fixup
Modified Paths:
--------------
tools/branches/gsoc2010-decompiler/decompiler/control_flow.h
tools/branches/gsoc2010-decompiler/decompiler/graph.h
tools/branches/gsoc2010-decompiler/decompiler/test/disassembler_test.h
tools/branches/gsoc2010-decompiler/decompiler/test/module.mk
Added Paths:
-----------
tools/branches/gsoc2010-decompiler/decompiler/test/branches.dmp
tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
tools/branches/gsoc2010-decompiler/decompiler/test/unreachable.dmp
Modified: tools/branches/gsoc2010-decompiler/decompiler/control_flow.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/control_flow.h 2010-06-17 22:08:07 UTC (rev 49953)
+++ tools/branches/gsoc2010-decompiler/decompiler/control_flow.h 2010-06-17 22:12:38 UTC (rev 49954)
@@ -37,32 +37,32 @@
std::map<uint32, GraphVertex> _addrMap; ///< Map between addresses and vertices.
/**
- * Find a graph vertex through an instruction.
+ * Finds a graph vertex through an instruction.
* @param inst The instruction to find the vertex for.
*/
GraphVertex find(Instruction inst);
/**
- * Find a graph vertex through an instruction iterator.
+ * Finds a graph vertex through an instruction iterator.
* @param it The iterator to find the vertex for.
*/
GraphVertex find(InstIterator it);
/**
- * Find a graph vertex through an address.
+ * Finds a graph vertex through an address.
* @param address The address to find the vertex for.
*/
GraphVertex find(uint32 address);
/**
- * Merge two graph vertices. g2 will be merged into g1.
+ * Merges two graph vertices. g2 will be merged into g1.
* @param g1 The first vertex to merge.
* @param g2 The second vertex to merge.
*/
void merge(GraphVertex g1, GraphVertex g2);
/**
- * Set the stack level for all instructions, using depth-first search.
+ * Sets the stack level for all instructions, using depth-first search.
* @param g The GraphVertex to search from.
* @param level The stack level when g is reached.
*/
@@ -70,6 +70,12 @@
public:
/**
+ * Gets the current control flow graph.
+ * @returns The current control flow graph.
+ */
+ const Graph &getGraph() { return _g; };
+
+ /**
* Constructor for the control flow graph.
* @param insts std::vector containing the instructions to analyze control flow for.
* @param engine Pointer to the Engine used for the script.
Modified: tools/branches/gsoc2010-decompiler/decompiler/graph.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/graph.h 2010-06-17 22:08:07 UTC (rev 49953)
+++ tools/branches/gsoc2010-decompiler/decompiler/graph.h 2010-06-17 22:12:38 UTC (rev 49954)
@@ -90,14 +90,15 @@
}
};
-typedef boost::property<boost::vertex_name_t, Group> GroupProperty; ///< Type representing properties containing a Group.
-typedef boost::property<boost::vertex_index_t, int, GroupProperty> GraphProperty; ///< Type representing properties containing an index, followed by a GroupProperty.
+typedef boost::property<boost::vertex_name_t, Group> GroupProperty; ///< Type representing properties containing a Group.
+typedef boost::property<boost::vertex_index_t, int, GroupProperty> GraphProperty; ///< Type representing properties containing an index, followed by a GroupProperty.
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::bidirectionalS, GraphProperty> Graph; ///< Type used for the code flow graph.
-typedef Graph::vertex_descriptor GraphVertex; ///< Type representing a vertex in the graph.
-typedef Graph::edge_descriptor GraphEdge; ///< Type representing an edge in the graph.
-typedef Graph::out_edge_iterator OutEdgeIterator; ///< Type representing an iterator for outgoing edges.
-typedef Graph::in_edge_iterator InEdgeIterator; ///< Type representing an iterator for ingoing edges.
-typedef std::pair<OutEdgeIterator, OutEdgeIterator> EdgeRange; ///< Type representing a range of edges from boost::out_edges.
+typedef Graph::vertex_descriptor GraphVertex; ///< Type representing a vertex in the graph.
+typedef Graph::vertex_iterator VertexIterator; ///< Type representing an iterator for vertices.
+typedef Graph::edge_descriptor GraphEdge; ///< Type representing an edge in the graph.
+typedef Graph::out_edge_iterator OutEdgeIterator; ///< Type representing an iterator for outgoing edges.
+typedef Graph::in_edge_iterator InEdgeIterator; ///< Type representing an iterator for ingoing edges.
+typedef std::pair<OutEdgeIterator, OutEdgeIterator> EdgeRange; ///< Type representing a range of edges from boost::out_edges.
/**
* Type used to set properties for dot output.
Added: tools/branches/gsoc2010-decompiler/decompiler/test/branches.dmp
===================================================================
(Binary files differ)
Property changes on: tools/branches/gsoc2010-decompiler/decompiler/test/branches.dmp
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h (rev 0)
+++ tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h 2010-06-17 22:12:38 UTC (rev 49954)
@@ -0,0 +1,116 @@
+/* ScummVM Tools
+ * Copyright (C) 2010 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include <cxxtest/TestSuite.h>
+
+#include "decompiler/control_flow.h"
+#include "decompiler/disassembler.h"
+#include "decompiler/graph.h"
+#include "decompiler/scummv6/engine.h"
+
+#include <vector>
+#define GET(vertex) (boost::get(boost::vertex_name, g, vertex))
+
+class CFGTestSuite : public CxxTest::TestSuite {
+public:
+ void testUnreachable() {
+ Scumm::v6::Engine* engine = new Scumm::v6::Engine();
+ Disassembler *d = engine->getDisassembler();
+ d->open("decompiler/test/unreachable.dmp");
+ std::vector<Instruction> insts = d->disassemble();
+ delete d;
+ ControlFlow* c = new ControlFlow(insts, engine);
+ Graph g = c->getGraph();
+ TS_ASSERT(boost::num_vertices(g) == 4);
+ std::pair<VertexIterator, VertexIterator> range = boost::vertices(g);
+ VertexIterator it = range.first;
+ Group gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 0);
+ TS_ASSERT(boost::in_degree(*it, g) == 0 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 2);
+ TS_ASSERT(boost::in_degree(*it, g) == 1 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 5);
+ TS_ASSERT(boost::in_degree(*it, g) == 0 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 6);
+ TS_ASSERT(boost::in_degree(*it, g) == 2 && boost::out_degree(*it, g) == 0);
+ };
+
+ void testBranching() {
+ Scumm::v6::Engine* engine = new Scumm::v6::Engine();
+ Disassembler *d = engine->getDisassembler();
+ d->open("decompiler/test/branches.dmp");
+ std::vector<Instruction> insts = d->disassemble();
+ delete d;
+ ControlFlow* c = new ControlFlow(insts, engine);
+ Graph g = c->getGraph();
+ TS_ASSERT(boost::num_vertices(g) == 4);
+ std::pair<VertexIterator, VertexIterator> range = boost::vertices(g);
+ VertexIterator it = range.first;
+ Group gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 0);
+ TS_ASSERT(boost::in_degree(*it, g) == 0 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 2);
+ TS_ASSERT(boost::in_degree(*it, g) == 1 && boost::out_degree(*it, g) == 2);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 5);
+ TS_ASSERT(boost::in_degree(*it, g) == 1 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 6);
+ TS_ASSERT(boost::in_degree(*it, g) == 2 && boost::out_degree(*it, g) == 0);
+ }
+
+ void testGrouping() {
+ Scumm::v6::Engine* engine = new Scumm::v6::Engine();
+ Disassembler *d = engine->getDisassembler();
+ d->open("decompiler/test/branches.dmp");
+ std::vector<Instruction> insts = d->disassemble();
+ delete d;
+ ControlFlow* c = new ControlFlow(insts, engine);
+ c->createGroups();
+ Graph g = c->getGraph();
+ TS_ASSERT(boost::num_vertices(g) == 3);
+ std::pair<VertexIterator, VertexIterator> range = boost::vertices(g);
+ VertexIterator it = range.first;
+ Group gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 0);
+ TS_ASSERT(gr._end->_address == 2);
+ TS_ASSERT(boost::in_degree(*it, g) == 0 && boost::out_degree(*it, g) == 2);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 5);
+ TS_ASSERT(boost::in_degree(*it, g) == 1 && boost::out_degree(*it, g) == 1);
+ ++it;
+ gr = GET(*it);
+ TS_ASSERT(gr._start->_address == 6);
+ TS_ASSERT(boost::in_degree(*it, g) == 2 && boost::out_degree(*it, g) == 0);
+ }
+};
Property changes on: tools/branches/gsoc2010-decompiler/decompiler/test/cfg_test.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: tools/branches/gsoc2010-decompiler/decompiler/test/disassembler_test.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/test/disassembler_test.h 2010-06-17 22:08:07 UTC (rev 49953)
+++ tools/branches/gsoc2010-decompiler/decompiler/test/disassembler_test.h 2010-06-17 22:12:38 UTC (rev 49954)
@@ -71,7 +71,7 @@
}
}
- //This test requires global script 15 from Sam & Max: Hit The Road.
+ //This test requires script-15.dmp from Sam & Max: Hit The Road.
//1ab08298c9c8fb4c77953756989c7449 *script-15.dmp
void testScummv6DisassemblerScript15() {
try {
@@ -79,8 +79,8 @@
s.open("decompiler/test/script-15.dmp");
std::vector<Instruction> insts = s.disassemble();
TS_ASSERT(insts.size() == 11);
- TS_ASSERT(insts[0]._address == 0 && insts[0]._name == "pushWordVar" && insts[0]._params[0].getSigned() == 16384);
- TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getSigned() == 197);
+ TS_ASSERT(insts[0]._address == 0 && insts[0]._name == "pushWordVar" && insts[0]._params[0].getUnsigned() == 16384);
+ TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getUnsigned() == 197);
TS_ASSERT(insts[2]._address == 6 && insts[2]._name == "pushWord" && insts[2]._params[0].getSigned() == 0);
TS_ASSERT(insts[3]._address == 9 && insts[3]._name == "pushWord" && insts[3]._params[0].getSigned() == 11);
TS_ASSERT(insts[4]._address == 12 && insts[4]._name == "pushWord" && insts[4]._params[0].getSigned() == 0);
@@ -95,7 +95,7 @@
}
}
- //This test requires global script 31 from Sam & Max: Hit The Road.
+ //This test requires script-31.dmp from Sam & Max: Hit The Road.
//f75f7ce110f378735d449f8eeb4a68e5 *script-31.dmp
void testScummv6DisassemblerScript31() {
try {
@@ -104,16 +104,16 @@
std::vector<Instruction> insts = s.disassemble();
TS_ASSERT(insts.size() == 5);
TS_ASSERT(insts[0]._address == 0 && insts[0]._name == "pushWord" && insts[0]._params[0].getSigned() == 0);
- TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getSigned() == 180);
+ TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getUnsigned() == 180);
TS_ASSERT(insts[2]._address == 6 && insts[2]._name == "pushWord" && insts[2]._params[0].getSigned() == 0);
- TS_ASSERT(insts[3]._address == 9 && insts[3]._name == "writeWordVar" && insts[3]._params[0].getSigned() == 181);
+ TS_ASSERT(insts[3]._address == 9 && insts[3]._name == "writeWordVar" && insts[3]._params[0].getUnsigned() == 181);
TS_ASSERT(insts[4]._address == 12 && insts[4]._name == "stopObjectCodeB");
} catch (...) {
TS_ASSERT(false);
}
}
- //This test requires global script 33 from Sam & Max: Hit The Road.
+ //This test requires script-33.dmp from Sam & Max: Hit The Road.
//9f09418bf34abbdec0ec54f388d8dca4 *script-33.dmp
void testScummv6DisassemblerScript33() {
try {
@@ -122,12 +122,12 @@
std::vector<Instruction> insts = s.disassemble();
TS_ASSERT(insts.size() == 10);
TS_ASSERT(insts[0]._address == 0 && insts[0]._name == "pushWord" && insts[0]._params[0].getSigned() == 0);
- TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getSigned() == 71);
- TS_ASSERT(insts[2]._address == 6 && insts[2]._name == "pushWordVar" && insts[2]._params[0].getSigned() == 177);
- TS_ASSERT(insts[3]._address == 9 && insts[3]._name == "writeWordVar" && insts[3]._params[0].getSigned() == 173);
+ TS_ASSERT(insts[1]._address == 3 && insts[1]._name == "writeWordVar" && insts[1]._params[0].getUnsigned() == 71);
+ TS_ASSERT(insts[2]._address == 6 && insts[2]._name == "pushWordVar" && insts[2]._params[0].getUnsigned() == 177);
+ TS_ASSERT(insts[3]._address == 9 && insts[3]._name == "writeWordVar" && insts[3]._params[0].getUnsigned() == 173);
TS_ASSERT(insts[4]._address == 12 && insts[4]._name == "pushWord" && insts[4]._params[0].getSigned() == 874);
- TS_ASSERT(insts[5]._address == 15 && insts[5]._name == "writeWordVar" && insts[5]._params[0].getSigned() == 177);
- TS_ASSERT(insts[6]._address == 18 && insts[6]._name == "pushWordVar" && insts[6]._params[0].getSigned() == 177);
+ TS_ASSERT(insts[5]._address == 15 && insts[5]._name == "writeWordVar" && insts[5]._params[0].getUnsigned() == 177);
+ TS_ASSERT(insts[6]._address == 18 && insts[6]._name == "pushWordVar" && insts[6]._params[0].getUnsigned() == 177);
TS_ASSERT(insts[7]._address == 21 && insts[7]._name == "pushWord" && insts[7]._params[0].getSigned() == 93);
TS_ASSERT(insts[8]._address == 24 && insts[8]._name == "cursorCmd_Image");
TS_ASSERT(insts[9]._address == 26 && insts[9]._name == "stopObjectCodeB");
@@ -135,4 +135,36 @@
TS_ASSERT(false);
}
}
+
+ //This test requires room-9-202.dmp from Sam & Max: Hit The Road.
+ //f010dc659264674a2b6da298acd0b88b *room-9-202.dmp
+ void testScummv6StackChangeFixRoom9202() {
+ try
+ {
+ Scumm::v6::Disassembler s;
+ s.open("decompiler/test/room-9-202.dmp");
+ std::vector<Instruction> insts = s.disassemble();
+ InstIterator it = insts.end();
+ it -= 8;
+ TS_ASSERT(it->_stackChange == -3);
+ } catch (...) {
+ TS_ASSERT(false);
+ }
+ }
+
+ //This test requires script-30.dmp from Sam & Max: Hit The Road.
+ //6e48faca13e1f6df9341567608962744 *script-30.dmp
+ void testScummv6StackChangeFixScript30() {
+ try
+ {
+ Scumm::v6::Disassembler s;
+ s.open("decompiler/test/script-30.dmp");
+ std::vector<Instruction> insts = s.disassemble();
+ InstIterator it = insts.end();
+ it -= 3;
+ TS_ASSERT(it->_stackChange == -6);
+ } catch (...) {
+ TS_ASSERT(false);
+ }
+ }
};
Modified: tools/branches/gsoc2010-decompiler/decompiler/test/module.mk
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/test/module.mk 2010-06-17 22:08:07 UTC (rev 49953)
+++ tools/branches/gsoc2010-decompiler/decompiler/test/module.mk 2010-06-17 22:12:38 UTC (rev 49954)
@@ -8,9 +8,11 @@
TESTS := $(srcdir)/decompiler/test/*.h
TEST_LIBS := \
common/file.o\
+ decompiler/control_flow.o \
decompiler/disassembler.o \
decompiler/simple_disassembler.o \
decompiler/scummv6/disassembler.o \
+ decompiler/scummv6/engine.o \
decompiler/test/disassembler/pasc.o \
decompiler/test/disassembler/subopcode.o \
decompiler/unknown_opcode.o \
Added: tools/branches/gsoc2010-decompiler/decompiler/test/unreachable.dmp
===================================================================
(Binary files differ)
Property changes on: tools/branches/gsoc2010-decompiler/decompiler/test/unreachable.dmp
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
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