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