1 /*
  2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jasm;
 24 
 25 import java.io.IOException;
 26 
 27 import static org.openjdk.asmtools.jasm.OpcodeTables.*;
 28 
 29 /**
 30  *
 31  */
 32 class Instr {
 33 
 34     Instr next = null;
 35     int pc;
 36     int pos;
 37     Opcode opc;
 38     Argument arg;
 39     Object arg2; // second or unusual argument
 40 
 41     public Instr(int pc, int pos, Opcode opc, Argument arg, Object arg2) {
 42         this.pc = pc;
 43         this.pos = pos;
 44         this.opc = opc;
 45         this.arg = arg;
 46         this.arg2 = arg2;
 47     }
 48 
 49     public Instr() {
 50     }
 51 
 52     public void write(CheckedDataOutputStream out, Environment env) throws IOException {
 53         OpcodeType type = opc.type();
 54         switch (type) {
 55             case NORMAL: {
 56                 if (opc == Opcode.opc_bytecode) {
 57                     out.writeByte(arg.arg);
 58                     return;
 59                 }
 60                 out.writeByte(opc.value());
 61                 int opcLen = opc.length();
 62                 if (opcLen == 1) {
 63                     return;
 64                 }
 65 
 66                 switch (opc) {
 67                     case opc_tableswitch:
 68                         ((SwitchTable) arg2).writeTableSwitch(out);
 69                         return;
 70                     case opc_lookupswitch:
 71                         ((SwitchTable) arg2).writeLookupSwitch(out);
 72                         return;
 73                 }
 74 
 75                 int iarg;
 76                 try {
 77                     iarg = arg.arg;
 78                 } catch (NullPointerException e) {
 79                     throw new Parser.CompilerError(env.errorStr("comperr.instr.nullarg", opc.parsekey()));
 80                 }
 81 //env.traceln("instr:"+opcNamesTab[opc]+" len="+opcLen+" arg:"+iarg);
 82                 switch (opc) {
 83                     case opc_jsr:
 84                     case opc_goto:
 85                     case opc_ifeq:
 86                     case opc_ifge:
 87                     case opc_ifgt:
 88                     case opc_ifle:
 89                     case opc_iflt:
 90                     case opc_ifne:
 91                     case opc_if_icmpeq:
 92                     case opc_if_icmpne:
 93                     case opc_if_icmpge:
 94                     case opc_if_icmpgt:
 95                     case opc_if_icmple:
 96                     case opc_if_icmplt:
 97                     case opc_if_acmpeq:
 98                     case opc_if_acmpne:
 99                     case opc_ifnull:
100                     case opc_ifnonnull:
101                     case opc_jsr_w:
102                     case opc_goto_w:
103                         iarg = iarg - pc;
104                         break;
105                     case opc_iinc:
106                         iarg = (iarg << 8) | (((Argument) arg2).arg & 0xFF);
107                         break;
108                     case opc_invokeinterface:
109                         iarg = ((iarg << 8) | (((Argument) arg2).arg & 0xFF)) << 8;
110                         break;
111                     case opc_invokedynamic: // JSR-292
112                         iarg = (iarg << 16);
113                         break;
114                     case opc_ldc:
115                         if ((iarg & 0xFFFFFF00) != 0) {
116                             throw new Parser.CompilerError(
117                                     env.errorStr("comperr.instr.arglong", opc.parsekey(), iarg));
118                         }
119                         break;
120                 }
121                 switch (opcLen) {
122                     case 1:
123                         return;
124                     case 2:
125                         out.writeByte(iarg);
126                         return;
127                     case 3:
128                         out.writeShort(iarg);
129                         return;
130                     case 4: // opc_multianewarray only
131                         out.writeShort(iarg);
132                         iarg = ((Argument) arg2).arg;
133                         out.writeByte(iarg);
134                         return;
135                     case 5:
136                         out.writeInt(iarg);
137                         return;
138                     default:
139                         throw new Parser.CompilerError(
140                                 env.errorStr("comperr.instr.opclen", opc.parsekey()));
141                 }
142             }
143             case WIDE:
144                 out.writeByte(Opcode.opc_wide.value());
145                 out.writeByte(opc.value() & 0xFF);
146                 out.writeShort(arg.arg);
147                 if (opc == Opcode.opc_iinc_w) {
148                     out.writeShort(((Argument) arg2).arg);
149                 }
150                 return;
151             case PRIVELEGED:
152             case NONPRIVELEGED:
153                 out.writeByte(opc.value() >> 8);
154                 out.writeByte(opc.value() & 0xFF);
155                 return;
156             default:
157                 throw new Parser.CompilerError(
158                         env.errorStr("comperr.instr.opclen", opc.parsekey()));
159         } // end writeSpecCode
160 
161     }
162 } // end Instr
163