initial implementation
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / codegen / Label.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.codegen;
12
13 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
14 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
15
16 /**
17  * This type is a port of smalltalks JavaLabel
18  */
19 public class Label {
20 //      public CodeStream codeStream;
21         final static int POS_NOT_SET = -1;
22         public int position = POS_NOT_SET; // position=POS_NOT_SET Then it's pos is not set.
23         public int[] forwardReferences = new int[10]; // Add an overflow check here.
24         public int forwardReferenceCount = 0;
25         private boolean isWide = false;
26 public Label() {
27 }
28 /**
29  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
30  */
31 //public Label(CodeStream codeStream) {
32 //      this.codeStream = codeStream;
33 //}
34 /**
35  * Add a forward refrence for the array.
36  */
37 void addForwardReference(int iPos) {
38         int length;
39         if (forwardReferenceCount >= (length = forwardReferences.length))
40                 System.arraycopy(forwardReferences, 0, (forwardReferences = new int[2*length]), 0, length);
41         forwardReferences[forwardReferenceCount++] = iPos;
42 }
43 /**
44  * Add a forward refrence for the array.
45  */
46 public void appendForwardReferencesFrom(Label otherLabel) {
47         int otherCount = otherLabel.forwardReferenceCount;
48         if (otherCount == 0) return;
49         int length = forwardReferences.length;
50         int neededSpace = otherCount + forwardReferenceCount;
51         if (neededSpace >= length){
52                 System.arraycopy(forwardReferences, 0, (forwardReferences = new int[neededSpace]), 0, forwardReferenceCount);
53         }
54         // append other forward references at the end, so they will get updated as well
55         System.arraycopy(otherLabel.forwardReferences, 0, forwardReferences, forwardReferenceCount, otherCount);
56         forwardReferenceCount = neededSpace;
57 }
58 /*
59 * Put down  a refernece to the array at the location in the codestream.
60 */
61 //void branch() {
62 //      if (position == POS_NOT_SET) {
63 //              addForwardReference(codeStream.position);
64 //              // Leave two bytes free to generate the jump afterwards
65 //              codeStream.position += 2;
66 //              codeStream.classFileOffset += 2;
67 //      } else {
68 //              /*
69 //               * Position is set. Write it if it is not a wide branch.
70 //               */
71 //              int offset = position - codeStream.position + 1;
72 //              if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
73 //                      throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
74 //              }
75 //              codeStream.writeSignedShort((short) offset);
76 //      }
77 //}
78 /*
79 * No support for wide branches yet
80 */
81 //void branchWide() {
82 //      if (position == POS_NOT_SET) {
83 //              addForwardReference(codeStream.position);
84 //              // Leave 4 bytes free to generate the jump offset afterwards
85 //              isWide = true;
86 //              codeStream.position += 4;
87 //              codeStream.classFileOffset += 4;
88 //      } else { //Position is set. Write it!
89 //              codeStream.writeSignedWord(position - codeStream.position + 1);
90 //      }
91 //}
92 /**
93  * @return boolean
94  */
95 public boolean hasForwardReferences() {
96         return forwardReferenceCount != 0;
97 }
98 /*
99  * Some placed labels might be branching to a goto bytecode which we can optimize better.
100  */
101 //public void inlineForwardReferencesFromLabelsTargeting(int gotoLocation) {
102 ///*
103 // Code required to optimized unreachable gotos.
104 //      public boolean isBranchTarget(int location) {
105 //              Label[] labels = codeStream.labels;
106 //              for (int i = codeStream.countLabels - 1; i >= 0; i--){
107 //                      Label label = labels[i];
108 //                      if ((label.position == location) && label.isStandardLabel()){
109 //                              return true;
110 //                      }
111 //              }
112 //              return false;
113 //      }
114 // */
115 //      
116 //      Label[] labels = codeStream.labels;
117 //      for (int i = codeStream.countLabels - 1; i >= 0; i--){
118 //              Label label = labels[i];
119 //              if ((label.position == gotoLocation) && label.isStandardLabel()){
120 //                      this.appendForwardReferencesFrom(label);
121 //                      /*
122 //                       Code required to optimized unreachable gotos.
123 //                              label.position = POS_NOT_SET;
124 //                      */
125 //              } else {
126 //                      break; // same target labels should be contiguous
127 //              }
128 //      }
129 //}
130 public boolean isStandardLabel(){
131         return true;
132 }
133 /*
134 * Place the label. If we have forward references resolve them.
135 */
136 //public void place() { // Currently lacking wide support.
137 //      if (position == POS_NOT_SET) {
138 //              position = codeStream.position;
139 //              codeStream.addLabel(this);
140 //              int oldPosition = position;
141 //              boolean optimizedBranch = false;
142 //              // TURNED OFF since fail on 1F4IRD9
143 //              if (forwardReferenceCount != 0) {
144 //                      if (optimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == CodeStream.OPC_goto)) {
145 //                              codeStream.position = (position -= 3);
146 //                              codeStream.classFileOffset -= 3;
147 //                              forwardReferenceCount--;
148 //                              // also update the PCs in the related debug attributes
149 //                              /** OLD CODE
150 //                                      int index = codeStream.pcToSourceMapSize - 1;
151 //                                              while ((index >= 0) && (codeStream.pcToSourceMap[index][1] == oldPosition)) {
152 //                                                      codeStream.pcToSourceMap[index--][1] = position;
153 //                                              }
154 //                              */
155 //                              // Beginning of new code
156 //                              int index = codeStream.pcToSourceMapSize - 2;
157 //                              if (codeStream.lastEntryPC == oldPosition) {
158 //                                      codeStream.lastEntryPC = position;
159 //                              }
160 //                              if ((index >= 0) && (codeStream.pcToSourceMap[index] == position)) {
161 //                                      codeStream.pcToSourceMapSize-=2;
162 //                              }
163 //                              // end of new code
164 //                              if (codeStream.generateLocalVariableTableAttributes) {
165 //                                      LocalVariableBinding locals[] = codeStream.locals;
166 //                                      for (int i = 0, max = locals.length; i < max; i++) {
167 //                                              LocalVariableBinding local = locals[i];
168 //                                              if ((local != null) && (local.initializationCount > 0)) {
169 //                                                      if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == oldPosition) {
170 //                                                              // we want to prevent interval of size 0 to have a negative size.
171 //                                                              // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable attribute
172 //                                                              local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = position;
173 //                                                      }
174 //                                                      if (local.initializationPCs[(local.initializationCount - 1) << 1] == oldPosition) {
175 //                                                              local.initializationPCs[(local.initializationCount - 1) << 1] = position;
176 //                                                      }
177 //                                              }
178 //                                      }
179 //                              }
180 //                      }
181 //              }
182 //              for (int i = 0; i < forwardReferenceCount; i++) {
183 //                      int offset = position - forwardReferences[i] + 1;
184 //                      if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
185 //                              throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
186 //                      }
187 //                      if (this.codeStream.wideMode) {
188 //                              if (this.isWide) {
189 //                                      codeStream.writeSignedWord(forwardReferences[i], offset);
190 //                              } else {
191 //                                      codeStream.writeSignedShort(forwardReferences[i], (short) offset);
192 //                              }
193 //                      } else {
194 //                              codeStream.writeSignedShort(forwardReferences[i], (short) offset);
195 //                      }
196 //              }
197 //              // For all labels placed at that position we check if we need to rewrite the jump
198 //              // offset. It is the case each time a label had a forward reference to the current position.
199 //              // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
200 //              if (optimizedBranch) {
201 //                      for (int i = 0; i < codeStream.countLabels; i++) {
202 //                              Label label = codeStream.labels[i];
203 //                              if (oldPosition == label.position) {
204 //                                      label.position = position;
205 //                                      if (label instanceof CaseLabel) {
206 //                                              int offset = position - ((CaseLabel) label).instructionPosition;
207 //                                              for (int j = 0; j < label.forwardReferenceCount; j++) {
208 //                                                      int forwardPosition = label.forwardReferences[j];
209 //                                                      codeStream.writeSignedWord(forwardPosition, offset);
210 //                                              }
211 //                                      } else {
212 //                                              for (int j = 0; j < label.forwardReferenceCount; j++) {
213 //                                                      int forwardPosition = label.forwardReferences[j];
214 //                                                      int offset = position - forwardPosition + 1;
215 //                                                      if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
216 //                                                              throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
217 //                                                      }
218 //                                                      if (this.codeStream.wideMode) {
219 //                                                              if (this.isWide) {
220 //                                                                      codeStream.writeSignedWord(forwardPosition, offset);
221 //                                                              } else {
222 //                                                                      codeStream.writeSignedShort(forwardPosition, (short) offset);
223 //                                                              }
224 //                                                      } else {
225 //                                                              codeStream.writeSignedShort(forwardPosition, (short) offset);
226 //                                                      }
227 //                                              }
228 //                                      }
229 //                              }
230 //                      }
231 //              }
232 //      }
233 //}
234 /**
235  * Print out the receiver
236  */
237 public String toString() {
238         StringBuffer buffer = new StringBuffer("(position="); //$NON-NLS-1$
239         buffer.append(position);
240         buffer.append(", forwards = ["); //$NON-NLS-1$
241         for (int i = 0; i < forwardReferenceCount - 1; i++)
242                 buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
243         if (forwardReferenceCount >= 1)
244                 buffer.append(forwardReferences[forwardReferenceCount-1]);
245         buffer.append("] )"); //$NON-NLS-1$
246         return buffer.toString();
247 }
248
249 public void resetStateForCodeGeneration() {
250         this.position = POS_NOT_SET;
251         this.forwardReferenceCount = 0;
252 }
253 }