001 package AST; 002 003 import java.util.HashSet; 004 import java.io.File; 005 import java.util.*; 006 import beaver.*; 007 import java.util.ArrayList; 008 import java.util.zip.*; 009 import java.io.*; 010 import java.io.FileNotFoundException; 011 import java.util.Collection; 012 /** 013 * @ast class 014 * 015 */ 016 public class CodeGeneration extends java.lang.Object { 017 018 private ByteArray bytes = new ByteArray(); 019 020 021 private ConstantPool constantPool; 022 023 024 025 public void clearCodeGeneration() { 026 bytes = null; 027 constantPool = null; 028 variableScopeLabelAddress = null; 029 variableScopeLabelUses = null; 030 localVariableTable = null; 031 lineNumberTable = null; 032 exceptions = null; 033 address = null; 034 uses = null; 035 } 036 037 038 039 private boolean wideGoto = false; 040 041 042 043 private boolean numberFormatError = false; 044 045 046 public boolean numberFormatError() { return numberFormatError; } 047 048 049 050 public CodeGeneration(ConstantPool constantPool) { 051 this.constantPool = constantPool; 052 } 053 054 055 056 public CodeGeneration(ConstantPool constantPool, boolean wideGoto) { 057 this.constantPool = constantPool; 058 this.wideGoto = wideGoto; 059 } 060 061 062 063 public ConstantPool constantPool() { 064 return constantPool; 065 } 066 067 068 069 private int variableScopeLabel = 1; 070 071 072 public int variableScopeLabel() { 073 return variableScopeLabel++; 074 } 075 076 077 public void addVariableScopeLabel(int label) { 078 Integer label_object = new Integer(label); 079 variableScopeLabelAddress.put(label_object, new Integer(pos())); 080 // Update all reference to this label 081 if(variableScopeLabelUses.containsKey(label_object)) { 082 ArrayList array = (ArrayList)variableScopeLabelUses.get(label_object); 083 for(Iterator iter = array.iterator(); iter.hasNext(); ) { 084 LocalVariableEntry e = (LocalVariableEntry)iter.next(); 085 e.length = pos() - e.start_pc; 086 } 087 } 088 } 089 090 091 private HashMap variableScopeLabelAddress = new HashMap(); 092 093 094 private HashMap variableScopeLabelUses = new HashMap(); 095 096 097 098 class LocalVariableEntry { 099 int start_pc; 100 int length; 101 int name_index; 102 int descriptor_index; 103 int index; 104 } 105 106 107 public Collection localVariableTable = new ArrayList(); 108 109 110 public void addLocalVariableEntryAtCurrentPC(String name, String typeDescriptor, int localNum, int variableScopeEndLabel) { 111 LocalVariableEntry e = new LocalVariableEntry(); 112 e.start_pc = pos(); 113 e.length = 0; 114 e.name_index = constantPool().addUtf8(name); 115 e.descriptor_index = constantPool().addUtf8(typeDescriptor); 116 e.index = localNum; 117 localVariableTable.add(e); 118 Integer label_object = new Integer(variableScopeEndLabel); 119 if(!variableScopeLabelUses.containsKey(label_object)) 120 variableScopeLabelUses.put(label_object, new ArrayList()); 121 Collection c = (Collection)variableScopeLabelUses.get(label_object); 122 c.add(e); 123 } 124 125 126 127 // at each variable declaration and parameter declaration 128 // inh int VariableDeclaration.variableScopeEndLabel(CodeGeneration gen); 129 // addLocalVariableEntryAtCurrentPC(this, variableScopeEndLabel()); 130 // syn lazy int Block.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel(); 131 // Block.createBCode() { ... gen.addLabel(variableScopeLabel()); 132 133 class LineNumberEntry { 134 int start_pc; 135 int line_number; 136 } 137 138 139 public Collection lineNumberTable = new ArrayList(); 140 141 142 public void addLineNumberEntryAtCurrentPC(ASTNode node) { 143 LineNumberEntry e = new LineNumberEntry(); 144 e.start_pc = pos(); 145 e.line_number = node.sourceLineNumber(); 146 if(e.line_number != -1 && e.line_number != 65535) 147 lineNumberTable.add(e); 148 } 149 150 151 152 public Collection exceptions = new ArrayList(); 153 154 155 public void addException(int start_pc, int end_pc, int handler_pc, int catch_type) { 156 ExceptionEntry e = new ExceptionEntry(); 157 e.start_pc = start_pc; 158 e.end_pc = end_pc; 159 e.handler_pc = handler_pc; 160 e.catch_type = catch_type; 161 if(e.start_pc != e.end_pc) 162 exceptions.add(e); 163 } 164 165 166 class ExceptionEntry { 167 int start_pc; 168 int end_pc; 169 int handler_pc; 170 int catch_type; 171 } 172 173 174 public void createExceptionTable(TryStmt tryStmt) { 175 for(int i = 0; i < tryStmt.getNumCatchClause(); i++) { 176 tryStmt.getCatchClause(i).exceptionTableEntries(this, tryStmt); 177 } 178 if(tryStmt.hasFinally()) { 179 addException( 180 addressOf(tryStmt.label_begin()), 181 addressOf(tryStmt.label_finally()), 182 addressOf(tryStmt.label_exception_handler()), 183 0 184 ); 185 } 186 } 187 188 189 public void createExceptionTable(SynchronizedStmt stmt) { 190 addException( 191 addressOf(stmt.label_begin()), 192 addressOf(stmt.label_finally()), 193 addressOf(stmt.label_exception_handler()), 194 0 195 ); 196 } 197 198 199 200 public int maxLocals() { 201 return maxLocals+1; 202 } 203 204 205 int maxLocals = 0; 206 207 208 209 /* 210 public int label() { 211 return labelCounter++; 212 } 213 private static int labelCounter = 1; 214 */ 215 private HashMap address = new HashMap(); 216 217 218 private HashMap uses = new HashMap(); 219 220 221 public void addLabel(int label) { 222 Integer label_object = new Integer(label); 223 /* 224 if(pos() - 3 == bytes.lastGotoPos() && bytes.get(pos() - 3) == Bytecode.GOTO) { 225 if(uses.containsKey(label_object)) { 226 ArrayList array = (ArrayList)uses.get(label_object); 227 for(int i = 0; i < array.size(); i++) { 228 int p = ((Integer)array.get(i)).intValue(); 229 if(pos() - 3 == p) { 230 //System.out.println("Found direct branch"); 231 array.remove(i); 232 i--; 233 } 234 } 235 bytes.setPos(pos() - 3); 236 } 237 } 238 */ 239 address.put(label_object, new Integer(pos())); 240 // Update all reference to this label 241 if(uses.containsKey(label_object)) { 242 ArrayList array = (ArrayList)uses.get(label_object); 243 for(int i = 0; i < array.size(); i++) { 244 int p = ((Integer)array.get(i)).intValue(); 245 if(bytes.get(p) == Bytecode.GOTO_W) 246 setAddress32(p + 1, pos() - p); 247 else 248 setAddress(p + 1, pos() - p); 249 } 250 } 251 } 252 253 254 public int addressOf(int label) { 255 Integer label_object = new Integer(label); 256 if(!address.containsKey(label_object)) 257 throw new Error("Can not compute address of unplaced label"); 258 return ((Integer)address.get(label_object)).intValue(); 259 } 260 261 262 private int jump(int label) { 263 Integer label_object = new Integer(label); 264 if(!uses.containsKey(label_object)) 265 uses.put(label_object, new ArrayList()); 266 ArrayList a = (ArrayList)uses.get(label_object); 267 a.add(new Integer(pos())); // position of the 16-bits reference 268 Integer val = (Integer)address.get(label_object); 269 if(val != null) 270 return val.intValue() - pos(); 271 return 0; // a position of 0 means not calculated yet 272 } 273 274 275 private void setAddress(int position, int address) { 276 if(address > Short.MAX_VALUE || address < Short.MIN_VALUE) 277 numberFormatError = true; 278 bytes.set(position + 0, (byte)((address&0xff00)>>8)); 279 bytes.set(position + 1, (byte)(address&0xff)); 280 } 281 282 283 private void setAddress32(int position, int address) { 284 bytes.set(position + 0, (byte)(address >> 24 & 0xff)); 285 bytes.set(position + 1, (byte)(address >> 16 & 0xff)); 286 bytes.set(position + 2, (byte)(address >> 8 & 0xff)); 287 bytes.set(position + 3, (byte)(address & 0xff)); 288 } 289 290 291 292 293 public void emitStoreReference(int pos) { 294 maxLocals = Math.max(maxLocals, pos+1); 295 if(pos == 0) emit(Bytecode.ASTORE_0); 296 else if(pos == 1) emit(Bytecode.ASTORE_1); 297 else if(pos == 2) emit(Bytecode.ASTORE_2); 298 else if(pos == 3) emit(Bytecode.ASTORE_3); 299 else if(pos < 256) emit(Bytecode.ASTORE).add(pos); 300 else emit(Bytecode.WIDE).emit(Bytecode.ASTORE).add2(pos); 301 } 302 303 304 public void emitLoadReference(int pos) { 305 maxLocals = Math.max(maxLocals, pos+1); 306 if(pos == 0) emit(Bytecode.ALOAD_0); 307 else if(pos == 1) emit(Bytecode.ALOAD_1); 308 else if(pos == 2) emit(Bytecode.ALOAD_2); 309 else if(pos == 3) emit(Bytecode.ALOAD_3); 310 else if(pos < 256) emit(Bytecode.ALOAD).add(pos); 311 else emit(Bytecode.WIDE).emit(Bytecode.ALOAD).add2(pos); 312 } 313 314 315 316 public void emitReturn() { 317 bytes.emit(Bytecode.RETURN); 318 } 319 320 321 322 public void emitThrow() { 323 bytes.emit(Bytecode.ATHROW); 324 } 325 326 327 328 public void emitInstanceof(TypeDecl type) { 329 int p = constantPool().addClass(type.isArrayDecl() ? type.typeDescriptor() : type.constantPoolName()); 330 bytes.emit(Bytecode.INSTANCEOF).add2(p); 331 } 332 333 334 public void emitCheckCast(TypeDecl type) { 335 int p = constantPool().addClass(type.isArrayDecl() ? type.typeDescriptor() : type.constantPoolName()); 336 bytes.emit(Bytecode.CHECKCAST).add2(p); 337 } 338 339 340 341 public void emitDup() { 342 bytes.emit(Bytecode.DUP); 343 } 344 345 346 public void emitDup2() { 347 bytes.emit(Bytecode.DUP2); 348 } 349 350 351 352 public void emitPop() { 353 bytes.emit(Bytecode.POP); 354 } 355 356 357 358 public void emitSwap() { 359 bytes.emit(Bytecode.SWAP); 360 } 361 362 363 364 public void emitBranchNonNull(int label) { 365 int p = jump(label); 366 bytes.emit(Bytecode.IFNONNULL).add2(p); 367 } 368 369 370 371 public void emitGoto(int label) { 372 int p = jump(label); 373 if(wideGoto) 374 bytes.emitGoto(Bytecode.GOTO_W).add4(p); 375 else { 376 if(p > Short.MAX_VALUE || p < Short.MIN_VALUE) 377 numberFormatError = true; 378 bytes.emitGoto(Bytecode.GOTO).add2(p); 379 } 380 } 381 382 383 384 public void emitJsr(int label) { 385 int p = jump(label); 386 bytes.emit(Bytecode.JSR).add2(p); 387 } 388 389 390 391 public void emitCompare(byte bytecode, int label) { 392 int p = jump(label); 393 bytes.emit(bytecode).add2(p); 394 } 395 396 397 398 public String toString() { 399 return bytes.toString(); 400 } 401 402 403 public int size() {return bytes.size();} 404 405 406 public int pos() {return bytes.pos();} 407 408 409 public byte[] toArray() {return bytes.toArray();} 410 411 412 CodeGeneration add(int i) { return add((byte)i); } 413 414 415 CodeGeneration add(byte b) { bytes.add(b); return this; } 416 417 418 CodeGeneration add2(int index) { 419 bytes.add2(index); 420 return this; 421 } 422 423 424 CodeGeneration add4(int index) { 425 bytes.add4(index); 426 return this; 427 } 428 429 430 CodeGeneration emit(byte b) { 431 bytes.emit(b); 432 return this; 433 } 434 435 436 CodeGeneration emit(byte b, int stackChange) { 437 bytes.emit(b, stackChange); 438 return this; 439 } 440 441 442 public int maxStackDepth() { 443 return bytes.maxStackDepth(); 444 } 445 446 447 public int stackDepth() { 448 return bytes.stackDepth(); 449 } 450 451 452 public void changeStackDepth(int i) { 453 bytes.changeStackDepth(i); 454 } 455 456 457 }