PageRenderTime 68ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Libraries/JManaVaLib/Source/org/managarm/jmanavalib/utils/VaWriter.java

http://managarm.googlecode.com/
Java | 817 lines | 604 code | 118 blank | 95 comment | 151 complexity | 43da6b1c1d0a189a55c32012050b3154 MD5 | raw file
Possible License(s): GPL-3.0
  1. /* This file is part of the Managarm operating system.
  2. * Copyright (C) 2007, 2008, 2009 Alexander van der Grinten
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>. */
  16. package org.managarm.jmanavalib.utils;
  17. // import java util classes
  18. import java.util.Iterator;
  19. import java.util.HashMap;
  20. import java.util.ArrayList;
  21. import java.io.OutputStream;
  22. import java.io.IOException;
  23. // import managarm virtual architecture
  24. import org.managarm.jmanavalib.core.VaClass;
  25. import org.managarm.jmanavalib.core.VaDatatype;
  26. import org.managarm.jmanavalib.core.VaClsInfo;
  27. import org.managarm.jmanavalib.core.VaMthInfo;
  28. import org.managarm.jmanavalib.core.VaFldInfo;
  29. import org.managarm.jmanavalib.core.VaProcedure;
  30. import org.managarm.jmanavalib.core.VaFrame;
  31. import org.managarm.jmanavalib.core.VaInst;
  32. import org.managarm.jmanavalib.core.VaLiteral;
  33. public class VaWriter {
  34. private static final int CNST_NULL = 0;
  35. private static final int VAIMG_VERSION = 1;
  36. private static final int VAIMG_MODEL = 2;
  37. // constant type ids
  38. private static final short CNST_CLSINFO = 1;
  39. private static final short CNST_MTHINFO = 2;
  40. private static final short CNST_FLDINFO = 3;
  41. private static final short CNST_PRIMTYPE = 4;
  42. private static final short CNST_CLSTYPE = 5;
  43. private static final short CNST_ARRTYPE = 6;
  44. private static final short CNST_DLGTYPE = 10;
  45. private static final short CNST_CARR_LITERAL = 7;
  46. private static final short CNST_INT_LITERAL = 8;
  47. private static final short CNST_UINT_LITERAL = 9;
  48. private static final short CNST_CHAR_LITERAL = 20;
  49. private static final short CNST_LIT_BOOLEAN = 21;
  50. private static final short CNST_LIT_NULL = 22;
  51. // operation code constants
  52. private static final short OPCODE_RETURN = 1;
  53. private static final short OPCODE_LOAD = 2;
  54. private static final short OPCODE_INVOKE_VIRT_RES = 3;
  55. private static final short OPCODE_INVOKE_VIRT_VOID = 4;
  56. private static final short OPCODE_INVOKE_STAT_RES = 5;
  57. private static final short OPCODE_INVOKE_STAT_VOID = 6;
  58. private static final short OPCODE_BINOP_ARITH_ADD = 7;
  59. private static final short OPCODE_BINOP_ARITH_SUB = 8;
  60. private static final short OPCODE_BINOP_ARITH_MUL = 9;
  61. private static final short OPCODE_BINOP_ARITH_DIV = 10;
  62. private static final short OPCODE_BINOP_ARITH_MOD = 11;
  63. private static final short OPCODE_BINOP_ARITH_OR = 12;
  64. private static final short OPCODE_BINOP_ARITH_AND = 13;
  65. private static final short OPCODE_BINOP_ARITH_XOR = 14;
  66. private static final short OPCODE_BINOP_ARITH_SHL = 15;
  67. private static final short OPCODE_BINOP_ARITH_SHR = 16;
  68. private static final short OPCODE_BINOP_SETIF_EQUALS = 17;
  69. private static final short OPCODE_BINOP_SETIF_ABOVE = 18;
  70. private static final short OPCODE_BINOP_SETIF_BELOW = 19;
  71. private static final short OPCODE_UNOP_ARITH_NOT = 20;
  72. private static final short OPCODE_UNOP_ARITH_NEG = 21;
  73. private static final short OPCODE_UNOP_ARR_SIZE = 22;
  74. private static final short OPCODE_JUMP = 23;
  75. private static final short OPCODE_CREATE_OBJECT = 24;
  76. private static final short OPCODE_CREATE_ARRAY = 25;
  77. private static final short OPCODE_ARRACC_LOAD = 26;
  78. private static final short OPCODE_ARRACC_STORE = 27;
  79. private static final short OPCODE_FLDACC_LOAD = 28;
  80. private static final short OPCODE_FLDACC_STORE = 29;
  81. private static final short OPCODE_CAST = 30;
  82. private static final short OPCODE_INSTANCEOF = 31;
  83. private static final short OPCODE_DLG_CONSTRUCT = 32;
  84. private static final short OPCODE_CATCH = 33;
  85. private static final short OPCODE_THROW = 34;
  86. private static final short OPCODE_PASS = 35;
  87. private static final short OPCODE_LEAVE = 36;
  88. // instruction set extension constants
  89. private static final short OPCODE_EXT0 = 255;
  90. // first opcode extension
  91. private static final long EXT0_XNAT_METHOD_ADDRESS = 1;
  92. private static final long EXT0_XNAT_SIZEOF_OBJECT = 2;
  93. private static final long EXT0_XNAT_SIZEOF_ARRAY = 3;
  94. private static final long EXT0_XNAT_ADDRESS_CAST = 4;
  95. private static final long EXT0_XNAT_ADDRESS_OF = 5;
  96. private static final long EXT0_XNAT_MAKE_OBJECT = 6;
  97. private static final long EXT0_XNAT_MAKE_ARRAY = 7;
  98. private static final long EXT0_XNAT_MAKE_DELEGATE = 8;
  99. private static final long EXT0_XNAT_REF_INCREMENT = 9;
  100. private static final long EXT0_XNAT_REF_DECREMENT = 10;
  101. private static final long EXT0_XATOM_CAS_RESULT = 100;
  102. private static final long EXT0_XATOM_CAS_VOID = 101;
  103. private static final long EXT0_XPERF_ARRAY_COPY = 200;
  104. // constant maps
  105. private final HashMap<Object, Integer> cnstMap = new HashMap<Object, Integer>();
  106. private final HashMap<String, Integer> stringMap = new HashMap<String, Integer>();
  107. // constant arrays
  108. private final ArrayList<Object> cnstList = new ArrayList<Object>();
  109. private final ArrayList<String> stringList = new ArrayList<String>();
  110. private final VaImage image;
  111. private int classCnt = 0;
  112. private int methodCnt = 0;
  113. public VaWriter(VaImage image) throws ValibException {
  114. // save the image
  115. this.image = image;
  116. // analyze the classes
  117. final Iterator<VaClsInfo> clsiter = image.classIterator();
  118. while(clsiter.hasNext()) {
  119. final VaClsInfo clsinfo = clsiter.next();
  120. mergeConst(clsinfo);
  121. analyzeClass(image.getClass(clsinfo));
  122. classCnt++;
  123. }
  124. // analyze the methods
  125. final Iterator<VaMthInfo> seciter = image.methodIterator();
  126. while(seciter.hasNext()) {
  127. final VaMthInfo mthinfo = seciter.next();
  128. mergeConst(mthinfo);
  129. analyzeSection(image.getMethod(mthinfo));
  130. methodCnt++;
  131. }
  132. }
  133. // write the image to the stream
  134. public void write(OutputStream stream) throws ValibException {
  135. // write the header
  136. writeUInt(VAIMG_VERSION, stream);
  137. writeUInt(VAIMG_MODEL, stream);
  138. // write the string count
  139. writeUInt(stringList.size(), stream);
  140. // write the strings
  141. for(int i = 0; i < stringList.size(); i++) {
  142. final String string = stringList.get(i);
  143. // write the string length
  144. writeUInt(string.length(), stream);
  145. // write the chars
  146. for(int j = 0; j < string.length(); j++) {
  147. if(string.charAt(j) >= 0xFF) {
  148. writeUByte((short)0xFF, stream);
  149. writeUInt((long)string.charAt(j), stream);
  150. }else{
  151. writeUByte((short)string.charAt(j), stream);
  152. }
  153. }
  154. }
  155. // write the constant count
  156. writeUInt(cnstList.size(), stream);
  157. // write the constants
  158. for(int i = 0; i < cnstList.size(); i++) {
  159. final Object cnst = cnstList.get(i);
  160. if(cnst instanceof VaClsInfo) {
  161. final VaClsInfo info = (VaClsInfo)cnst;
  162. // write the constant's type
  163. writeUByte(CNST_CLSINFO, stream);
  164. // write the class' identifier and version
  165. writeUInt(stringMap.get(info.ident), stream);
  166. writeUInt(info.major, stream);
  167. writeUInt(info.minor, stream);
  168. writeUInt(info.revision, stream);
  169. // write the flags
  170. writeUInt(info.flags0, stream);
  171. }else if(cnst instanceof VaMthInfo) {
  172. final VaMthInfo info = (VaMthInfo)cnst;
  173. // write the constant's type
  174. writeUByte(CNST_MTHINFO, stream);
  175. // write the identifier
  176. writeUInt(stringMap.get(info.ident), stream);
  177. // write the flags
  178. writeUInt(info.flags0, stream);
  179. // write the class
  180. writeUInt(cnstMap.get(info.clsInfo), stream);
  181. // write the return type
  182. writeUInt(cnstMap.get(info.returnType), stream);
  183. // write the argument count
  184. writeUInt(info.getArgumentCnt(), stream);
  185. // write the arguments
  186. for(int j = 0; j < info.getArgumentCnt(); j++) {
  187. writeUInt(cnstMap.get(info.getArgument(j)), stream);
  188. }
  189. }else if(cnst instanceof VaFldInfo) {
  190. final VaFldInfo info = (VaFldInfo)cnst;
  191. // write the constant's type
  192. writeUByte(CNST_FLDINFO, stream);
  193. // write the identifier
  194. writeUInt(stringMap.get(info.ident), stream);
  195. // write the flags
  196. writeUInt(info.flags0, stream);
  197. // write the class
  198. writeUInt(cnstMap.get(info.clsInfo), stream);
  199. // write the type
  200. writeUInt(cnstMap.get(info.datatype), stream);
  201. }else if(cnst instanceof VaDatatype.DtPrimitive) {
  202. final VaDatatype.DtPrimitive type
  203. = (VaDatatype.DtPrimitive)cnst;
  204. // write the constant's type
  205. writeUByte(CNST_PRIMTYPE, stream);
  206. // write the primitive id
  207. writeUByte(type.identity, stream);
  208. }else if(cnst instanceof VaDatatype.DtArray) {
  209. final VaDatatype.DtArray type = (VaDatatype.DtArray)cnst;
  210. // write the constant's type
  211. writeUByte(CNST_ARRTYPE, stream);
  212. // write the base type and flag fields
  213. writeUInt(cnstMap.get(type.basetype), stream);
  214. writeUInt(type.flags0, stream);
  215. }else if(cnst instanceof VaDatatype.DtClass) {
  216. final VaDatatype.DtClass type = (VaDatatype.DtClass)cnst;
  217. // write the constant's type
  218. writeUByte(CNST_CLSTYPE, stream);
  219. // write the class info
  220. writeUInt(cnstMap.get(type.clsInfo), stream);
  221. }else if(cnst instanceof VaDatatype.DtDelegate) {
  222. final VaDatatype.DtDelegate type = (VaDatatype.DtDelegate)cnst;
  223. // write the constant's type
  224. writeUByte(CNST_DLGTYPE, stream);
  225. // write the return type
  226. writeUInt(cnstMap.get(type.returnType), stream);
  227. writeUInt(type.getArgumentCnt(), stream);
  228. // write the argument types
  229. for(int j = 0; j < type.getArgumentCnt(); j++)
  230. writeUInt(cnstMap.get(type.getArgument(j)), stream);
  231. }else if(cnst instanceof VaLiteral.LitNull) {
  232. // write the constant's type
  233. writeUByte(CNST_LIT_NULL, stream);
  234. }else if(cnst instanceof VaLiteral.LitUInt) {
  235. final VaLiteral.LitUInt literal = (VaLiteral.LitUInt)cnst;
  236. // write the constant's type
  237. writeUByte(CNST_UINT_LITERAL, stream);
  238. // write the value
  239. writeUInt(literal.value, stream);
  240. }else if(cnst instanceof VaLiteral.LitChar) {
  241. final VaLiteral.LitChar literal = (VaLiteral.LitChar)cnst;
  242. // write the constant's type
  243. writeUByte(CNST_CHAR_LITERAL, stream);
  244. // write the value
  245. writeUInt((int)literal.value, stream);
  246. }else if(cnst instanceof VaLiteral.LitBoolean) {
  247. final VaLiteral.LitBoolean literal = (VaLiteral.LitBoolean)cnst;
  248. // write the constant's type
  249. writeUByte(CNST_LIT_BOOLEAN, stream);
  250. // write the value
  251. writeUByte((byte)(literal.value ? 1 : 0), stream);
  252. }else if(cnst instanceof VaLiteral.LitCharArray) {
  253. final VaLiteral.LitCharArray literal = (VaLiteral.LitCharArray)cnst;
  254. // write the constant's type
  255. writeUByte(CNST_CARR_LITERAL, stream);
  256. // write the char count
  257. writeUInt(literal.size(), stream);
  258. // write the chars
  259. for(int j = 0; j < literal.size(); j++)
  260. writeUInt(literal.get(j), stream);
  261. }else{
  262. throw new ValibException("Unknown constant " + cnst.getClass().getSimpleName());
  263. }
  264. }
  265. // write the classes count
  266. writeUInt(classCnt, stream);
  267. // write the classes
  268. final Iterator<VaClsInfo> clsiter = image.classIterator();
  269. while(clsiter.hasNext()) {
  270. final VaClsInfo clsinfo = clsiter.next();
  271. final VaClass cls = image.getClass(clsinfo);
  272. // write the class info
  273. writeUInt(cnstMap.get(clsinfo), stream);
  274. // write the parent info
  275. if(cls.parentInfo != null) {
  276. writeUInt(cnstMap.get(cls.parentInfo), stream);
  277. }else{
  278. writeUInt(CNST_NULL, stream);
  279. }
  280. // write the method count
  281. writeUInt(cls.getMethodCnt(), stream);
  282. // write the methods
  283. for(int i = 0; i < cls.getMethodCnt(); i++) {
  284. writeUInt(cnstMap.get(cls.getMethod(i)), stream);
  285. }
  286. // write the field count
  287. writeUInt(cls.getFieldCnt(), stream);
  288. // write the fields
  289. for(int i = 0; i < cls.getFieldCnt(); i++) {
  290. writeUInt(cnstMap.get(cls.getField(i)), stream);
  291. }
  292. }
  293. // write the section count
  294. writeUInt(methodCnt, stream);
  295. final Iterator<VaMthInfo> mthiter = image.methodIterator();
  296. while(mthiter.hasNext()) {
  297. final VaMthInfo mthinfo = mthiter.next();
  298. final VaProcedure procedure = image.getMethod(mthinfo);
  299. // write the method description
  300. writeUInt(cnstMap.get(mthinfo), stream);
  301. // write the procedure
  302. writeProcedure(procedure, stream);
  303. }
  304. }
  305. private void writeProcedure(final VaProcedure procedure,
  306. final OutputStream stream) throws ValibException {
  307. // write the frame count
  308. writeUInt(procedure.getFrameCnt(), stream);
  309. for(int j = 0; j < procedure.getFrameCnt(); j++) {
  310. final VaFrame frame = procedure.getFrame(j);
  311. // write the argument count
  312. writeUInt(frame.argumentCnt, stream);
  313. // write the register count
  314. writeUInt(frame.getRegisterCnt(), stream);
  315. // write the register types
  316. for(int k = 0; k < frame.getRegisterCnt(); k++)
  317. writeUInt(cnstMap.get(frame.getRegister(k)), stream);
  318. // write the instruction count
  319. writeUInt(frame.getInstCnt(), stream);
  320. // write the instructions
  321. for(int k = 0; k < frame.getInstCnt(); k++) {
  322. final VaInst opcode = frame.getInst(k);
  323. if(opcode instanceof VaInst.InstReturn) {
  324. final VaInst.InstReturn inst = (VaInst.InstReturn)opcode;
  325. writeUByte(OPCODE_RETURN, stream);
  326. writeUInt(inst.register, stream);
  327. }else if(opcode instanceof VaInst.InstLoad) {
  328. final VaInst.InstLoad inst = (VaInst.InstLoad)opcode;
  329. writeUByte(OPCODE_LOAD, stream);
  330. writeUInt(cnstMap.get(inst.literal), stream);
  331. }else if(opcode instanceof VaInst.InstInvoke) {
  332. final VaInst.InstInvoke inst = (VaInst.InstInvoke)opcode;
  333. if(inst.virtual && inst.result) {
  334. writeUByte(OPCODE_INVOKE_VIRT_RES, stream);
  335. }else if(inst.virtual && !inst.result) {
  336. writeUByte(OPCODE_INVOKE_VIRT_VOID, stream);
  337. }else if(!inst.virtual && inst.result) {
  338. writeUByte(OPCODE_INVOKE_STAT_RES, stream);
  339. }else if(!inst.virtual && !inst.result){
  340. writeUByte(OPCODE_INVOKE_STAT_VOID, stream);
  341. }
  342. if(inst.mthInfo == null) {
  343. writeUInt(0, stream);
  344. }else{
  345. writeUInt(cnstMap.get(inst.mthInfo), stream);
  346. }
  347. writeRegister(inst.object, stream);
  348. writeUInt(inst.getArgumentCnt(), stream);
  349. for(int i = 0; i < inst.getArgumentCnt(); i++)
  350. writeRegister(inst.getArgument(i), stream);
  351. }else if(opcode instanceof VaInst.InstBinOperation) {
  352. final VaInst.InstBinOperation inst = (VaInst.InstBinOperation)opcode;
  353. if(inst.operator == VaInst.InstBinOperation.OP_ARITH_ADD) {
  354. writeUByte(OPCODE_BINOP_ARITH_ADD, stream);
  355. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SUB) {
  356. writeUByte(OPCODE_BINOP_ARITH_SUB, stream);
  357. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_MUL) {
  358. writeUByte(OPCODE_BINOP_ARITH_MUL, stream);
  359. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_DIV) {
  360. writeUByte(OPCODE_BINOP_ARITH_DIV, stream);
  361. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_MOD) {
  362. writeUByte(OPCODE_BINOP_ARITH_MOD, stream);
  363. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_OR) {
  364. writeUByte(OPCODE_BINOP_ARITH_OR, stream);
  365. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_AND) {
  366. writeUByte(OPCODE_BINOP_ARITH_AND, stream);
  367. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_XOR) {
  368. writeUByte(OPCODE_BINOP_ARITH_XOR, stream);
  369. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SHL) {
  370. writeUByte(OPCODE_BINOP_ARITH_SHL, stream);
  371. }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SHR) {
  372. writeUByte(OPCODE_BINOP_ARITH_SHR, stream);
  373. }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_EQUALS) {
  374. writeUByte(OPCODE_BINOP_SETIF_EQUALS, stream);
  375. }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_ABOVE) {
  376. writeUByte(OPCODE_BINOP_SETIF_ABOVE, stream);
  377. }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_BELOW) {
  378. writeUByte(OPCODE_BINOP_SETIF_BELOW, stream);
  379. }else{
  380. throw new UnsupportedOperationException("Invalid operator for InstBinOperation");
  381. }
  382. writeUInt(inst.left, stream);
  383. writeUInt(inst.right, stream);
  384. }else if(opcode instanceof VaInst.InstUnOperation) {
  385. final VaInst.InstUnOperation inst = (VaInst.InstUnOperation)opcode;
  386. if(inst.operator == VaInst.InstUnOperation.OP_ARITH_NOT) {
  387. writeUByte(OPCODE_UNOP_ARITH_NOT, stream);
  388. }else if(inst.operator == VaInst.InstUnOperation.OP_ARITH_NEG) {
  389. writeUByte(OPCODE_UNOP_ARITH_NEG, stream);
  390. }else if(inst.operator == VaInst.InstUnOperation.OP_ARR_SIZE) {
  391. writeUByte(OPCODE_UNOP_ARR_SIZE, stream);
  392. }
  393. writeUInt(inst.operand, stream);
  394. }else if(opcode instanceof VaInst.InstJump) {
  395. final VaInst.InstJump inst = (VaInst.InstJump)opcode;
  396. writeUByte(OPCODE_JUMP, stream);
  397. writeUInt(inst.frameId, stream);
  398. writeRegister(inst.register, stream);
  399. writeUInt(inst.getArgumentCnt(), stream);
  400. for(int i = 0; i < inst.getArgumentCnt(); i++)
  401. writeRegister(inst.getArgument(i), stream);
  402. }else if(opcode instanceof VaInst.InstCreateObject) {
  403. final VaInst.InstCreateObject inst = (VaInst.InstCreateObject)opcode;
  404. writeUByte(OPCODE_CREATE_OBJECT, stream);
  405. writeUInt(cnstMap.get(inst.datatype), stream);
  406. }else if(opcode instanceof VaInst.InstCreateArray) {
  407. final VaInst.InstCreateArray inst = (VaInst.InstCreateArray)opcode;
  408. writeUByte(OPCODE_CREATE_ARRAY, stream);
  409. writeUInt(cnstMap.get(inst.datatype), stream);
  410. writeUInt(inst.size, stream);
  411. }else if(opcode instanceof VaInst.InstArrAccess) {
  412. final VaInst.InstArrAccess inst = (VaInst.InstArrAccess)opcode;
  413. if(inst.operator == VaInst.InstArrAccess.OP_LOAD) {
  414. writeUByte(OPCODE_ARRACC_LOAD, stream);
  415. }else if(inst.operator == VaInst.InstArrAccess.OP_STORE) {
  416. writeUByte(OPCODE_ARRACC_STORE, stream);
  417. }
  418. writeUInt(inst.array, stream);
  419. writeUInt(inst.index, stream);
  420. writeUInt(inst.operand, stream);
  421. }else if(opcode instanceof VaInst.InstFldAccess) {
  422. final VaInst.InstFldAccess inst = (VaInst.InstFldAccess)opcode;
  423. if(inst.operator == VaInst.InstFldAccess.OP_LOAD) {
  424. writeUByte(OPCODE_FLDACC_LOAD, stream);
  425. }else if(inst.operator == VaInst.InstFldAccess.OP_STORE) {
  426. writeUByte(OPCODE_FLDACC_STORE, stream);
  427. }
  428. writeUInt(cnstMap.get(inst.fldInfo), stream);
  429. writeUInt(inst.object, stream);
  430. writeUInt(inst.operand, stream);
  431. }else if(opcode instanceof VaInst.InstCast) {
  432. final VaInst.InstCast inst = (VaInst.InstCast)opcode;
  433. writeUByte(OPCODE_CAST, stream);
  434. writeUInt(cnstMap.get(inst.datatype), stream);
  435. writeUInt(inst.source, stream);
  436. }else if(opcode instanceof VaInst.InstInstanceof) {
  437. final VaInst.InstInstanceof inst = (VaInst.InstInstanceof)opcode;
  438. writeUByte(OPCODE_INSTANCEOF, stream);
  439. writeUInt(cnstMap.get(inst.datatype), stream);
  440. writeUInt(inst.object, stream);
  441. }else if(opcode instanceof VaInst.InstDlgConstruct) {
  442. final VaInst.InstDlgConstruct inst
  443. = (VaInst.InstDlgConstruct)opcode;
  444. writeUByte(OPCODE_DLG_CONSTRUCT, stream);
  445. writeUInt(cnstMap.get(inst.method), stream);
  446. writeUInt(inst.object, stream);
  447. }else if(opcode instanceof VaInst.InstCatch) {
  448. final VaInst.InstCatch inst = (VaInst.InstCatch)opcode;
  449. writeUByte(OPCODE_CATCH, stream);
  450. writeUInt(inst.frame, stream);
  451. writeUInt(inst.getArgumentCnt(), stream);
  452. for(int i = 0; i < inst.getArgumentCnt(); i++)
  453. writeUInt(inst.getArgument(i), stream);
  454. writeProcedure(inst.procedure, stream);
  455. }else if(opcode instanceof VaInst.InstThrow) {
  456. final VaInst.InstThrow inst = (VaInst.InstThrow)opcode;
  457. writeUByte(OPCODE_THROW, stream);
  458. writeUInt(inst.exception, stream);
  459. }else if(opcode instanceof VaInst.InstPass) {
  460. final VaInst.InstPass inst = (VaInst.InstPass)opcode;
  461. writeUByte(OPCODE_PASS, stream);
  462. writeUInt(inst.argument, stream);
  463. writeUInt(inst.register, stream);
  464. }else if(opcode instanceof VaInst.InstLeave) {
  465. writeUByte(OPCODE_LEAVE, stream);
  466. }else if(opcode instanceof VaInst.InstXNatSizeofObject) {
  467. final VaInst.InstXNatSizeofObject inst = (VaInst.InstXNatSizeofObject)opcode;
  468. writeUByte(OPCODE_EXT0, stream);
  469. writeUInt(EXT0_XNAT_SIZEOF_OBJECT, stream);
  470. writeUInt(cnstMap.get(inst.datatype), stream);
  471. }else if(opcode instanceof VaInst.InstXNatMthAddress) {
  472. final VaInst.InstXNatMthAddress inst = (VaInst.InstXNatMthAddress)opcode;
  473. writeUByte(OPCODE_EXT0, stream);
  474. writeUInt(EXT0_XNAT_METHOD_ADDRESS, stream);
  475. writeUInt(cnstMap.get(inst.method), stream);
  476. }else if(opcode instanceof VaInst.InstXNatAddressCast) {
  477. final VaInst.InstXNatAddressCast inst = (VaInst.InstXNatAddressCast)opcode;
  478. writeUByte(OPCODE_EXT0, stream);
  479. writeUInt(EXT0_XNAT_ADDRESS_CAST, stream);
  480. writeUInt(cnstMap.get(inst.datatype), stream);
  481. writeUInt(inst.address, stream);
  482. }else if(opcode instanceof VaInst.InstXNatAddressOf) {
  483. final VaInst.InstXNatAddressOf inst = (VaInst.InstXNatAddressOf)opcode;
  484. writeUByte(OPCODE_EXT0, stream);
  485. writeUInt(EXT0_XNAT_ADDRESS_OF, stream);
  486. writeUInt(inst.address, stream);
  487. writeUInt(inst.object, stream);
  488. }else if(opcode instanceof VaInst.InstXNatMakeDelegate) {
  489. final VaInst.InstXNatMakeDelegate inst = (VaInst.InstXNatMakeDelegate)opcode;
  490. writeUByte(OPCODE_EXT0, stream);
  491. writeUInt(EXT0_XNAT_MAKE_DELEGATE, stream);
  492. writeUInt(cnstMap.get(inst.datatype), stream);
  493. writeUInt(inst.method, stream);
  494. writeUInt(inst.object, stream);
  495. }else if(opcode instanceof VaInst.InstXNatRefOperation) {
  496. final VaInst.InstXNatRefOperation inst
  497. = (VaInst.InstXNatRefOperation)opcode;
  498. writeUByte(OPCODE_EXT0, stream);
  499. if(inst.operation == VaInst.InstXNatRefOperation.REF_INCREMENT) {
  500. writeUInt(EXT0_XNAT_REF_INCREMENT, stream);
  501. }else{
  502. writeUInt(EXT0_XNAT_REF_DECREMENT, stream);
  503. }
  504. writeUInt(inst.register, stream);
  505. }else if(opcode instanceof VaInst.InstXAtomCas) {
  506. final VaInst.InstXAtomCas inst = (VaInst.InstXAtomCas)opcode;
  507. writeUByte(OPCODE_EXT0, stream);
  508. if(inst.result) {
  509. writeUInt(EXT0_XATOM_CAS_RESULT, stream);
  510. }else{
  511. writeUInt(EXT0_XATOM_CAS_VOID, stream);
  512. }
  513. writeUInt(cnstMap.get(inst.field), stream);
  514. writeUInt(inst.object, stream);
  515. writeUInt(inst.source, stream);
  516. writeUInt(inst.value, stream);
  517. }else if(opcode instanceof VaInst.InstXPerfArrayCopy) {
  518. final VaInst.InstXPerfArrayCopy inst = (VaInst.InstXPerfArrayCopy)opcode;
  519. writeUByte(OPCODE_EXT0, stream);
  520. writeUInt(EXT0_XPERF_ARRAY_COPY, stream);
  521. writeUInt(inst.dest, stream);
  522. writeUInt(inst.source, stream);
  523. writeUInt(inst.destOffset, stream);
  524. writeUInt(inst.sourceOffset, stream);
  525. writeUInt(inst.size, stream);
  526. }else{
  527. throw new UnsupportedOperationException("Invalid instruction");
  528. }
  529. }
  530. }
  531. }
  532. private void analyzeClass(VaClass cls) throws ValibException {
  533. if(cls.parentInfo != null)
  534. mergeConst(cls.parentInfo);
  535. // merge the method descs
  536. for(int i = 0; i < cls.getMethodCnt(); i++)
  537. mergeConst(cls.getMethod(i));
  538. // merge the field desc
  539. for(int i = 0; i < cls.getFieldCnt(); i++)
  540. mergeConst(cls.getField(i));
  541. }
  542. private void analyzeSection(VaProcedure procedure) throws ValibException {
  543. for(int i = 0; i < procedure.getFrameCnt(); i++) {
  544. final VaFrame frame = procedure.getFrame(i);
  545. for(int j = 0; j < frame.getRegisterCnt(); j++)
  546. mergeConst(frame.getRegister(j));
  547. for(int j = 0; j < frame.getInstCnt(); j++) {
  548. final VaInst opcode = frame.getInst(j);
  549. if(opcode instanceof VaInst.InstLoad) {
  550. final VaInst.InstLoad inst = (VaInst.InstLoad)opcode;
  551. mergeConst(inst.literal);
  552. }else if(opcode instanceof VaInst.InstInvoke) {
  553. final VaInst.InstInvoke inst = (VaInst.InstInvoke)opcode;
  554. if(inst.mthInfo != null)
  555. mergeConst(inst.mthInfo);
  556. }else if(opcode instanceof VaInst.InstFldAccess) {
  557. final VaInst.InstFldAccess inst = (VaInst.InstFldAccess)opcode;
  558. mergeConst(inst.fldInfo);
  559. }else if(opcode instanceof VaInst.InstCreateObject) {
  560. final VaInst.InstCreateObject inst = (VaInst.InstCreateObject)opcode;
  561. mergeConst(inst.datatype);
  562. }else if(opcode instanceof VaInst.InstCreateArray) {
  563. final VaInst.InstCreateArray inst = (VaInst.InstCreateArray)opcode;
  564. mergeConst(inst.datatype);
  565. }else if(opcode instanceof VaInst.InstInstanceof) {
  566. final VaInst.InstInstanceof inst = (VaInst.InstInstanceof)opcode;
  567. mergeConst(inst.datatype);
  568. }else if(opcode instanceof VaInst.InstCast) {
  569. final VaInst.InstCast inst = (VaInst.InstCast)opcode;
  570. mergeConst(inst.datatype);
  571. }else if(opcode instanceof VaInst.InstDlgConstruct) {
  572. final VaInst.InstDlgConstruct inst
  573. = (VaInst.InstDlgConstruct)opcode;
  574. mergeConst(inst.method);
  575. }else if(opcode instanceof VaInst.InstXNatMthAddress) {
  576. final VaInst.InstXNatMthAddress inst
  577. = (VaInst.InstXNatMthAddress)opcode;
  578. mergeConst(inst.method);
  579. }else if(opcode instanceof VaInst.InstXNatSizeofObject) {
  580. final VaInst.InstXNatSizeofObject inst
  581. = (VaInst.InstXNatSizeofObject)opcode;
  582. mergeConst(inst.datatype);
  583. }else if(opcode instanceof VaInst.InstXNatAddressCast) {
  584. final VaInst.InstXNatAddressCast inst
  585. = (VaInst.InstXNatAddressCast)opcode;
  586. mergeConst(inst.datatype);
  587. }else if(opcode instanceof VaInst.InstXNatMakeObject) {
  588. final VaInst.InstXNatMakeObject inst
  589. = (VaInst.InstXNatMakeObject)opcode;
  590. mergeConst(inst.clsInfo);
  591. }else if(opcode instanceof VaInst.InstXNatMakeArray) {
  592. final VaInst.InstXNatMakeArray inst
  593. = (VaInst.InstXNatMakeArray)opcode;
  594. mergeConst(inst.datatype);
  595. }else if(opcode instanceof VaInst.InstXAtomCas) {
  596. final VaInst.InstXAtomCas inst
  597. = (VaInst.InstXAtomCas)opcode;
  598. mergeConst(inst.field);
  599. }else if(opcode instanceof VaInst.InstXNatMakeDelegate) {
  600. final VaInst.InstXNatMakeDelegate inst
  601. = (VaInst.InstXNatMakeDelegate)opcode;
  602. mergeConst(inst.datatype);
  603. }
  604. }
  605. }
  606. }
  607. // adds "cnst" and all constants that depend on "cnst" to the constant map
  608. private void mergeConst(Object cnst) throws ValibException {
  609. if(cnstMap.containsKey(cnst))
  610. return;
  611. // merge dependancies
  612. if(cnst instanceof VaClsInfo) {
  613. final VaClsInfo info = (VaClsInfo)cnst;
  614. mergeString(info.ident);
  615. }else if(cnst instanceof VaMthInfo) {
  616. final VaMthInfo info = (VaMthInfo)cnst;
  617. mergeString(info.ident);
  618. mergeConst(info.returnType);
  619. // merge the arguments
  620. for(int i = 0; i < info.getArgumentCnt(); i++)
  621. mergeConst(info.getArgument(i));
  622. }else if(cnst instanceof VaFldInfo) {
  623. final VaFldInfo info = (VaFldInfo)cnst;
  624. mergeString(info.ident);
  625. mergeConst(info.datatype);
  626. // merge the literal
  627. if(info.literal != null)
  628. mergeConst(info.literal);
  629. }else if(cnst instanceof VaDatatype.DtClass) {
  630. final VaDatatype.DtClass type = (VaDatatype.DtClass)cnst;
  631. mergeConst(type.clsInfo);
  632. }else if(cnst instanceof VaDatatype.DtArray) {
  633. final VaDatatype.DtArray type = (VaDatatype.DtArray)cnst;
  634. mergeConst(type.basetype);
  635. }else if(cnst instanceof VaDatatype.DtDelegate) {
  636. final VaDatatype.DtDelegate type = (VaDatatype.DtDelegate)cnst;
  637. mergeConst(type.returnType);
  638. for(int i = 0; i < type.getArgumentCnt(); i++)
  639. mergeConst(type.getArgument(i));
  640. }else if(cnst instanceof VaDatatype.DtPrimitive) {
  641. }else if(cnst instanceof VaLiteral.LitNull) {
  642. }else if(cnst instanceof VaLiteral.LitUInt) {
  643. }else if(cnst instanceof VaLiteral.LitChar) {
  644. }else if(cnst instanceof VaLiteral.LitBoolean) {
  645. }else if(cnst instanceof VaLiteral.LitCharArray) {
  646. // do nothing
  647. }else{
  648. throw new ValibException("Unknown constant " + cnst.getClass().getSimpleName());
  649. }
  650. // add the constant to the map
  651. cnstList.add(cnst);
  652. cnstMap.put(cnst, cnstList.size());
  653. }
  654. private void mergeString(final String string) {
  655. if(stringMap.containsKey(string))
  656. return;
  657. stringList.add(string);
  658. stringMap.put(string, stringList.size());
  659. }
  660. private static void writeRegister(int register,
  661. OutputStream stream) throws ValibException {
  662. if(register < 0xFF) {
  663. writeUByte((short)register, stream);
  664. }else{
  665. writeUByte((short)0xFF, stream);
  666. writeUInt(register, stream);
  667. }
  668. }
  669. private static void writeBool(boolean value,
  670. OutputStream stream) throws ValibException {
  671. if(value) {
  672. writeUByte((short)1, stream);
  673. }else{
  674. writeUByte((short)0, stream);
  675. }
  676. }
  677. // writes an unsigned integer value to a stream
  678. private static void writeUInt(long value,
  679. OutputStream stream) throws ValibException {
  680. writeUByte((short)((value & 0xFF000000L) >> 24), stream);
  681. writeUByte((short)((value & 0xFF0000L) >> 16), stream);
  682. writeUByte((short)((value & 0xFF00L) >> 8), stream);
  683. writeUByte((short)(value & 0xFFL), stream);
  684. }
  685. // writes an unsigned short value to a stream
  686. private static void writeUShort(int value,
  687. OutputStream stream) throws ValibException {
  688. writeUByte((short)((value & 0xFF00) >> 8), stream);
  689. writeUByte((short)(value & 0xFF), stream);
  690. }
  691. private static void writeUByte(short value,
  692. OutputStream stream) throws ValibException {
  693. try {
  694. stream.write(value);
  695. } catch(IOException e) {
  696. throw new ValibException("Could not write output file");
  697. }
  698. }
  699. }