[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