mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 06:39:17 +00:00
STARK: Dont try to visit the same block multiple times when decompiling
Unless the block is trivial. The original compiler seems to reuse "end" commands.
This commit is contained in:
parent
d2f1bb8d80
commit
d523c326c5
@ -307,6 +307,14 @@ CFGCommand *Block::getConditionCommand() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::allowDuplication() const {
|
||||
// Allow simple termination blocks to be duplicated in the decompiled output
|
||||
bool isScriptEnd = !_follower && !_trueBranch && !_falseBranch;
|
||||
bool isShort = _commands.size() < 5;
|
||||
|
||||
return isScriptEnd && isShort;
|
||||
}
|
||||
|
||||
ControlStructure::ControlStructure(ControlStructureType t) :
|
||||
type(t),
|
||||
condition(nullptr),
|
||||
|
@ -87,6 +87,9 @@ public:
|
||||
bool isInfiniteLoopStart() const;
|
||||
void setInfiniteLoopStart(bool infiniteLoopStart);
|
||||
|
||||
/** Can this block appear multiple times in the decompiled output? */
|
||||
bool allowDuplication() const;
|
||||
|
||||
// Graph query methods
|
||||
bool hasPredecessor(Block *predecessor) const;
|
||||
bool hasSuccessor(Block *successor) const;
|
||||
|
@ -290,6 +290,18 @@ void Decompiler::buildASTFromBlock(ASTBlock *parent, Block *block, Block *stopBl
|
||||
stopBlock = block;
|
||||
}
|
||||
|
||||
{
|
||||
bool alreadyVisited = Common::find(_visitedBlocks.begin(), _visitedBlocks.end(), block) != _visitedBlocks.end();
|
||||
if (alreadyVisited && !block->allowDuplication()) {
|
||||
// FIXME: We just return for now when an already visited block is visited again.
|
||||
// Obviously, this leads to invalid decompiled code, which is caught by the verification step.
|
||||
// To fix, either handle the cases leading to multiple visits, or generate gotos.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_visitedBlocks.push_back(block);
|
||||
|
||||
Common::Array<CFGCommand *> commands = block->getLinearCommands();
|
||||
for (uint i = 0; i < commands.size(); i++) {
|
||||
parent->addNode(new ASTCommand(parent, commands[i]));
|
||||
@ -376,7 +388,7 @@ bool Decompiler::verifyCommandInAST(CFGCommand *cfgCommand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (list.size() > 1) {
|
||||
if (list.size() > 1 && !cfgCommand->getBlock()->allowDuplication()) {
|
||||
_error = Common::String::format("Command %d found %d times in the AST", cfgCommand->getIndex(), list.size());
|
||||
return false;
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ private:
|
||||
|
||||
ASTNode *_astHead;
|
||||
Common::Array<Block *> _visitedInfiniteLoopStarts;
|
||||
Common::Array<Block *> _visitedBlocks;
|
||||
};
|
||||
|
||||
} // End of namespace Tools
|
||||
|
Loading…
Reference in New Issue
Block a user