00001 package de.fub.bytecode.generic;
00002
00003 import java.io.*;
00004 import de.fub.bytecode.util.ByteSequence;
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
00016 protected int index;
00017 protected InstructionHandle target;
00018 protected int position;
00019
00020
00021
00022
00023
00024 BranchInstruction() {}
00025
00026
00027
00028
00029 protected BranchInstruction(short tag, InstructionHandle target) {
00030 super(tag, (short)3);
00031 setTarget(target);
00032 }
00033
00034
00035
00036 public boolean containsTarget(InstructionHandle ih) {
00037 return (target == ih);
00038 }
00039
00040
00041
00042 void dispose() {
00043 setTarget(null);
00044 index=-1;
00045 position=-1;
00046 }
00047
00048
00049
00050
00051 public void dump(DataOutputStream out) throws IOException {
00052 out.writeByte(tag);
00053
00054 index = getTargetOffset();
00055
00056 if(Math.abs(index) >= 32767)
00057 throw new ClassGenException("Branch target offset too large for short");
00058
00059 out.writeShort(index);
00060 }
00061
00062
00063
00064 public final int getIndex() { return index; }
00065
00066
00067
00068 public InstructionHandle getTarget() { return target; }
00069
00070
00071
00072 protected int getTargetOffset() { return getTargetOffset(target); }
00073
00074
00075
00076
00077 protected int getTargetOffset(InstructionHandle target) {
00078 if(target == null)
00079 throw new ClassGenException("Target of " + super.toString(true) +
00080 " is invalid null handle");
00081
00082 int t = target.getPosition();
00083
00084 if(t < 0)
00085 throw new ClassGenException("Invalid branch target position offset for " +
00086 super.toString(true) + ":" + t + ":" + target);
00087
00088 return t - position;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
00099 {
00100 length = 3;
00101 index = bytes.readShort();
00102 }
00103
00104
00105
00106 static final void notifyTarget(InstructionHandle old_ih, InstructionHandle new_ih,
00107 InstructionTargeter t) {
00108 if(old_ih != null)
00109 old_ih.removeTargeter(t);
00110 if(new_ih != null)
00111 new_ih.addTargeter(t);
00112 }
00113
00114
00115
00116
00117 public void setTarget(InstructionHandle target) {
00118 notifyTarget(this.target, target, this);
00119 this.target = target;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 public String toString(boolean verbose) {
00133 String s = super.toString(verbose);
00134 String t = "null";
00135
00136 if(verbose) {
00137 if(target != null) {
00138 if(target.getInstruction() == this)
00139 t = "<points to itself>";
00140 else if(target.getInstruction() == null)
00141 t = "<null instruction!!!?>";
00142 else
00143 t = target.getInstruction().toString(verbose);
00144 }
00145 } else {
00146 if(target != null) {
00147 index = getTargetOffset();
00148 t = "" + (index + position);
00149 }
00150 }
00151
00152 return s + " -> " + t;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 protected int updatePosition(int offset, int max_offset) {
00165 position += offset;
00166 return 0;
00167 }
00168
00169
00170
00171
00172 public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
00173 if(target == old_ih)
00174 setTarget(new_ih);
00175 else
00176 throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
00177 }
00178 }