[Scummvm-cvs-logs] SF.net SVN: scummvm:[51960] tools/branches/gsoc2010-decompiler/decompiler/ kyra

pidgeot at users.sourceforge.net pidgeot at users.sourceforge.net
Wed Aug 11 00:18:53 CEST 2010


Revision: 51960
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51960&view=rev
Author:   pidgeot
Date:     2010-08-10 22:18:51 +0000 (Tue, 10 Aug 2010)

Log Message:
-----------
DECOMPILER: Proper support for Kyra return values
as parameters and in conditions

Modified Paths:
--------------
    tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp
    tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h

Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp	2010-08-10 20:54:02 UTC (rev 51959)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.cpp	2010-08-10 22:18:51 UTC (rev 51960)
@@ -40,7 +40,9 @@
 	case kLoad:
 		switch (inst._opcode) {
 		case 2:
-			_stack.push(new VarEntry("retval"));
+			// If something has been called previously in this group, don't output retval variable
+			if (inst._address <= findFirstCall()._address)
+				_stack.push(new VarEntry("retval"));
 			break;
 		case 3:
 		case 4:
@@ -141,7 +143,10 @@
 			for (size_t i = 0; i < f._metadata.length(); i++)
 				processSpecialMetadata(inst, f._metadata[i]);
 			_stack.push(new CallEntry(f._name, _argList));
-			if (!f._retVal) {
+			// Leave call on stack if this is a condition, or other calls follow in same group
+			if (_curGroup->_type == kIfCond || _curGroup->_type == kWhileCond || _curGroup->_type == kDoWhileCond || inst._address != findLastCall()._address) {
+				break;
+			}	else if (!f._retVal) {
 				std::stringstream stream;
 				stream << _stack.pop() << ";";
 				addOutputLine(stream.str());
@@ -153,7 +158,7 @@
 		}
 	case kSpecial:
 		{
-			if (inst._opcode == 2)
+			if (inst._opcode != 14)
 				return;
 			_argList.clear();
 			bool returnsValue = (inst._codeGenData.find("r") == 1);
@@ -161,7 +166,10 @@
 			for (size_t i = 0; i < metadata.length(); i++)
 				processSpecialMetadata(inst, metadata[i]);
 			_stack.push(new CallEntry(inst._name, _argList));
-			if (!returnsValue) {
+			// Leave call on stack if this is a condition, or other calls follow in same group
+			if (_curGroup->_type == kIfCond || _curGroup->_type == kWhileCond || _curGroup->_type == kDoWhileCond || inst._address != findLastCall()._address) {
+				break;
+			}	else if (!returnsValue) {
 				std::stringstream stream;
 				stream << _stack.pop() << ";";
 				addOutputLine(stream.str());
@@ -181,6 +189,26 @@
 	}
 }
 
+const Instruction &Kyra::CodeGenerator::findFirstCall() {
+	ConstInstIterator it = _curGroup->_start;
+	do {
+		if (it->_type == kCall || (it->_type == kSpecial && it->_opcode == 14))
+			return *it;
+	} while (it++ != _curGroup->_end);
+
+	return *_curGroup->_start;
+}
+
+const Instruction &Kyra::CodeGenerator::findLastCall() {
+	ConstInstIterator it = _curGroup->_end;
+	do {
+		if (it->_type == kCall || (it->_type == kSpecial && it->_opcode == 14))
+			return *it;
+	} while (it-- != _curGroup->_start);
+
+	return *_curGroup->_end;
+}
+
 void Kyra::CodeGenerator::processSpecialMetadata(const Instruction inst, char c) {
 	switch (c) {
 	case '0':

Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h	2010-08-10 20:54:02 UTC (rev 51959)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/codegen.h	2010-08-10 22:18:51 UTC (rev 51960)
@@ -33,6 +33,24 @@
 class CodeGenerator : public ::CodeGenerator {
 private:
 	int _stackOffset; ///< Running count of where in the stack to look for the next argument.
+
+	/**
+	 * Finds the first call instruction in the current group and returns it.
+	 * The call may either be a kCall or kSpecial.
+	 * Used to check whether retVal should be output by pushRet.
+	 *
+	 * @return The first call instruction in the current group. If no calls are found, returns the first instruction.
+	 */
+	const Instruction &findFirstCall();
+
+	/**
+	 * Finds the last call instruction in the current group and returns it.
+	 * The call may either be a kCall or kSpecial.
+	 * Used to check whether retVal should be output by calls.
+	 *
+	 * @return The last call instruction in the current group. If no calls are found, returns the last instruction.
+	 */
+	const Instruction &findLastCall();
 public:
 	/**
 	 * Constructor for Kyra::CodeGenerator.


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