decompiler_codegen.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #pragma once
  2. /* ScummVM Tools
  3. *
  4. * ScummVM Tools is the legal property of its developers, whose
  5. * names are too numerous to list here. Please refer to the
  6. * COPYRIGHT file distributed with this source distribution.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. */
  22. #include "graph.h"
  23. #include "value.h"
  24. #include "unknown_opcode_exception.h"
  25. #include <ostream>
  26. #include <utility>
  27. #include <boost/intrusive_ptr.hpp>
  28. #include <memory>
  29. class Engine;
  30. class Function;
  31. const int kIndentAmount = 4; ///< How many spaces to use for each indent.
  32. /**
  33. * Enumeration for the different argument/operand orderings.
  34. */
  35. enum ArgOrder
  36. {
  37. FIFO_ARGUMENT_ORDER, ///< First argument is pushed to stack first.
  38. LIFO_ARGUMENT_ORDER ///< First argument is pushed to stack last.
  39. };
  40. class ITargetLanaguge
  41. {
  42. public:
  43. enum eContext
  44. {
  45. eToElseBlock, // End of if/elseif block and about to start a final else
  46. eBeginElse,
  47. eEndOfIf,
  48. eEndOfWhile,
  49. eEndIfElseChain,
  50. eBeginWhile,
  51. eEndWhile
  52. };
  53. virtual ~ITargetLanaguge() = default;
  54. virtual std::string LoopBreak() = 0;
  55. virtual std::string LoopContinue() = 0;
  56. virtual std::string Goto(uint32 target) = 0;
  57. virtual std::string DoLoopHeader() = 0;
  58. virtual std::string DoLoopFooter(bool beforeExpr) = 0;
  59. virtual std::string If(bool beforeExpr) = 0;
  60. virtual std::string WhileHeader(bool beforeExpr) = 0;
  61. virtual std::string FunctionCallArgumentSeperator() = 0;
  62. virtual std::string FunctionCallBegin() = 0;
  63. virtual std::string FunctionCallEnd() = 0;
  64. virtual std::string Label(uint32 addr) = 0;
  65. virtual std::string Else() = 0;
  66. virtual std::string StartBlock(eContext) = 0;
  67. virtual std::string EndBlock(eContext) = 0;
  68. virtual std::string LineTerminator() = 0;
  69. };
  70. class CTargetLanguage : public ITargetLanaguge
  71. {
  72. public:
  73. virtual std::string LoopBreak() override
  74. {
  75. return "break;";
  76. }
  77. virtual std::string LoopContinue() override
  78. {
  79. return "continue;";
  80. }
  81. virtual std::string Goto(uint32 target) override
  82. {
  83. std::stringstream s;
  84. s << boost::format("goto label_0x%X;") % target;
  85. return s.str();
  86. }
  87. virtual std::string DoLoopHeader() override
  88. {
  89. return "do {";
  90. }
  91. virtual std::string DoLoopFooter(bool beforeExpr) override
  92. {
  93. if (beforeExpr)
  94. {
  95. return " } while (";
  96. }
  97. return ");";
  98. }
  99. virtual std::string If(bool beforeExpr) override
  100. {
  101. if (beforeExpr)
  102. {
  103. return "if (";
  104. }
  105. return ") {";
  106. }
  107. virtual std::string WhileHeader(bool beforeExpr) override
  108. {
  109. if (beforeExpr)
  110. {
  111. return "while (";
  112. }
  113. return ")";
  114. }
  115. virtual std::string FunctionCallArgumentSeperator() override
  116. {
  117. return ",";
  118. }
  119. virtual std::string FunctionCallBegin() override
  120. {
  121. return "(";
  122. }
  123. virtual std::string FunctionCallEnd() override
  124. {
  125. return ");";
  126. }
  127. virtual std::string Label(uint32 addr) override
  128. {
  129. std::stringstream s;
  130. s << boost::format("label_0x%X:") % addr;
  131. return s.str();
  132. }
  133. virtual std::string Else() override
  134. {
  135. return "else";
  136. }
  137. virtual std::string StartBlock(eContext) override
  138. {
  139. return "{";
  140. }
  141. virtual std::string EndBlock(eContext) override
  142. {
  143. return "}";
  144. }
  145. virtual std::string LineTerminator() override
  146. {
  147. return ";";
  148. }
  149. };
  150. class LuaTargetLanguage : public ITargetLanaguge
  151. {
  152. public:
  153. virtual std::string LoopBreak() override
  154. {
  155. return "break";
  156. }
  157. virtual std::string LoopContinue() override
  158. {
  159. // LUA has no continue keyword
  160. //throw InternalDecompilerError();
  161. return "-- TODO continue not supported in LUA!";
  162. }
  163. virtual std::string Goto(uint32 target) override
  164. {
  165. std::stringstream s;
  166. s << boost::format("goto label_0x%X") % target;
  167. return s.str();
  168. }
  169. virtual std::string DoLoopHeader() override
  170. {
  171. return "repeat";
  172. }
  173. virtual std::string DoLoopFooter(bool beforeExpr) override
  174. {
  175. if (beforeExpr)
  176. {
  177. return "until (";
  178. }
  179. return ")";
  180. }
  181. virtual std::string If(bool beforeExpr) override
  182. {
  183. if (beforeExpr)
  184. {
  185. return "if (";
  186. }
  187. return ") then";
  188. }
  189. virtual std::string WhileHeader(bool beforeExpr) override
  190. {
  191. if (beforeExpr)
  192. {
  193. return "while (";
  194. }
  195. return ") do";
  196. }
  197. virtual std::string FunctionCallArgumentSeperator() override
  198. {
  199. return ",";
  200. }
  201. virtual std::string FunctionCallBegin() override
  202. {
  203. return "(";
  204. }
  205. virtual std::string FunctionCallEnd() override
  206. {
  207. return ")";
  208. }
  209. virtual std::string Label(uint32 addr) override
  210. {
  211. std::stringstream s;
  212. s << boost::format("::label_0x%X::") % addr;
  213. return s.str();
  214. }
  215. virtual std::string Else() override
  216. {
  217. return "else";
  218. }
  219. virtual std::string StartBlock(eContext) override
  220. {
  221. return "";
  222. }
  223. virtual std::string EndBlock(eContext ctx) override
  224. {
  225. if (ctx == eToElseBlock)
  226. {
  227. // For the final else we don't need an end before it
  228. return "";
  229. }
  230. return "end";
  231. }
  232. virtual std::string LineTerminator() override
  233. {
  234. return "";
  235. }
  236. };
  237. /**
  238. * Base class for code generators.
  239. */
  240. class CodeGenerator
  241. {
  242. private:
  243. Graph _g; ///< The annotated graph of the script.
  244. /**
  245. * Processes a GraphVertex.
  246. *
  247. * @param v The vertex to process.
  248. */
  249. void process(Function& func, InstVec& insts, GraphVertex v);
  250. protected:
  251. Engine *_engine; ///< Pointer to the Engine used for the script.
  252. std::ostream &_output; ///< The std::ostream to output the code to.
  253. ValueStack _stack; ///< The stack currently being processed.
  254. uint _indentLevel; ///< Indentation level.
  255. GraphVertex _curVertex; ///< Graph vertex currently being processed.
  256. std::unique_ptr<ITargetLanaguge> target_lang_;
  257. /**
  258. * Processes an instruction. Called by process() for each instruction.
  259. * Call the base class implementation for opcodes you cannot handle yourself,
  260. * or where the base class implementation is preferable.
  261. *
  262. * @param inst The instruction to process.
  263. */
  264. void ProcessInst(Function& func, InstVec& insts, const InstPtr inst);
  265. void processUncondJumpInst(Function& func, InstVec& insts, const InstPtr inst);
  266. void processCondJumpInst(const InstPtr inst);
  267. /**
  268. * Indents a string according to the current indentation level.
  269. *
  270. * @param s The string to indent.
  271. * @result The indented string.
  272. */
  273. std::string indentString(std::string s);
  274. /**
  275. * Construct the signature for a function.
  276. *
  277. * @param func Reference to the function to construct the signature for.
  278. */
  279. virtual std::string ConstructFuncSignature(const Function& func);
  280. virtual void OnBeforeStartFunction(const Function& func);
  281. virtual void OnEndFunction(const Function& func);
  282. virtual void OnStartFunction(const Function&) { }
  283. virtual bool OutputOnlyRequiredLabels() const { return false; }
  284. void generatePass(InstVec& insts, const Graph& g);
  285. bool mIsLabelPass = true;
  286. public:
  287. ITargetLanaguge& TargetLang()
  288. {
  289. assert(target_lang_);
  290. return *target_lang_;
  291. }
  292. void writeFunctionCall(std::string functionName, std::string paramsFormat, const std::vector<ValuePtr>& params);
  293. const ArgOrder _binOrder; ///< Order of operands for binary operations.
  294. const ArgOrder _callOrder; ///< Order of operands for call arguments.
  295. ValueList _argList; ///< Storage for lists of arguments to be built when processing function calls.
  296. GroupPtr mCurGroup; ///< Pointer to the group currently being processed.
  297. virtual ~CodeGenerator() { }
  298. /**
  299. * Constructor for CodeGenerator.
  300. *
  301. * @param engine Pointer to the Engine used for the script.
  302. * @param output The std::ostream to output the code to.
  303. * @param binOrder Order of arguments for binary operators.
  304. * @param callOrder Order of arguments for function calls.
  305. */
  306. CodeGenerator(Engine *engine, std::ostream &output, ArgOrder binOrder, ArgOrder callOrder);
  307. /**
  308. * Generates code from the provided graph and outputs it to stdout.
  309. *
  310. * @param g The annotated graph of the script.
  311. */
  312. virtual void Generate(InstVec& insts, const Graph &g);
  313. /**
  314. * Adds a line of code to the current group.
  315. *
  316. * @param s The line to add.
  317. * @param unindentBefore Whether or not to remove an indentation level before the line. Defaults to false.
  318. * @param indentAfter Whether or not to add an indentation level after the line. Defaults to false.
  319. */
  320. virtual void AddOutputLine(std::string s, bool unindentBefore = false, bool indentAfter = false);
  321. /**
  322. * Generate an assignment statement.
  323. *
  324. * @param dst The variable being assigned to.
  325. * @param src The value being assigned.
  326. */
  327. void writeAssignment(ValuePtr dst, ValuePtr src);
  328. /**
  329. * Add an argument to the argument list.
  330. *
  331. * @param p The argument to add.
  332. */
  333. void addArg(ValuePtr p);
  334. /**
  335. * Process a single character of metadata.
  336. *
  337. * @param inst The instruction being processed.
  338. * @param c The character signifying the action to be taken.
  339. * @param pos The position at which c occurred in the metadata.
  340. */
  341. virtual void processSpecialMetadata(const InstPtr inst, char c, int pos);
  342. };