gcsx_bytecode.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* GCSx
  2. ** BYTECODE.H
  3. **
  4. ** Bytecode-related utilities/datatypes/structures
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #ifndef __GCSx_BYTECODE_H_
  24. #define __GCSx_BYTECODE_H_
  25. // Bits combine to form datatypes
  26. enum {
  27. // Base types- all but VAR match with OM_
  28. DATA_VOID = -2,
  29. DATA_VAR = -1, // 0 reserved for none
  30. DATA_INT = 1,
  31. DATA_FLOAT = 2,
  32. DATA_STR = 3,
  33. DATA_ENTITY = 7,
  34. DATA_OBJECT = 8,
  35. // Flags
  36. DATA_ARRAY = 1,
  37. DATA_HASH = 2,
  38. DATA_CONST = 4,
  39. DATA_LOCAL = 8,
  40. DATA_GLOBAL = 16,
  41. DATA_PRIVATE = 32,
  42. DATA_PUBLIC = 64,
  43. };
  44. struct DataType {
  45. int baseType;
  46. int subType; // 0 for unapplicable OR unspecified/unknown
  47. int flags;
  48. };
  49. // datatype to wart conversion; doesn't consider local/global/private/public
  50. // type C + baseType (A void B var D int E float etc.)
  51. // followed by A + flags (A none B array C hash E const)
  52. // followed by hexadecimal subtype (optional)
  53. std::string dataTypeToWart(const DataType& dt);
  54. // wart to datatype; returns pointer to first unused character within string,
  55. // for reading next wart etc. returns NULL if error decoding wart
  56. const char* wartToDataType(const char* wart, DataType& result);
  57. // Labels within a codespace; also marks loops
  58. // Labels cannot be accessed between workspaces
  59. struct Label {
  60. int scope;
  61. int offset;
  62. int isLoop;
  63. // Stack depth at moment of label creation
  64. int stackDepth;
  65. };
  66. // Maps names to labels; names are newly-allocated char*s
  67. // Blank name for anonymous loops
  68. typedef hash_map<const char*, std::list<Label>, hash<const char*>, hash_eqstr> LabelMap;
  69. void destroyLabelMap(LabelMap* map);
  70. std::list<Label>& addLabelMap(LabelMap* map, const std::string& name);
  71. // Functions listed within an individual script/etc
  72. // Keyed off of name within a map
  73. struct Function {
  74. int numparam;
  75. DataType* parameters; // All have LOCAL added
  76. DataType returntype;
  77. // -1 = unknown
  78. // during compile, offset is within functions section
  79. int offset;
  80. };
  81. // Maps names to functions; names are newly-allocated char*s
  82. typedef hash_map<const char*, Function, hash<const char*>, hash_eqstr> FunctionMap;
  83. void destroyFunctionMap(FunctionMap* map);
  84. Function& addFunctionMap(FunctionMap* map, const std::string& name);
  85. // Variables listed within an individual script/etc
  86. // Keyed off of name within a map
  87. struct Variable {
  88. DataType datatype;
  89. int scope; // <0 global, 0 main local, >0 subscope (incl function param)
  90. union {
  91. Sint32 offs; // locals- stack offset
  92. Sint32 constI;
  93. BCfloat constF;
  94. const char* constS; // Allocated and owned
  95. } val;
  96. const char* name; // Backreference to name
  97. };
  98. // Maps names to varaibles; names are newly-allocated char*s
  99. typedef hash_map<const char*, std::list<Variable>, hash<const char*>, hash_eqstr> VariableMap;
  100. void destroyVariableMap(VariableMap* map);
  101. // storeName is gauranteed to point to a valid string as long as map entry exists
  102. std::list<Variable>& addVariableMap(VariableMap* map, const std::string& name, const char*& storeName);
  103. // Linker entries (global variables, built-in functions, function libraries)
  104. // Also used for global consts, to check consistency during linking
  105. // Also used for local strings/functions/loops, but removed before final result
  106. struct LinkEntry {
  107. enum LinkEntryType {
  108. LINK_GLOBAL = 1, // Link to global var's data
  109. LINK_GLOBALVAR, // Link directly to global var (may be different)
  110. LINK_BUILTIN,
  111. LINK_LIBRARY,
  112. LINK_CONST,
  113. LINK_STRING,
  114. LINK_FUNCTION,
  115. LINK_LOOP_CONTINUE,
  116. LINK_LOOP_END,
  117. // @TODO: links directly to other entity members/functions
  118. } type; // What type of link
  119. int offset; // Offset within bytecode to place/adjust ptr (ignored for const)
  120. std::string scope; // Library name, if specified (ignored for globals/local strings/functions/loops)
  121. std::string name; // Name of global/function/loop (ignored for local strings)
  122. // Combination of return/parameter types to verify at linking
  123. // For global variables, type
  124. // For global consts, includes const value
  125. // (ignored for local strings/functions/loops)
  126. std::string wart;
  127. };
  128. // Opcodes
  129. enum Opcode {
  130. OP_NOOP = 0,
  131. // These may be alphabetical, but future opcodes add at end
  132. OP_ADD,
  133. OP_ADDf,
  134. OP_AND,
  135. OP_CONCAT,
  136. OP_CONVERT,
  137. OP_CREATEa,
  138. OP_CREATEe,
  139. OP_CREATEh,
  140. OP_CREATEo,
  141. OP_DEBUG,
  142. OP_DISCARD,
  143. OP_DISCARDL,
  144. OP_DIV,
  145. OP_DIVf,
  146. OP_EQ,
  147. OP_EQf,
  148. OP_EQo,
  149. OP_EQs,
  150. OP_GE,
  151. OP_GEf,
  152. OP_GEs,
  153. OP_GT,
  154. OP_GTf,
  155. OP_GTs,
  156. OP_IFFALSE,
  157. OP_IFFALSEa,
  158. OP_IFFALSEf,
  159. OP_IFFALSEh,
  160. OP_IFFALSEo,
  161. OP_IFFALSEs,
  162. OP_IFFALSEv,
  163. OP_IFTRUE,
  164. OP_IFTRUEa,
  165. OP_IFTRUEf,
  166. OP_IFTRUEh,
  167. OP_IFTRUEo,
  168. OP_IFTRUEs,
  169. OP_IFTRUEv,
  170. OP_INIT,
  171. OP_JUMP,
  172. OP_LE,
  173. OP_LEf,
  174. OP_LEs,
  175. OP_LT,
  176. OP_LTf,
  177. OP_LTs,
  178. OP_MOD,
  179. OP_MULT,
  180. OP_MULTf,
  181. OP_NE,
  182. OP_NEf,
  183. OP_NEo,
  184. OP_NEs,
  185. OP_OR,
  186. OP_PUSH,
  187. OP_PUSHa,
  188. OP_PUSHf,
  189. OP_PUSHh,
  190. OP_PUSHo,
  191. OP_PUSHs,
  192. OP_PUSHv,
  193. OP_RET,
  194. OP_SHIFTL,
  195. OP_SHIFTR,
  196. OP_STOP,
  197. OP_STORE,
  198. OP_STOREa,
  199. OP_STOREf,
  200. OP_STOREh,
  201. OP_STOREo,
  202. OP_STOREs,
  203. OP_STOREv,
  204. OP_SUB,
  205. OP_SUBf,
  206. OP_SUBR,
  207. OP_XOR,
  208. OP_GETe,
  209. OP_SETe,
  210. OP_GETo,
  211. OP_SETo,
  212. OP_IDLE,
  213. OP_RETVOID,
  214. OP_SETef,
  215. OP_SETei,
  216. OP_SETof,
  217. OP_SEToi,
  218. // (not an actual opcode)
  219. OP_LAST,
  220. };
  221. // O)perand addressing M)odes
  222. // Most bit combinations are valid
  223. // - Unused object types are reserved (types 9-15)
  224. // - Array/hash literals not supported (types 5-6)
  225. // - Reserved literals not supported (types 10-15)
  226. // - Cannot use OM_INDIRECT with entry, array, hash, local, global
  227. // - Cannot use OM_POP with entry, non-const, or convert
  228. // - Const and copy go together; non-const and convert go together
  229. enum OperMode {
  230. // Non-literals
  231. OM_ENTRY = 0, // Represents a variant
  232. OM_INT = 1,
  233. OM_FLOAT = 2,
  234. OM_STR = 3,
  235. OM_STR_CONST = 4,
  236. OM_ARRAY = 5,
  237. OM_HASH = 6,
  238. OM_ENTITY = 7,
  239. OM_OBJECT = 8,
  240. // (these types are reserved)
  241. OM_RESERVED_1 = 9,
  242. OM_RESERVED_2 = 10,
  243. OM_RESERVED_3 = 11,
  244. OM_RESERVED_4 = 12,
  245. OM_RESERVED_5 = 13,
  246. OM_RESERVED_6 = 14,
  247. OM_RESERVED_7 = 15,
  248. // Literals
  249. OM_NONE = 0,
  250. // OM_INT also used as literal for offsets
  251. // OM_FLOAT
  252. // [OM_STR not legal but used during compilation]
  253. // OM_STR_CONST
  254. // [OM_ARRAY / OM_HASH reserved for literals later]
  255. OM_ALL = 7, // entity, always w/subtype even if 0
  256. OM_ALL_OTHER = 8, // entity, always w/subtype even if 0
  257. OM_NOTHING = 9, // entity or object, no subtype
  258. OM_THIS = 10, // entity, no subtype
  259. // 11-14 reserved; currently assumed to be other OBJ_ literals
  260. OM_POINTER = 15,
  261. // Location
  262. OM_POP = 0, // Must always use with one of two flags
  263. OM_STACK = 16,
  264. OM_LOCAL = 32,
  265. OM_GLOBAL = 48,
  266. // Use with pop/stack to indicate stack entry is a POINTER
  267. // directly within an array/hash to the noted type, NO CONVERSION
  268. OM_INDIRECT = 192,
  269. // Flags
  270. // If present type is preknown and no conversion needed
  271. // If not, item is converted 'in place' if necessary
  272. // Converting an array or hash makes a new copy, but this
  273. // will NOT make a new copy if type is already correct
  274. OM_NO_CONVERT = 64,
  275. // If conversion performed, don't affect original
  276. // Also *gaurantees* a new array/hash copy (no ref)
  277. OM_COPY = 128,
  278. // Masks
  279. OM_BASETYPE = 15,
  280. OM_LOCATION = 48,
  281. OM_FLAGS = 192,
  282. };
  283. // Use these to ensure proper handling due to overlapping operand mode bits
  284. // These may not be used in bytecode interpreting for speed/efficiency reasons
  285. #define OM_IS_NONE(x) ((x) == OM_NONE)
  286. #define OM_IS_OFFSET(x) ((x) == OM_INT)
  287. #define OM_IS_POINTER(x) ((x) == OM_POINTER)
  288. #define OM_IS_LITERAL(x) (((x) & OM_BASETYPE) == (x))
  289. #define OM_IS_INT(x) (((x) & OM_BASETYPE) == OM_INT)
  290. #define OM_IS_FLOAT(x) (((x) & OM_BASETYPE) == OM_FLOAT)
  291. #define OM_IS_STR(x) (((x) & OM_BASETYPE) == OM_STR || ((x) & OM_BASETYPE) == OM_STR_CONST)
  292. #define OM_IS_CONST(x) (((x) & OM_BASETYPE) == OM_STR_CONST)
  293. // Be prepared for literal arrays/hashes in the future
  294. #define OM_IS_ARRAY(x) (((x) & OM_BASETYPE) == OM_ARRAY)
  295. #define OM_IS_HASH(x) (((x) & OM_BASETYPE) == OM_HASH)
  296. // Always check for literal status first before anything further
  297. #define OM_IS_ENTITY(x) (((x) & OM_BASETYPE) == OM_ENTITY)
  298. #define OM_IS_OBJECT(x) (((x) & OM_BASETYPE) == OM_OBJECT)
  299. // (or can check for 'none' instead of literal, before this one)
  300. #define OM_IS_ENTRY(x) (((x) & OM_BASETYPE) == OM_ENTRY)
  301. #define OM_IS_LOCAL(x) (((x) & OM_LOCATION) == OM_LOCAL)
  302. #define OM_IS_STACK(x) (((x) & OM_LOCATION) == OM_STACK)
  303. #define OM_IS_GLOBAL(x) (((x) & OM_LOCATION) == OM_GLOBAL)
  304. #define OM_IS_POP(x) (((x) & OM_LOCATION) == OM_POP && ((x) & OM_BASETYPE) != (x))
  305. #define OM_IS_INDIRECT(x) (((x) & OM_FLAGS) == OM_INDIRECT)
  306. #define OM_IS_KNOWN(x) (((x) & OM_FLAGS) == OM_NO_CONVERT)
  307. #define OM_IS_CONVERT(x) (((x) & OM_FLAGS) != OM_NO_CONVERT && ((x) & OM_FLAGS) != OM_INDIRECT)
  308. #define OM_IS_COPY(x) (((x) & OM_FLAGS) == OM_COPY)
  309. #ifdef COMPILEASSERT
  310. // Checks for valid opcode/mode combinations
  311. void checkOpcode(Opcode opc, Uint8 mode1, Uint8 mode2, Uint8 mode3);
  312. #endif
  313. // Dumps program to debug (uses static globals, not thread-safe)
  314. void decompileBytecode(const Uint32* bytecode, const std::list<LinkEntry>* links);
  315. int debugBytecode(std::string& line, const Uint32* bytecode);
  316. #endif