You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InstructionFactory.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. package org.aspectj.apache.bcel.generic;
  2. /* ====================================================================
  3. * The Apache Software License, Version 1.1
  4. *
  5. * Copyright (c) 2001 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Apache" and "Apache Software Foundation" and
  28. * "Apache BCEL" must not be used to endorse or promote products
  29. * derived from this software without prior written permission. For
  30. * written permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * "Apache BCEL", nor may "Apache" appear in their name, without
  34. * prior written permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation. For more
  52. * information on the Apache Software Foundation, please see
  53. * <http://www.apache.org/>.
  54. */
  55. import org.aspectj.apache.bcel.Constants;
  56. import org.aspectj.apache.bcel.classfile.ConstantPool;
  57. import org.aspectj.apache.bcel.classfile.Utility;
  58. /**
  59. * Instances of this class may be used, e.g., to generate typed versions of instructions. Its main purpose is to be used as the byte
  60. * code generating backend of a compiler. You can subclass it to add your own create methods.
  61. *
  62. * @version $Id: InstructionFactory.java,v 1.7 2010/08/23 20:44:10 aclement Exp $
  63. * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  64. * @see Constants
  65. */
  66. public class InstructionFactory implements InstructionConstants {
  67. protected ClassGen cg;
  68. protected ConstantPool cp;
  69. public InstructionFactory(ClassGen cg, ConstantPool cp) {
  70. this.cg = cg;
  71. this.cp = cp;
  72. }
  73. public InstructionFactory(ClassGen cg) {
  74. this(cg, cg.getConstantPool());
  75. }
  76. public InstructionFactory(ConstantPool cp) {
  77. this(null, cp);
  78. }
  79. public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind) {
  80. return createInvoke(class_name, name, ret_type, arg_types, kind, false);
  81. }
  82. /**
  83. * Create an invoke instruction.
  84. *
  85. * @param class_name name of the called class
  86. * @param name name of the called method
  87. * @param ret_type return type of method
  88. * @param arg_types argument types of method
  89. * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, or INVOKESPECIAL
  90. * @param isInterface for an invokestatic on an interface allows us to tell this method the target is an interface
  91. * @see Constants
  92. */
  93. public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind, boolean isInterface) {
  94. String signature = Utility.toMethodSignature(ret_type, arg_types);
  95. int index;
  96. if (kind == Constants.INVOKEINTERFACE || isInterface) {
  97. index = cp.addInterfaceMethodref(class_name, name, signature);
  98. } else if (kind == Constants.INVOKEDYNAMIC){
  99. throw new IllegalStateException("NYI");
  100. } else {
  101. index = cp.addMethodref(class_name, name, signature);
  102. }
  103. switch (kind) {
  104. case Constants.INVOKESPECIAL:
  105. return new InvokeInstruction(Constants.INVOKESPECIAL, index);
  106. case Constants.INVOKEVIRTUAL:
  107. return new InvokeInstruction(Constants.INVOKEVIRTUAL, index);
  108. case Constants.INVOKESTATIC:
  109. return new InvokeInstruction(Constants.INVOKESTATIC, index);
  110. case Constants.INVOKEINTERFACE:
  111. int nargs = 0;
  112. for (Type arg_type : arg_types) {
  113. nargs += arg_type.getSize();
  114. }
  115. return new INVOKEINTERFACE(index, nargs + 1, 0);
  116. default:
  117. throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
  118. }
  119. }
  120. public InvokeInstruction createInvoke(String class_name, String name, String signature, short kind) {
  121. int index;
  122. if (kind == Constants.INVOKEINTERFACE) {
  123. index = cp.addInterfaceMethodref(class_name, name, signature);
  124. } else if (kind == Constants.INVOKEDYNAMIC){
  125. throw new IllegalStateException("NYI");
  126. } else {
  127. index = cp.addMethodref(class_name, name, signature);
  128. }
  129. switch (kind) {
  130. case Constants.INVOKESPECIAL:
  131. return new InvokeInstruction(Constants.INVOKESPECIAL, index);
  132. case Constants.INVOKEVIRTUAL:
  133. return new InvokeInstruction(Constants.INVOKEVIRTUAL, index);
  134. case Constants.INVOKESTATIC:
  135. return new InvokeInstruction(Constants.INVOKESTATIC, index);
  136. case Constants.INVOKEINTERFACE:
  137. Type[] argumentTypes = Type.getArgumentTypes(signature);
  138. int nargs = 0;
  139. for (Type argumentType : argumentTypes) {// Count size of arguments
  140. nargs += argumentType.getSize();
  141. }
  142. return new INVOKEINTERFACE(index, nargs + 1, 0);
  143. default:
  144. throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
  145. }
  146. }
  147. public static Instruction createALOAD(int n) {
  148. if (n < 4) {
  149. return new InstructionLV((short) (Constants.ALOAD_0 + n));
  150. }
  151. return new InstructionLV(Constants.ALOAD, n);
  152. }
  153. public static Instruction createASTORE(int n) {
  154. if (n < 4) {
  155. return new InstructionLV((short) (Constants.ASTORE_0 + n));
  156. }
  157. return new InstructionLV(Constants.ASTORE, n);
  158. }
  159. /**
  160. * Uses PUSH to push a constant value onto the stack.
  161. *
  162. * @param value must be of type Number, Boolean, Character or String
  163. */
  164. // OPTIMIZE callers should use the PUSH methods where possible if they know the types
  165. public Instruction createConstant(Object value) {
  166. Instruction instruction;
  167. if (value instanceof Number) {
  168. instruction = InstructionFactory.PUSH(cp, (Number) value);
  169. } else if (value instanceof String) {
  170. instruction = InstructionFactory.PUSH(cp, (String) value);
  171. } else if (value instanceof Boolean) {
  172. instruction = InstructionFactory.PUSH(cp, (Boolean) value);
  173. } else if (value instanceof Character) {
  174. instruction = InstructionFactory.PUSH(cp, (Character) value);
  175. } else if (value instanceof ObjectType) {
  176. instruction = InstructionFactory.PUSH(cp, (ObjectType) value);
  177. } else {
  178. throw new ClassGenException("Illegal type: " + value.getClass());
  179. }
  180. return instruction;
  181. }
  182. /**
  183. * Create a field instruction.
  184. *
  185. * @param class_name name of the accessed class
  186. * @param name name of the referenced field
  187. * @param type type of field
  188. * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
  189. * @see Constants
  190. */
  191. public FieldInstruction createFieldAccess(String class_name, String name, Type type, short kind) {
  192. int index;
  193. String signature = type.getSignature();
  194. index = cp.addFieldref(class_name, name, signature);
  195. switch (kind) {
  196. case Constants.GETFIELD:
  197. return new FieldInstruction(Constants.GETFIELD, index);
  198. case Constants.PUTFIELD:
  199. return new FieldInstruction(Constants.PUTFIELD, index);
  200. case Constants.GETSTATIC:
  201. return new FieldInstruction(Constants.GETSTATIC, index);
  202. case Constants.PUTSTATIC:
  203. return new FieldInstruction(Constants.PUTSTATIC, index);
  204. default:
  205. throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
  206. }
  207. }
  208. /**
  209. * Create reference to `this'
  210. */
  211. public static Instruction createThis() {
  212. return new InstructionLV(Constants.ALOAD, 0);
  213. }
  214. /**
  215. * Create typed return
  216. */
  217. public static Instruction createReturn(Type type) {
  218. switch (type.getType()) {
  219. case Constants.T_ARRAY:
  220. case Constants.T_OBJECT:
  221. return ARETURN;
  222. case Constants.T_INT:
  223. case Constants.T_SHORT:
  224. case Constants.T_BOOLEAN:
  225. case Constants.T_CHAR:
  226. case Constants.T_BYTE:
  227. return IRETURN;
  228. case Constants.T_FLOAT:
  229. return FRETURN;
  230. case Constants.T_DOUBLE:
  231. return DRETURN;
  232. case Constants.T_LONG:
  233. return LRETURN;
  234. case Constants.T_VOID:
  235. return RETURN;
  236. default:
  237. throw new RuntimeException("Invalid type: " + type);
  238. }
  239. }
  240. /**
  241. * @param size size of operand, either 1 (int, e.g.) or 2 (double)
  242. */
  243. public static Instruction createPop(int size) {
  244. return (size == 2) ? POP2 : POP;
  245. }
  246. /**
  247. * @param size size of operand, either 1 (int, e.g.) or 2 (double)
  248. */
  249. public static Instruction createDup(int size) {
  250. return (size == 2) ? DUP2 : DUP;
  251. }
  252. /**
  253. * @param size size of operand, either 1 (int, e.g.) or 2 (double)
  254. */
  255. public static Instruction createDup_2(int size) {
  256. return (size == 2) ? DUP2_X2 : DUP_X2;
  257. }
  258. /**
  259. * @param size size of operand, either 1 (int, e.g.) or 2 (double)
  260. */
  261. public static Instruction createDup_1(int size) {
  262. return (size == 2) ? DUP2_X1 : DUP_X1;
  263. }
  264. /**
  265. * @param index index of local variable
  266. */
  267. public static InstructionLV createStore(Type type, int index) {
  268. switch (type.getType()) {
  269. case Constants.T_BOOLEAN:
  270. case Constants.T_CHAR:
  271. case Constants.T_BYTE:
  272. case Constants.T_SHORT:
  273. case Constants.T_INT:
  274. return new InstructionLV(Constants.ISTORE, index);
  275. case Constants.T_FLOAT:
  276. return new InstructionLV(Constants.FSTORE, index);
  277. case Constants.T_DOUBLE:
  278. return new InstructionLV(Constants.DSTORE, index);
  279. case Constants.T_LONG:
  280. return new InstructionLV(Constants.LSTORE, index);
  281. case Constants.T_ARRAY:
  282. case Constants.T_OBJECT:
  283. return new InstructionLV(Constants.ASTORE, index);
  284. default:
  285. throw new RuntimeException("Invalid type " + type);
  286. }
  287. }
  288. /**
  289. * @param index index of local variable
  290. */
  291. public static InstructionLV createLoad(Type type, int index) {
  292. switch (type.getType()) {
  293. case Constants.T_BOOLEAN:
  294. case Constants.T_CHAR:
  295. case Constants.T_BYTE:
  296. case Constants.T_SHORT:
  297. case Constants.T_INT:
  298. return new InstructionLV(Constants.ILOAD, index);
  299. case Constants.T_FLOAT:
  300. return new InstructionLV(Constants.FLOAD, index);
  301. case Constants.T_DOUBLE:
  302. return new InstructionLV(Constants.DLOAD, index);
  303. case Constants.T_LONG:
  304. return new InstructionLV(Constants.LLOAD, index);
  305. case Constants.T_ARRAY:
  306. case Constants.T_OBJECT:
  307. return new InstructionLV(Constants.ALOAD, index);
  308. default:
  309. throw new RuntimeException("Invalid type " + type);
  310. }
  311. }
  312. /**
  313. * @param type type of elements of array, i.e., array.getElementType()
  314. */
  315. public static Instruction createArrayLoad(Type type) {
  316. switch (type.getType()) {
  317. case Constants.T_BOOLEAN:
  318. case Constants.T_BYTE:
  319. return BALOAD;
  320. case Constants.T_CHAR:
  321. return CALOAD;
  322. case Constants.T_SHORT:
  323. return SALOAD;
  324. case Constants.T_INT:
  325. return IALOAD;
  326. case Constants.T_FLOAT:
  327. return FALOAD;
  328. case Constants.T_DOUBLE:
  329. return DALOAD;
  330. case Constants.T_LONG:
  331. return LALOAD;
  332. case Constants.T_ARRAY:
  333. case Constants.T_OBJECT:
  334. return AALOAD;
  335. default:
  336. throw new RuntimeException("Invalid type " + type);
  337. }
  338. }
  339. /**
  340. * @param type type of elements of array, i.e., array.getElementType()
  341. */
  342. public static Instruction createArrayStore(Type type) {
  343. switch (type.getType()) {
  344. case Constants.T_BOOLEAN:
  345. case Constants.T_BYTE:
  346. return BASTORE;
  347. case Constants.T_CHAR:
  348. return CASTORE;
  349. case Constants.T_SHORT:
  350. return SASTORE;
  351. case Constants.T_INT:
  352. return IASTORE;
  353. case Constants.T_FLOAT:
  354. return FASTORE;
  355. case Constants.T_DOUBLE:
  356. return DASTORE;
  357. case Constants.T_LONG:
  358. return LASTORE;
  359. case Constants.T_ARRAY:
  360. case Constants.T_OBJECT:
  361. return AASTORE;
  362. default:
  363. throw new RuntimeException("Invalid type " + type);
  364. }
  365. }
  366. private static final char[] shortNames = { 'C', 'F', 'D', 'B', 'S', 'I', 'L' };
  367. /**
  368. * Create conversion operation for two stack operands, this may be an I2C, instruction, e.g., if the operands are basic types
  369. * and CHECKCAST if they are reference types.
  370. */
  371. public Instruction createCast(Type src_type, Type dest_type) {
  372. if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
  373. byte dest = dest_type.getType();
  374. byte src = src_type.getType();
  375. if (dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE || src == Constants.T_SHORT)) {
  376. src = Constants.T_INT;
  377. }
  378. if (src == Constants.T_DOUBLE) {
  379. switch (dest) {
  380. case Constants.T_FLOAT:
  381. return InstructionConstants.D2F;
  382. case Constants.T_INT:
  383. return InstructionConstants.D2I;
  384. case Constants.T_LONG:
  385. return InstructionConstants.D2L;
  386. }
  387. } else if (src == Constants.T_FLOAT) {
  388. switch (dest) {
  389. case Constants.T_DOUBLE:
  390. return InstructionConstants.F2D;
  391. case Constants.T_INT:
  392. return InstructionConstants.F2I;
  393. case Constants.T_LONG:
  394. return InstructionConstants.F2L;
  395. }
  396. } else if (src == Constants.T_INT) {
  397. switch (dest) {
  398. case Constants.T_BYTE:
  399. return InstructionConstants.I2B;
  400. case Constants.T_CHAR:
  401. return InstructionConstants.I2C;
  402. case Constants.T_DOUBLE:
  403. return InstructionConstants.I2D;
  404. case Constants.T_FLOAT:
  405. return InstructionConstants.I2F;
  406. case Constants.T_LONG:
  407. return InstructionConstants.I2L;
  408. case Constants.T_SHORT:
  409. return InstructionConstants.I2S;
  410. }
  411. } else if (src == Constants.T_LONG) {
  412. switch (dest) {
  413. case Constants.T_DOUBLE:
  414. return InstructionConstants.L2D;
  415. case Constants.T_FLOAT:
  416. return InstructionConstants.L2F;
  417. case Constants.T_INT:
  418. return InstructionConstants.L2I;
  419. }
  420. }
  421. // String name = "org.aspectj.apache.bcel.generic." + short_names[src - Constants.T_CHAR] +
  422. // "2" + short_names[dest - Constants.T_CHAR];
  423. // Instruction i = null;
  424. // try {
  425. // i = (Instruction)java.lang.Class.forName(name).newInstance();
  426. // } catch(Exception e) {
  427. // throw new RuntimeException("Could not find instruction: " + name);
  428. // }
  429. return null;
  430. // return i;
  431. } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
  432. if (dest_type instanceof ArrayType) {
  433. return new InstructionCP(Constants.CHECKCAST, cp.addArrayClass((ArrayType) dest_type));
  434. } else {
  435. return new InstructionCP(Constants.CHECKCAST, cp.addClass(((ObjectType) dest_type).getClassName()));
  436. }
  437. } else {
  438. throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
  439. }
  440. }
  441. public FieldInstruction createGetField(String class_name, String name, Type t) {
  442. return new FieldInstruction(Constants.GETFIELD, cp.addFieldref(class_name, name, t.getSignature()));
  443. }
  444. public FieldInstruction createGetStatic(String class_name, String name, Type t) {
  445. return new FieldInstruction(Constants.GETSTATIC, cp.addFieldref(class_name, name, t.getSignature()));
  446. }
  447. public FieldInstruction createPutField(String class_name, String name, Type t) {
  448. return new FieldInstruction(Constants.PUTFIELD, cp.addFieldref(class_name, name, t.getSignature()));
  449. }
  450. public FieldInstruction createPutStatic(String class_name, String name, Type t) {
  451. return new FieldInstruction(Constants.PUTSTATIC, cp.addFieldref(class_name, name, t.getSignature()));
  452. }
  453. public Instruction createCheckCast(ReferenceType t) {
  454. if (t instanceof ArrayType) {
  455. return new InstructionCP(Constants.CHECKCAST, cp.addArrayClass((ArrayType) t));
  456. } else {
  457. return new InstructionCP(Constants.CHECKCAST, cp.addClass((ObjectType) t));
  458. }
  459. }
  460. public Instruction createInstanceOf(ReferenceType t) {
  461. if (t instanceof ArrayType) {
  462. return new InstructionCP(Constants.INSTANCEOF, cp.addArrayClass((ArrayType) t));
  463. } else {
  464. return new InstructionCP(Constants.INSTANCEOF, cp.addClass((ObjectType) t));
  465. }
  466. }
  467. public Instruction createNew(ObjectType t) {
  468. return new InstructionCP(Constants.NEW, cp.addClass(t));
  469. }
  470. public Instruction createNew(String s) {
  471. return createNew(new ObjectType(s));
  472. }
  473. /**
  474. * Create new array of given size and type.
  475. *
  476. * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction
  477. */
  478. public Instruction createNewArray(Type t, short dim) {
  479. if (dim == 1) {
  480. if (t instanceof ObjectType) {
  481. return new InstructionCP(Constants.ANEWARRAY, cp.addClass((ObjectType) t));
  482. } else if (t instanceof ArrayType) {
  483. return new InstructionCP(Constants.ANEWARRAY, cp.addArrayClass((ArrayType) t));
  484. } else {
  485. return new InstructionByte(Constants.NEWARRAY, ((BasicType) t).getType());
  486. }
  487. } else {
  488. ArrayType at;
  489. if (t instanceof ArrayType) {
  490. at = (ArrayType) t;
  491. } else {
  492. at = new ArrayType(t, dim);
  493. }
  494. return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
  495. }
  496. }
  497. /**
  498. * Create "null" value for reference types, 0 for basic types like int
  499. */
  500. public static Instruction createNull(Type type) {
  501. switch (type.getType()) {
  502. case Constants.T_ARRAY:
  503. case Constants.T_OBJECT:
  504. return ACONST_NULL;
  505. case Constants.T_INT:
  506. case Constants.T_SHORT:
  507. case Constants.T_BOOLEAN:
  508. case Constants.T_CHAR:
  509. case Constants.T_BYTE:
  510. return ICONST_0;
  511. case Constants.T_FLOAT:
  512. return FCONST_0;
  513. case Constants.T_DOUBLE:
  514. return DCONST_0;
  515. case Constants.T_LONG:
  516. return LCONST_0;
  517. case Constants.T_VOID:
  518. return NOP;
  519. default:
  520. throw new RuntimeException("Invalid type: " + type);
  521. }
  522. }
  523. /**
  524. * Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH. For those you should use the SWITCH compound
  525. * instruction.
  526. */
  527. public static InstructionBranch createBranchInstruction(short opcode, InstructionHandle target) {
  528. switch (opcode) {
  529. case Constants.IFEQ:
  530. return new InstructionBranch(Constants.IFEQ, target);
  531. case Constants.IFNE:
  532. return new InstructionBranch(Constants.IFNE, target);
  533. case Constants.IFLT:
  534. return new InstructionBranch(Constants.IFLT, target);
  535. case Constants.IFGE:
  536. return new InstructionBranch(Constants.IFGE, target);
  537. case Constants.IFGT:
  538. return new InstructionBranch(Constants.IFGT, target);
  539. case Constants.IFLE:
  540. return new InstructionBranch(Constants.IFLE, target);
  541. case Constants.IF_ICMPEQ:
  542. return new InstructionBranch(Constants.IF_ICMPEQ, target);
  543. case Constants.IF_ICMPNE:
  544. return new InstructionBranch(Constants.IF_ICMPNE, target);
  545. case Constants.IF_ICMPLT:
  546. return new InstructionBranch(Constants.IF_ICMPLT, target);
  547. case Constants.IF_ICMPGE:
  548. return new InstructionBranch(Constants.IF_ICMPGE, target);
  549. case Constants.IF_ICMPGT:
  550. return new InstructionBranch(Constants.IF_ICMPGT, target);
  551. case Constants.IF_ICMPLE:
  552. return new InstructionBranch(Constants.IF_ICMPLE, target);
  553. case Constants.IF_ACMPEQ:
  554. return new InstructionBranch(Constants.IF_ACMPEQ, target);
  555. case Constants.IF_ACMPNE:
  556. return new InstructionBranch(Constants.IF_ACMPNE, target);
  557. case Constants.GOTO:
  558. return new InstructionBranch(Constants.GOTO, target);
  559. case Constants.JSR:
  560. return new InstructionBranch(Constants.JSR, target);
  561. case Constants.IFNULL:
  562. return new InstructionBranch(Constants.IFNULL, target);
  563. case Constants.IFNONNULL:
  564. return new InstructionBranch(Constants.IFNONNULL, target);
  565. case Constants.GOTO_W:
  566. return new InstructionBranch(Constants.GOTO_W, target);
  567. case Constants.JSR_W:
  568. return new InstructionBranch(Constants.JSR_W, target);
  569. default:
  570. throw new RuntimeException("Invalid opcode: " + opcode);
  571. }
  572. }
  573. public void setClassGen(ClassGen c) {
  574. cg = c;
  575. }
  576. public ClassGen getClassGen() {
  577. return cg;
  578. }
  579. public void setConstantPool(ConstantPool c) {
  580. cp = c;
  581. }
  582. public ConstantPool getConstantPool() {
  583. return cp;
  584. }
  585. /**
  586. * Returns the right instruction for putting whatever you want onto the stack
  587. */
  588. public static Instruction PUSH(ConstantPool cp, int value) {
  589. Instruction instruction = null;
  590. if ((value >= -1) && (value <= 5)) {
  591. return INSTRUCTIONS[Constants.ICONST_0 + value];
  592. } else if ((value >= -128) && (value <= 127)) {
  593. instruction = new InstructionByte(Constants.BIPUSH, (byte) value);
  594. } else if ((value >= -32768) && (value <= 32767)) {
  595. instruction = new InstructionShort(Constants.SIPUSH, (short) value);
  596. } else // If everything fails create a Constant pool entry
  597. {
  598. int pos = cp.addInteger(value);
  599. if (pos <= Constants.MAX_BYTE) {
  600. instruction = new InstructionCP(Constants.LDC, pos);
  601. } else {
  602. instruction = new InstructionCP(Constants.LDC_W, pos);
  603. }
  604. }
  605. return instruction;
  606. }
  607. public static Instruction PUSH(ConstantPool cp, ObjectType t) {
  608. return new InstructionCP(Constants.LDC_W, cp.addClass(t));
  609. }
  610. public static Instruction PUSH(ConstantPool cp, boolean value) {
  611. return INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)];
  612. }
  613. public static Instruction PUSH(ConstantPool cp, float value) {
  614. Instruction instruction = null;
  615. if (value == 0.0) {
  616. instruction = FCONST_0;
  617. } else if (value == 1.0) {
  618. instruction = FCONST_1;
  619. } else if (value == 2.0) {
  620. instruction = FCONST_2;
  621. } else {
  622. // Create a Constant pool entry
  623. int i = cp.addFloat(value);
  624. instruction = new InstructionCP(i <= Constants.MAX_BYTE ? Constants.LDC : Constants.LDC_W, i);
  625. }
  626. return instruction;
  627. }
  628. public static Instruction PUSH(ConstantPool cp, long value) {
  629. Instruction instruction = null;
  630. if (value == 0) {
  631. instruction = LCONST_0;
  632. } else if (value == 1) {
  633. instruction = LCONST_1;
  634. } else {
  635. instruction = new InstructionCP(Constants.LDC2_W, cp.addLong(value));
  636. }
  637. return instruction;
  638. }
  639. public static Instruction PUSH(ConstantPool cp, double value) {
  640. Instruction instruction = null;
  641. if (value == 0.0) {
  642. instruction = DCONST_0;
  643. } else if (value == 1.0) {
  644. instruction = DCONST_1;
  645. } else {
  646. // Create a Constant pool entry
  647. instruction = new InstructionCP(Constants.LDC2_W, cp.addDouble(value));
  648. }
  649. return instruction;
  650. }
  651. public static Instruction PUSH(ConstantPool cp, String value) {
  652. Instruction instruction = null;
  653. if (value == null) {
  654. instruction = ACONST_NULL;
  655. } else {
  656. int i = cp.addString(value);
  657. instruction = new InstructionCP(i <= Constants.MAX_BYTE ? Constants.LDC : Constants.LDC_W, i);
  658. }
  659. return instruction;
  660. }
  661. public static Instruction PUSH(ConstantPool cp, Number value) {
  662. Instruction instruction = null;
  663. if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
  664. instruction = PUSH(cp, value.intValue());
  665. } else if (value instanceof Double) {
  666. instruction = PUSH(cp, value.doubleValue());
  667. } else if (value instanceof Float) {
  668. instruction = PUSH(cp, value.floatValue());
  669. } else if (value instanceof Long) {
  670. instruction = PUSH(cp, value.longValue());
  671. } else {
  672. throw new ClassGenException("What's this: " + value);
  673. }
  674. return instruction;
  675. }
  676. public static Instruction PUSH(ConstantPool cp, Character value) {
  677. return PUSH(cp, value.charValue());
  678. }
  679. public static Instruction PUSH(ConstantPool cp, Boolean value) {
  680. return PUSH(cp, value.booleanValue());
  681. }
  682. /**
  683. * Return a list that will load the Class object - on 1.5 or later use the class variant of ldc, whilst on earlier JVMs use the
  684. * regular Class.forName.
  685. */
  686. public InstructionList PUSHCLASS(ConstantPool cp, String className) {
  687. InstructionList iList = new InstructionList();
  688. int classIndex = cp.addClass(className);
  689. if (cg != null && cg.getMajor() >= Constants.MAJOR_1_5) {
  690. if (classIndex <= Constants.MAX_BYTE) {
  691. iList.append(new InstructionCP(Instruction.LDC, classIndex));
  692. } else {
  693. iList.append(new InstructionCP(Instruction.LDC_W, classIndex));
  694. }
  695. } else {
  696. className = className.replace('/', '.');
  697. iList.append(InstructionFactory.PUSH(cp, className));
  698. iList.append(this.createInvoke("java.lang.Class", "forName", ObjectType.CLASS, Type.STRINGARRAY1,
  699. Constants.INVOKESTATIC));
  700. }
  701. return iList;
  702. }
  703. }