فهرست منبع

Function and Engine refactored.

Iñigo Valentin 3 سال پیش
والد
کامیت
47e8075a81

+ 0 - 1
V-Gears-Installer/CMakeLists.txt

@@ -90,7 +90,6 @@ set(SOURCE_FILES
     src/decompiler/ControlFlow.cpp
     src/decompiler/Disassembler.cpp
     src/decompiler/Engine.cpp
-    src/decompiler/Function.cpp
     src/decompiler/graph.cpp
     src/decompiler/instruction.cpp
     src/decompiler/simple_disassembler.cpp

+ 41 - 32
V-Gears-Installer/include/decompiler/Engine.h

@@ -31,83 +31,92 @@ typedef std::map<uint32, Function> FuncMap;
  * Base class for engines.
  */
 class Engine {
+
     public:
 
         virtual ~Engine() = default;
 
-        virtual std::unique_ptr<Disassembler> GetDisassembler(InstVec &, const std::vector<unsigned char>& )
-        {
-            throw NotImplementedException();
-        }
+        virtual std::unique_ptr<Disassembler> GetDisassembler(
+          InstVec& insts, const std::vector<unsigned char>& c
+        );
 
         /**
          * Retrieve the disassembler for the engine.
          *
-         * @param insts Reference to the std::vector to place the Instructions in.
-         * @return Pointer to a Disassembler for the engine.
+         * @param insts[out] Vector to place the Instructions in.
+         * @return Pointer to a disassembler for the engine.
          */
         virtual std::unique_ptr<Disassembler> GetDisassembler(InstVec &insts) = 0;
 
         /**
          * Retrieve the code generator for the engine.
          *
-         * @param output The std::ostream to output the code to.
+         * @param output[out] Stream to output the code to.
          * @return Pointer to a CodeGenerator for the engine.
          */
-        virtual std::unique_ptr<CodeGenerator> GetCodeGenerator(const InstVec& insts, std::ostream &output) = 0;
+        virtual std::unique_ptr<CodeGenerator> GetCodeGenerator(
+          const InstVec& insts, std::ostream &output
+        ) = 0;
 
         /**
          * Post-processing step after CFG analysis.
-         * @param insts Reference to the std::vector to place the Instructions in.
-         * @param g Graph generated from the CFG analysis.
+         * @param insts[out] Vector to place the Instructions in.
+         * @param graph[in] Graph generated from the CFG analysis.
          */
-        virtual void PostCFG(InstVec&, Graph) { }
+        virtual void PostCFG(InstVec& insts, Graph graph);
 
         /**
          * Whether or not code flow analysis is supported for this engine.
          *
-         * @return True if supported, false if not. If false is returned, code flow analysis should not take place, and -D should be implied.
+         * @return True if supported, false if not. If false is returned, code
+         * flow analysis should not take place.
          */
-        virtual bool SupportsCodeFlow() const { return true; }
+        virtual bool SupportsCodeFlow() const;
 
         /**
          * Whether or not code generation is supported for this engine.
          *
-         * @return True if supported, false if not. If false is returned, code generation should not take place, and -G should be implied.
+         * @return True if supported, false if not. If false is returned, code
+         * generation should not take place.
          */
-        virtual bool SupportsCodeGen() const { return true; }
-
-
+        virtual bool SupportsCodeGen() const;
 
         /**
-         * Fill a vector with the names of all variants supported for this engine.
-         * If variants are not used by this engine, leave the vector empty (default implementation).
+         * Retrieves the names of all variants supported for this engine.
          *
-         * @param variants Vector to add the supported variants to.
+         * If variants are not used by this engine, it will be empty (default
+         * implementation).
+         *
+         * @param variants Vector with the supported variants.
          */
-        virtual void GetVariants(std::vector<std::string>&) const { };
+        virtual void GetVariants(std::vector<std::string>&) const;
 
 
         /**
          * Whether or not to use "pure" grouping during code flow analysis.
-         * With pure grouping, code flow analysis only looks at branches when merging.
-         * This method may be more appropriate for non-stack-based engines.
+         *
+         * With pure grouping, code flow analysis only looks at branches when
+         * merging. This method may be more appropriate for non-stack-based
+         * engines.
          *
          * @return True if pure grouping should be used, false if not.
          */
-        virtual bool UsePureGrouping() const { return false; }
+        virtual bool UsePureGrouping() const;
 
-        virtual FuncMap GetFunctions() const{return _functions;}
+        // TODO: functions must probably be set to private, and have accessors, but...
+        // too much depends on it being public right now.
+        // Maybe at some point in the future...
 
-        virtual void SetFunction(uint32 index, Function function){
-            _functions[index] = function;
-        }
-
-        FuncMap _functions;
+        /**
+         * Map to functions in the current script, indexed by start address.
+         */
+        FuncMap functions;
 
     protected:
 
-        //FuncMap _functions; ///< Map to functions in the current script, indexed by starting address.
-        std::string _variant; ///< Engine variant to use for the script.
+        /**
+         * Engine variant to use for the script.
+         */
+        std::string variant_;
 
 };

+ 7 - 9
V-Gears-Installer/include/decompiler/Function.h

@@ -22,15 +22,14 @@
 /**
  * Structure representing a function.
  */
-class Function {
-    public:
+struct Function {
 
         /**
          * Constructor.
          *
          * Required for use with STL, should not be called manually.
          */
-        Function();
+        Function(): start_addr(0), end_addr(0), num_instructions(0){}
 
         /**
          * Constructor.
@@ -38,22 +37,23 @@ class Function {
          * @param start_addr[in] Address of the first instruction in the function.
          * @param end_addr[in] Address of the last instruction in the function
          */
-        Function(uint32 start_addr, uint32 end_addr);
+        Function(uint32 start_addr, uint32 end_addr):
+          start_addr(start_addr), end_addr(end_addr), num_instructions(0){}
 
         /**
          * The function starting address.
          */
-        uint32 start_addr = 0;
+        uint32 start_addr;
 
         /**
          * The function ending address.
          */
-        uint32 end_addr = 0;
+        uint32 end_addr;
 
         /**
          * Number of instructions in the function.
          */
-        uint32 num_instructions = 0;
+        uint32 num_instructions;
 
         /**
          * The name of the function.
@@ -80,6 +80,4 @@ class Function {
          */
         std::string metadata;
 
-
-
 };

+ 3 - 3
V-Gears-Installer/src/decompiler/CodeGenerator.cpp

@@ -257,8 +257,8 @@ typedef std::pair<GraphVertex, ValueStack> DFSEntry;
 void CodeGenerator::GeneratePass(InstVec& insts, const Graph& graph){
     graph_ = graph;
     for (
-      FuncMap::iterator fn = engine_->GetFunctions().begin();
-      fn != engine_->GetFunctions().end();
+      FuncMap::iterator fn = engine_->functions.begin();
+      fn != engine_->functions.end();
       ++ fn
     ){
         while (!stack_.empty()) stack_.pop();
@@ -268,7 +268,7 @@ void CodeGenerator::GeneratePass(InstVec& insts, const Graph& graph){
         bool print_func_signature = !func_signature.empty();
         if (print_func_signature){
             cur_group_ = GET(entry_point);
-            if (!(fn == engine_->GetFunctions().begin())) AddOutputLine("");
+            if (!(fn == engine_->functions.begin())) AddOutputLine("");
             OnBeforeStartFunction(fn->second);
             AddOutputLine(func_signature, false, true);
             OnStartFunction(fn->second);

+ 11 - 17
V-Gears-Installer/src/decompiler/ControlFlow.cpp

@@ -65,12 +65,8 @@ ControlFlow::ControlFlow(InstVec& insts, Engine& engine): insts_(insts),engine_(
     // Automatically add a function if we're not supposed to look for more functions
     // and no functions are defined.
     // This avoids a special case for when no real functions exist in the script.
-    if (engine_.GetFunctions().empty()){
-        /*engine_.SetFunction(
-          (*insts.begin())->_address,
-          Function((*insts.begin())->_address, (insts.back())->_address)
-        );*/
-        engine_._functions[(*insts.begin())->_address]= Function(
+    if (engine_.functions.empty()){
+        engine_.functions[(*insts.begin())->_address]= Function(
           (*insts.begin())->_address, (insts.back())->_address
         );
     }
@@ -84,10 +80,8 @@ ControlFlow::ControlFlow(InstVec& insts, Engine& engine): insts_(insts),engine_(
         PUT_ID(cur, id);
         id ++;
         // Add reference to vertex if function starts here.
-        /*if (engine_.GetFunctions().find((*it)->_address) != engine_.GetFunctions().end())
-            engine_.GetFunctions()[(*it)->_address].vertex = cur;*/
-        if (engine_._functions.find((*it)->_address) != engine_._functions.end()){
-            engine_._functions[(*it)->_address].vertex = cur;
+        if (engine_.functions.find((*it)->_address) != engine_.functions.end()){
+            engine_.functions[(*it)->_address].vertex = cur;
         }
         prev = GET(cur);
     }
@@ -97,7 +91,7 @@ ControlFlow::ControlFlow(InstVec& insts, Engine& engine): insts_(insts),engine_(
     bool add_edge = false;
     prev = NULL;
     for (InstIterator it = insts.begin(); it != insts.end(); ++it){
-        if (engine_.GetFunctions().find((*it)->_address) != engine_.GetFunctions().end())
+        if (engine_.functions.find((*it)->_address) != engine_.functions.end())
             add_edge = false;
         GraphVertex cur = Find(it);
         if (add_edge){
@@ -192,17 +186,17 @@ void ControlFlow::SetStackLevel(GraphVertex graph, int level){
 
 void ControlFlow::CreateGroups(){
     if (
-      !engine_.GetFunctions().empty()
-      //&& GET(engine_.GetFunctions().begin()->second.GetVertex())->_stackLevel != -1
-      //&& GET(engine_.GetFunctions().begin()->second.vertex_)->_stackLevel != -1
-      && GET(engine_._functions.begin()->second.vertex)->_stackLevel != -1
+      !engine_.functions.empty()
+      //&& GET(engine_.functions.begin()->second.GetVertex())->_stackLevel != -1
+      //&& GET(engine_.functions.begin()->second.vertex_)->_stackLevel != -1
+      && GET(engine_.functions.begin()->second.vertex)->_stackLevel != -1
     ){
         return;
     }
 
     for (
-      FuncMap::iterator fn = engine_._functions.begin();
-      fn != engine_._functions.end();
+      FuncMap::iterator fn = engine_.functions.begin();
+      fn != engine_.functions.end();
       ++ fn
     ){
         SetStackLevel(fn->second.vertex, 0);

+ 17 - 0
V-Gears-Installer/src/decompiler/Engine.cpp

@@ -13,3 +13,20 @@
  * GNU General Public License for more details.
  */
 
+#include "decompiler/Engine.h"
+
+std::unique_ptr<Disassembler> Engine::GetDisassembler(
+  InstVec& insts, const std::vector<unsigned char>& c
+){
+    throw NotImplementedException();
+}
+
+void Engine::PostCFG(InstVec& insts, Graph graph){}
+
+bool Engine::SupportsCodeFlow() const{return true;}
+
+bool Engine::SupportsCodeGen() const{return true;}
+
+void Engine::GetVariants(std::vector<std::string>&) const{};
+
+bool Engine::UsePureGrouping() const{return false;}

+ 0 - 32
V-Gears-Installer/src/decompiler/Function.cpp

@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2022 The V-Gears Team
- *
- * This file is part of V-Gears
- *
- * V-Gears is free software: you can redistribute it and/or modify it under
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, version 3.0 (GPLv3) of the License.
- *
- * V-Gears 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.
- */
-
-#include "decompiler/Function.h"
-
-/**
- * Constructor.
- *
- * Required for use with STL, should not be called manually.
- */
-Function::Function(): start_addr(0), end_addr(0), num_instructions(0){}
-
-/**
- * Constructor.
- *
- * @param start_addr[in] Address of the first instruction in the function.
- * @param end_addr[in] Address of the last instruction in the function
- */
-Function::Function(uint32 start_addr, uint32 end_addr)
-  : start_addr(start_addr), end_addr(end_addr), num_instructions(0){}

+ 2 - 2
V-Gears-Installer/src/decompiler/field/FieldCodeGenerator.cpp

@@ -88,8 +88,8 @@ void FF7::FieldCodeGenerator::Generate(InstVec& insts, const Graph& graph){
     
     std::vector<std::pair<Function&, InstVec>> functions_with_bodies;
     for (
-      auto function = engine_->_functions.begin();
-      function != engine_->_functions.end();
+      auto function = engine_->functions.begin();
+      function != engine_->functions.end();
       ++ function
     ){
         InstVec body;

+ 2 - 3
V-Gears-Installer/src/decompiler/field/FieldDisassembler.cpp

@@ -233,7 +233,7 @@ void FF7::FieldDisassembler::AddFunc(
     // If there is no ID check if there was an ID for this entity in any of
     // its other functions and use that instead.
     if (id == -1){
-        for (auto& func : engine_->GetFunctions()){
+        for (auto& func : engine_->functions){
             FunctionMetaData func_meta_data(func.second.metadata);
             if (func_meta_data.GetEntityName() == entity_name && func_meta_data.GetCharacterId() != -1){
                 id = func_meta_data.GetCharacterId();
@@ -243,8 +243,7 @@ void FF7::FieldDisassembler::AddFunc(
     }
     meta_data += std::to_string(id) + "_" + entity_name;
     func->metadata = meta_data;
-    //engine_->_functions[SCRIPT_ENTRY_POINT] = *func;
-    engine_->SetFunction(SCRIPT_ENTRY_POINT, *func);
+    engine_->functions[SCRIPT_ENTRY_POINT] = *func;
     engine_->AddEntityFunction(entity_name, entity_index, func->name, script_index);
     // If the entity is a line, mark it as so.
     if (is_line) engine_->MarkEntityAsLine(entity_index, true, point_a, point_b);

+ 5 - 5
V-Gears-Installer/src/decompiler/field/FieldEngine.cpp

@@ -146,7 +146,7 @@ bool FF7::FieldEngine::UsePureGrouping() const{return false;}
 
 std::map<std::string, int> FF7::FieldEngine::GetEntities() const{
     std::map<std::string, int> r;
-    for (auto& f : _functions){
+    for (auto& f : functions){
         const Function& func = f.second;
         FF7::FunctionMetaData meta(func.metadata);
         auto it = r.find(meta.GetEntityName());
@@ -172,7 +172,7 @@ std::vector<SUDM::FF7::Field::FieldEntity> FF7::FieldEngine::GetEntityList() con
             // Get character ID.
             ent.char_id = -1;
             std::map<std::string, int> r;
-            for (auto& f : _functions){
+            for (auto& f : functions){
                 const Function& func = f.second;
                 FF7::FunctionMetaData meta(func.metadata);
                 if (meta.GetEntityName() == ent.name){
@@ -239,7 +239,7 @@ float FF7::FieldEngine::GetScaleFactor() const {return scale_factor_;}
 const std::string& FF7::FieldEngine::GetScriptName() const {return script_name_;}
 
 void FF7::FieldEngine::RemoveExtraneousReturnStatements(InstVec& insts, Graph graph){
-    for (auto& f : _functions){
+    for (auto& f : functions){
         Function& func = f.second;
         for (auto it = insts.begin(); it != insts.end(); it ++){
             // Is it the last instruction in the function, and is it a return statement?
@@ -260,7 +260,7 @@ void FF7::FieldEngine::RemoveExtraneousReturnStatements(InstVec& insts, Graph gr
 }
 
 void FF7::FieldEngine::RemoveTrailingInfiniteLoops(InstVec& insts, Graph graph){
-    for (auto& f : _functions){
+    for (auto& f : functions){
         Function& func = f.second;
         for (auto it = insts.begin(); it != insts.end(); it ++){
             // Is it the last instruction in the function, a jump, and a jumping to itself?
@@ -281,7 +281,7 @@ void FF7::FieldEngine::RemoveTrailingInfiniteLoops(InstVec& insts, Graph graph){
 }
 
 void FF7::FieldEngine::MarkInfiniteLoopGroups(InstVec& insts, Graph graph){
-    for (auto& f : _functions){
+    for (auto& f : functions){
         Function& func = f.second;
         for (auto it = insts.begin(); it != insts.end(); it ++){
             if ((*it)->_address == func.end_addr){

+ 1 - 1
V-Gears-Installer/src/decompiler/graph.cpp

@@ -25,7 +25,7 @@
 
 void GraphProperties::operator()(std::ostream& out) const {
 	out << "node [shape=record]" << std::endl;
-	for (FuncMap::iterator fn = _engine->GetFunctions().begin(); fn != _engine->GetFunctions().end(); ++fn) {
+	for (FuncMap::iterator fn = _engine->functions.begin(); fn != _engine->functions.end(); ++fn) {
 		int index = (boost::get(boost::vertex_index, *_g, fn->second.vertex));
 		out << "XXX" << index << " [shape=none, label=\"\", height=0]" << std::endl;
 		out << "XXX" << index << " -> " << index << std::endl;