001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * 2013, Jesper Öqvist <jesper.oqvist@cs.lth.se> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are met: 007 * 008 * 1. Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * 3. Neither the name of the copyright holder nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 029 * POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 import java.util.*; 033 import java.io.*; 034 035 aspect CreateBCode { 036 037 inh TypeDecl CatchClause.hostType(); 038 039 public abstract void CatchClause.exceptionTableEntries(CodeGeneration gen, int begin_lbl, int end_lbl); 040 041 public void BasicCatch.exceptionTableEntries(CodeGeneration gen, int begin_lbl, int end_lbl) { 042 gen.addException( 043 begin_lbl, 044 end_lbl, 045 label(), 046 gen.constantPool().addClass(getParameter().type().constantPoolName()) 047 ); 048 } 049 050 syn lazy boolean TypeDecl.hasClinit() { 051 for (int i = 0; i < getNumBodyDecl(); i++) { 052 BodyDecl b = getBodyDecl(i); 053 if (b instanceof FieldDeclaration) { 054 FieldDeclaration f = (FieldDeclaration) b; 055 if (f.isStatic() && f.hasInit()) { 056 return true; 057 } 058 } else if (b instanceof StaticInitializer) { 059 return true; 060 } 061 } 062 return false; 063 } 064 065 syn lazy CodeGeneration TypeDecl.bytecodes(ConstantPool constantPool) { 066 CodeGeneration gen = new CodeGeneration(constantPool); 067 generateBytecodes(gen); 068 if (!gen.numberFormatError()) { 069 return gen; 070 } 071 gen = new CodeGeneration(constantPool, true); 072 generateBytecodes(gen); 073 if (!gen.numberFormatError()) { 074 return gen; 075 } 076 throw new Error("Could not generate code for initializers in " + hostType().typeName()); 077 } 078 079 private void TypeDecl.generateBytecodes(CodeGeneration gen) { 080 for (int i = 0; i < getNumBodyDecl(); i++) { 081 BodyDecl b = getBodyDecl(i); 082 if (b instanceof FieldDeclaration && b.isBytecodeField()) { 083 FieldDeclaration f = (FieldDeclaration) b; 084 f.emitStaticInitializer(gen, this); 085 } else if (b instanceof StaticInitializer) { 086 b.createBCode(gen); 087 } 088 } 089 gen.emitReturn(); 090 } 091 092 syn lazy CodeGeneration MethodDecl.bytecodes(ConstantPool constantPool) { 093 CodeGeneration gen = new CodeGeneration(constantPool); 094 generateBytecodes(gen); 095 if (!gen.numberFormatError()) { 096 return gen; 097 } 098 gen = new CodeGeneration(constantPool, true); 099 generateBytecodes(gen); 100 if (!gen.numberFormatError()) { 101 return gen; 102 } 103 throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName()); 104 } 105 106 private void MethodDecl.generateBytecodes(CodeGeneration gen) { 107 int label = gen.variableScopeLabel(); 108 int paramLength = 0; 109 if (!isStatic()) { 110 paramLength += 1; 111 gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); 112 } 113 for (ParameterDeclaration p: getParameterList()) { 114 paramLength += p.type().variableSize(); 115 if (paramLength > 255) { 116 throw new Error("parameter list too large"); 117 } 118 gen.addLocalVariableEntryAtCurrentPC( 119 p.name(), p.type().typeDescriptor(), p.localNum(), label 120 ); 121 } 122 createBCode(gen); 123 if (type() instanceof VoidType) // TODO: canCompleteNormally check as well 124 gen.emitReturn(); 125 gen.addVariableScopeLabel(label); 126 } 127 128 syn lazy CodeGeneration ConstructorDecl.bytecodes(ConstantPool constantPool) { 129 CodeGeneration gen = new CodeGeneration(constantPool); 130 generateBytecodes(gen); 131 if (!gen.numberFormatError()) { 132 return gen; 133 } 134 gen = new CodeGeneration(constantPool, true); 135 generateBytecodes(gen); 136 if (!gen.numberFormatError()) { 137 return gen; 138 } 139 throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName()); 140 } 141 142 private void ConstructorDecl.generateBytecodes(CodeGeneration gen) { 143 int label = gen.variableScopeLabel(); 144 int paramLength = 1; 145 gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); 146 for (ParameterDeclaration p: getParameterList()) { 147 paramLength += p.type().variableSize(); 148 if (paramLength > 255) { 149 throw new Error("parameter list too large"); 150 } 151 gen.addLocalVariableEntryAtCurrentPC( 152 p.name(), p.type().typeDescriptor(), p.localNum(), label 153 ); 154 } 155 createBCode(gen); 156 gen.emitReturn(); 157 gen.addVariableScopeLabel(label); 158 } 159 160 public void MethodDecl.createBCode(CodeGeneration gen) { 161 try { 162 if (hasBlock()) { 163 gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); 164 getBlock().createBCode(gen); 165 } 166 } catch (Error e) { 167 System.err.println(hostType().typeName() + ": " + this); 168 throw e; 169 } 170 } 171 172 public void ConstructorDecl.createBCode(CodeGeneration gen) { 173 try { 174 boolean needsInit = true; 175 176 if (hasConstructorInvocation()) { 177 getConstructorInvocation().createBCode(gen); 178 Stmt stmt = getConstructorInvocation(); 179 if (stmt instanceof ExprStmt) { 180 ExprStmt exprStmt = (ExprStmt) stmt; 181 Expr expr = exprStmt.getExpr(); 182 if (!expr.isSuperConstructorAccess()) { 183 needsInit = false; 184 } 185 186 } 187 } 188 189 if (needsEnclosing()) { 190 gen.emitLoadReference(0); 191 gen.emitLoadReference(1); 192 String classname = hostType().constantPoolName(); 193 String desc = enclosing().typeDescriptor(); 194 String name = "this$0"; 195 int index = gen.constantPool().addFieldref(classname, name, desc); 196 gen.emit(Bytecode.PUTFIELD, -2).add2(index); 197 } 198 199 int localIndex = offsetFirstEnclosingVariable(); 200 for (Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) { 201 Variable v = (Variable) iter.next(); 202 gen.emitLoadReference(0); 203 v.type().emitLoadLocal(gen, localIndex); 204 String classname = hostType().constantPoolName(); 205 String desc = v.type().typeDescriptor(); 206 String name = "val$" + v.name(); 207 int index = gen.constantPool().addFieldref(classname, name, desc); 208 gen.emit(Bytecode.PUTFIELD, -1 - v.type().variableSize()).add2(index); 209 localIndex += v.type().variableSize(); 210 } 211 212 if (needsInit) { 213 TypeDecl typeDecl = hostType(); 214 for (int i = 0; i < typeDecl.getNumBodyDecl(); i++) { 215 BodyDecl b = typeDecl.getBodyDecl(i); 216 if (b instanceof FieldDeclaration && b.isBytecodeField()) { 217 FieldDeclaration f = (FieldDeclaration) b; 218 f.emitInstanceInitializer(gen, hostType()); 219 } else if (b instanceof InstanceInitializer) { 220 b.createBCode(gen); 221 } 222 } 223 } 224 gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); 225 getBlock().createBCode(gen); 226 } catch (Error e) { 227 System.err.println(hostType().typeName() + ": " + this); 228 throw e; 229 } 230 } 231 232 public void ASTNode.createBCode(CodeGeneration gen) { 233 for (int i=0; i<getNumChild(); i++) { 234 getChild(i).createBCode(gen); 235 } 236 } 237 238 public void Literal.createBCode(CodeGeneration gen) { 239 emitPushConstant(gen); 240 } 241 242 protected boolean Expr.needsPush() { 243 ASTNode n = getParent(); 244 while (n instanceof ParExpr) { 245 n = n.getParent(); 246 } 247 return !(n instanceof ExprStmt); 248 } 249 250 syn boolean ExprStmt.needsPop() = getExpr().needsPop(); 251 syn boolean Expr.needsPop() = true; 252 eq AbstractDot.needsPop() = lastAccess().needsPop(); 253 eq ConstructorAccess.needsPop() = false; 254 255 eq ParExpr.needsPop() = getExpr().needsPop(); 256 //eq AssignExpr.needsPop() = false; // if dest is instance variable that needs accessor 257 eq AssignExpr.needsPop() = getDest().isVarAccessWithAccessor(); 258 eq PreIncExpr.needsPop() = false; 259 eq PostIncExpr.needsPop() = getOperand().isVarAccessWithAccessor(); 260 eq PreDecExpr.needsPop() = false; 261 eq PostDecExpr.needsPop() = getOperand().isVarAccessWithAccessor(); 262 263 syn boolean Expr.isVarAccessWithAccessor() = false; 264 eq ParExpr.isVarAccessWithAccessor() = getExpr().isVarAccessWithAccessor(); 265 eq AbstractDot.isVarAccessWithAccessor() = lastAccess().isVarAccessWithAccessor(); 266 eq VarAccess.isVarAccessWithAccessor() = decl() instanceof FieldDeclaration && 267 decl().isInstanceVariable() && requiresAccessor(); 268 269 public void VarDeclStmt.createBCode(CodeGeneration gen) { 270 gen.addLineNumberEntryAtCurrentPC(this);// generate line number entry 271 for (VariableDeclaration decl: getSingleDeclList()) { 272 decl.createBCode(gen); 273 } 274 } 275 276 public void VariableDeclaration.createBCode(CodeGeneration gen) { 277 if (hasInit()) { 278 gen.addLocalVariableEntryAtCurrentPC(name(), type().typeDescriptor(), localNum(), variableScopeEndLabel(gen)); 279 emitInitializerBCode(gen); 280 type().emitStoreLocal(gen, localNum()); 281 } 282 } 283 284 /** 285 * Generate variable initialization bytecode. 286 */ 287 protected void VariableDeclaration.emitInitializerBCode(CodeGeneration gen) { 288 getInit().createBCode(gen); 289 getInit().type().emitAssignConvTo(gen, type()); 290 } 291 292 /** 293 * Generate static initialization code for the field. 294 */ 295 public void FieldDeclaration.emitStaticInitializer(CodeGeneration gen, TypeDecl hostType) { 296 if (isStatic() && hasInit()) { 297 emitInitializerBCode(gen); 298 emitStoreField(gen, hostType); 299 } 300 } 301 302 /** 303 * Generate instance initialization code for the field. 304 */ 305 public void FieldDeclaration.emitInstanceInitializer(CodeGeneration gen, TypeDecl hostType) { 306 if (!isStatic() && hasInit()) { 307 gen.emit(Bytecode.ALOAD_0); 308 emitInitializerBCode(gen); 309 emitStoreField(gen, hostType); 310 } 311 } 312 313 /** 314 * Generate field initialization bytecode. 315 */ 316 protected void FieldDeclaration.emitInitializerBCode(CodeGeneration gen) { 317 getInit().createBCode(gen); 318 getInit().type().emitAssignConvTo(gen, type()); 319 } 320 321 /** 322 * Create bytecode for a simple assign expression. 323 */ 324 public void AssignSimpleExpr.createBCode(CodeGeneration gen) { 325 getDest().createAssignSimpleLoadDest(gen); 326 getSource().createBCode(gen); 327 getSource().type().emitAssignConvTo(gen, getDest().type()); // AssignConversion 328 if (needsPush()) { 329 getDest().createPushAssignmentResult(gen); 330 } 331 getDest().emitStore(gen); 332 } 333 334 /** 335 * Create bytecode for a compund assign expression. 336 */ 337 public void AssignExpr.createBCode(CodeGeneration gen) { 338 TypeDecl dest = getDest().type(); 339 TypeDecl source = getSource().type(); 340 TypeDecl type; 341 if (dest.isNumericType() && source.isNumericType()) { 342 type = dest.binaryNumericPromotion(source); 343 } else { 344 type = dest; 345 } 346 getDest().createAssignLoadDest(gen); 347 dest.emitCastTo(gen, type); 348 getSource().createBCode(gen); 349 source.emitCastTo(gen, type); 350 createAssignOp(gen, type); 351 type.emitCastTo(gen, dest); 352 if (needsPush()) { 353 getDest().createPushAssignmentResult(gen); 354 } 355 getDest().emitStore(gen); 356 } 357 358 // string addition assign expression 359 public void AssignPlusExpr.createBCode(CodeGeneration gen) { 360 TypeDecl dest = getDest().type(); 361 TypeDecl source = getSource().type(); 362 if (dest.isString()) { 363 getDest().createAssignLoadDest(gen); 364 365 // new StringBuffer() 366 TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer"); 367 String classname = stringBuffer.constantPoolName(); 368 String desc; 369 int index; 370 TypeDecl argumentType; 371 stringBuffer.emitNew(gen); // new StringBuffer 372 gen.emitDup(); // dup 373 desc = "()V"; 374 index = gen.constantPool().addMethodref(classname, "<init>", desc); 375 gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer() 376 377 gen.emitSwap(); 378 379 // append 380 argumentType = dest.stringPromotion(); 381 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 382 index = gen.constantPool().addMethodref(classname, "append", desc); 383 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 384 385 getSource().createBCode(gen); 386 387 // typed append 388 argumentType = source.stringPromotion(); 389 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 390 index = gen.constantPool().addMethodref(classname, "append", desc); 391 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 392 393 // toString 394 desc = "()" + type().typeDescriptor(); 395 index = gen.constantPool().addMethodref(classname, "toString", desc); 396 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString 397 398 if (needsPush()) { 399 getDest().createPushAssignmentResult(gen); 400 } 401 getDest().emitStore(gen); 402 } else { 403 super.createBCode(gen); 404 } 405 } 406 407 // shift assign expression 408 public void AssignExpr.emitShiftExpr(CodeGeneration gen) { 409 TypeDecl dest = getDest().type(); 410 TypeDecl source = getSource().type(); 411 TypeDecl type = dest.unaryNumericPromotion(); 412 getDest().createAssignLoadDest(gen); 413 dest.emitCastTo(gen, type); 414 getSource().createBCode(gen); 415 source.emitCastTo(gen, typeInt()); 416 createAssignOp(gen, type); 417 type.emitCastTo(gen, dest); 418 if (needsPush()) { 419 getDest().createPushAssignmentResult(gen); 420 } 421 getDest().emitStore(gen); 422 } 423 public void AssignLShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 424 public void AssignRShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 425 public void AssignURShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 426 427 // load left hand side of destination in a simple assign expression 428 public void Expr.createAssignSimpleLoadDest(CodeGeneration gen) { 429 } 430 public void AbstractDot.createAssignSimpleLoadDest(CodeGeneration gen) { 431 lastAccess().createAssignSimpleLoadDest(gen); 432 } 433 public void VarAccess.createAssignSimpleLoadDest(CodeGeneration gen) { 434 createLoadQualifier(gen); 435 } 436 public void ArrayAccess.createAssignSimpleLoadDest(CodeGeneration gen) { 437 prevExpr().createBCode(gen); 438 getExpr().createBCode(gen); 439 } 440 441 /** 442 * duplicate top value on stack and store below destination element 443 */ 444 public void Expr.createPushAssignmentResult(CodeGeneration gen) { 445 } 446 public void AbstractDot.createPushAssignmentResult(CodeGeneration gen) { 447 lastAccess().createPushAssignmentResult(gen); 448 } 449 public void VarAccess.createPushAssignmentResult(CodeGeneration gen) { 450 if (hostType().needsAccessorFor(decl())) { 451 return; 452 } 453 if (decl().isInstanceVariable()) { 454 type().emitDup_x1(gen); 455 } else { 456 type().emitDup(gen); 457 } 458 } 459 public void ArrayAccess.createPushAssignmentResult(CodeGeneration gen) { 460 type().emitDup_x2(gen); 461 } 462 463 // load left hand side of destination in a compound assign expression 464 public void Expr.createAssignLoadDest(CodeGeneration gen) { 465 } 466 public void AbstractDot.createAssignLoadDest(CodeGeneration gen) { 467 lastAccess().createAssignLoadDest(gen); 468 } 469 public void VarAccess.createAssignLoadDest(CodeGeneration gen) { 470 createLoadQualifier(gen); 471 Variable v = decl(); 472 if (v.isInstanceVariable()) { 473 gen.emitDup(); 474 } 475 if (v instanceof VariableDeclaration) { 476 VariableDeclaration decl = (VariableDeclaration) v; 477 decl.type().emitLoadLocal(gen, decl.localNum()); 478 } else if (v instanceof ParameterDeclaration) { 479 ParameterDeclaration decl = (ParameterDeclaration) v; 480 decl.type().emitLoadLocal(gen, decl.localNum()); 481 } else if (v instanceof FieldDeclaration) { 482 FieldDeclaration f = (FieldDeclaration) v; 483 if (requiresAccessor()) { 484 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 485 } else { 486 f.emitLoadField(gen, fieldQualifierType()); 487 } 488 } 489 } 490 public void ArrayAccess.createAssignLoadDest(CodeGeneration gen) { 491 prevExpr().createBCode(gen); 492 gen.emitDup(); 493 getExpr().createBCode(gen); 494 typeInt().emitDup_x1(gen); 495 gen.emit(type().arrayLoad()); 496 } 497 498 // select the typed operation for a compound assign expression 499 public void AssignExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { 500 throw new Error("Operation createAssignOp is not implemented for " + getClass().getName()); 501 } 502 public void AssignMulExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.mul(gen); } 503 public void AssignDivExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.div(gen); } 504 public void AssignModExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.rem(gen); } 505 public void AssignPlusExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.add(gen); } 506 public void AssignMinusExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.sub(gen); } 507 public void AssignLShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.shl(gen); } 508 public void AssignRShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.shr(gen); } 509 public void AssignURShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.ushr(gen); } 510 public void AssignAndExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitand(gen); } 511 public void AssignXorExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitxor(gen); } 512 public void AssignOrExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitor(gen); } 513 514 public void AbstractDot.createBCode(CodeGeneration gen) { 515 lastAccess().createBCode(gen); 516 } 517 518 public void VarAccess.createBCode(CodeGeneration gen) { 519 Variable v = decl(); 520 if (v instanceof VariableDeclaration) { 521 VariableDeclaration decl = (VariableDeclaration) v; 522 if (decl.hostType() == hostType()) { 523 decl.type().emitLoadLocal(gen, decl.localNum()); 524 } else { 525 emitLoadLocalInNestedClass(gen, decl); 526 } 527 } else if (v instanceof ParameterDeclaration) { 528 ParameterDeclaration decl = (ParameterDeclaration) v; 529 if (decl.hostType() == hostType()) { 530 decl.type().emitLoadLocal(gen, decl.localNum()); 531 } else { 532 emitLoadLocalInNestedClass(gen, decl); 533 } 534 } else if (v instanceof FieldDeclaration) { 535 FieldDeclaration f = (FieldDeclaration) v; 536 createLoadQualifier(gen); 537 if (f.isConstant() && (f.type().isPrimitive() || f.type().isString())) { 538 if (!f.isStatic()) { 539 fieldQualifierType().emitPop(gen); 540 } 541 f.constant().createBCode(gen); 542 } else if (requiresAccessor()) { 543 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 544 } else { 545 f.emitLoadField(gen, fieldQualifierType()); 546 } 547 } 548 } 549 550 syn boolean TypeDecl.needsAccessorFor(Variable v) { 551 if (!(v instanceof FieldDeclaration)) { 552 return false; 553 } 554 FieldDeclaration f = (FieldDeclaration) v; 555 if (f.isConstant() && (f.type().isPrimitive() || f.type().isString())) { 556 return false; 557 } 558 return f.isPrivate() && !hasField(v.name()); 559 } 560 561 inh boolean Access.inExplicitConstructorInvocation(); 562 public void Access.emitLoadLocalInNestedClass(CodeGeneration gen, Variable v) { 563 if (inExplicitConstructorInvocation() && enclosingBodyDecl() instanceof ConstructorDecl) { 564 ConstructorDecl c = (ConstructorDecl) enclosingBodyDecl(); 565 v.type().emitLoadLocal(gen, c.localIndexOfEnclosingVariable(v)); 566 } else { 567 String classname = hostType().constantPoolName(); 568 String desc = v.type().typeDescriptor(); 569 String name = "val$" + v.name(); 570 int index = gen.constantPool().addFieldref(classname, name, desc); 571 gen.emit(Bytecode.ALOAD_0); 572 gen.emit(Bytecode.GETFIELD, v.type().variableSize() - 1).add2(index); 573 } 574 } 575 576 protected void VarAccess.createLoadQualifier(CodeGeneration gen) { 577 Variable v = decl(); 578 if (v instanceof FieldDeclaration) { 579 FieldDeclaration f = (FieldDeclaration) v; 580 if (hasPrevExpr()) { 581 // load explicit qualifier 582 prevExpr().createBCode(gen); 583 // pop qualifier stack element for class variables 584 // this qualifier must be computed to ensure side effects 585 if (!prevExpr().isTypeAccess() && f.isClassVariable()) { 586 prevExpr().type().emitPop(gen); 587 } 588 } else if (f.isInstanceVariable()) { 589 emitThis(gen, fieldQualifierType()); 590 } 591 } 592 } 593 594 public void MethodAccess.createBCode(CodeGeneration gen) { 595 createLoadQualifier(gen); 596 597 if (program().options().hasOption("-debug")) { 598 if (decl().type().isUnknown()) { 599 System.err.println("Could not bind " + this); 600 for (int i = 0; i < getNumArg(); ++i) { 601 System.err.println("Argument " + getArg(i) 602 + " is of type " + getArg(i).type().typeName()); 603 if (getArg(i).varDecl() != null) { 604 System.err.println(getArg(i).varDecl() + " in " 605 + getArg(i).varDecl().hostType().typeName()); 606 } 607 } 608 if (isQualified()) { 609 System.err.println("Qualifier " + qualifier() 610 + " is of type " + qualifier().type().typeName()); 611 } 612 throw new Error("Could not bind " + this); 613 } 614 if (decl().getNumParameter() != getNumArg()) { 615 System.err.println(this 616 + " does not have the same number of arguments as " + decl()); 617 } 618 } 619 620 for (int i = 0; i < getNumArg(); ++i) { 621 getArg(i).createBCode(gen); 622 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 623 } 624 625 if (!decl().isStatic() && isQualified() && prevExpr().isSuperAccess()) { 626 if (!hostType().instanceOf(prevExpr().type())) { 627 decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget()); 628 } else { 629 decl().emitInvokeSpecialMethod(gen, methodQualifierType()); 630 } 631 } else { 632 decl().emitInvokeMethod(gen, methodQualifierType()); 633 } 634 } 635 636 protected void MethodAccess.createLoadQualifier(CodeGeneration gen) { 637 MethodDecl m = decl(); 638 if (hasPrevExpr()) { 639 // load explicit qualifier 640 prevExpr().createBCode(gen); 641 // pop qualifier stack element for class variables 642 // this qualifier must be computed to ensure side effects 643 if (m.isStatic() && !prevExpr().isTypeAccess()) { 644 prevExpr().type().emitPop(gen); 645 } 646 } else if (!m.isStatic()) { 647 // load implicit this qualifier 648 emitThis(gen, methodQualifierType()); 649 } 650 } 651 652 public void ArrayAccess.createBCode(CodeGeneration gen) { 653 prevExpr().createBCode(gen); 654 getExpr().createBCode(gen); 655 gen.emit(type().arrayLoad()); 656 } 657 658 public void ThisAccess.createBCode(CodeGeneration gen) { 659 emitThis(gen, decl()); 660 } 661 public void SuperAccess.createBCode(CodeGeneration gen) { 662 emitThis(gen, decl()); 663 } 664 665 // load this where hostType is the target this instance 666 // supporting inner classes and in explicit contructor invocations 667 public void Access.emitThis(CodeGeneration gen, TypeDecl targetDecl) { 668 if (targetDecl == hostType()) { 669 gen.emit(Bytecode.ALOAD_0); 670 } else { 671 TypeDecl enclosing = hostType(); 672 if (inExplicitConstructorInvocation()) { 673 gen.emit(Bytecode.ALOAD_1); 674 enclosing = enclosing.enclosing(); 675 } else { 676 gen.emit(Bytecode.ALOAD_0); 677 } 678 while (enclosing != targetDecl) { 679 String classname = enclosing.constantPoolName(); 680 enclosing = enclosing.enclosingType(); 681 String desc = enclosing.typeDescriptor(); 682 int index = gen.constantPool().addFieldref(classname, "this$0", desc); 683 gen.emit(Bytecode.GETFIELD, 0).add2(index); 684 } 685 } 686 } 687 688 689 public void ConstructorAccess.createBCode(CodeGeneration gen) { 690 ConstructorDecl c = decl(); 691 int index = 0; 692 // this 693 gen.emitLoadReference(index++); 694 // this$0 695 if (c.needsEnclosing()) { 696 gen.emitLoadReference(index++); 697 } 698 if (c.needsSuperEnclosing()) { 699 gen.emitLoadReference(index++); 700 } 701 702 // args 703 for (int i = 0; i < getNumArg(); ++i) { 704 getArg(i).createBCode(gen); 705 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 706 } 707 if (decl().isPrivate() && decl().hostType() != hostType()) { 708 gen.emit(Bytecode.ACONST_NULL); 709 decl().createAccessor().emitInvokeConstructor(gen); 710 } else { 711 decl().emitInvokeConstructor(gen); 712 } 713 } 714 715 public void SuperConstructorAccess.createBCode(CodeGeneration gen) { 716 ConstructorDecl c = decl(); 717 718 // this 719 gen.emit(Bytecode.ALOAD_0); 720 721 if (c.needsEnclosing()) { 722 if (hasPrevExpr() && !prevExpr().isTypeAccess()) { 723 prevExpr().createBCode(gen); 724 gen.emitDup(); 725 int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;"); 726 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); 727 gen.emitPop(); 728 } else { 729 if (hostType().needsSuperEnclosing()) { 730 if (hostType().needsEnclosing()) { 731 gen.emit(Bytecode.ALOAD_2); 732 } else { 733 gen.emit(Bytecode.ALOAD_1); 734 } 735 } else { 736 emitThis(gen, superConstructorQualifier(c.hostType().enclosingType())); 737 } 738 } 739 } 740 741 // args 742 for (int i = 0; i < getNumArg(); ++i) { 743 getArg(i).createBCode(gen); 744 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 745 } 746 if (decl().isPrivate() && decl().hostType() != hostType()) { 747 gen.emit(Bytecode.ACONST_NULL); 748 decl().createAccessor().emitInvokeConstructor(gen); 749 } else { 750 decl().emitInvokeConstructor(gen); 751 } 752 } 753 754 // 15.9.2 755 private void ClassInstanceExpr.emitLocalEnclosing(CodeGeneration gen, TypeDecl localClass) { 756 if (!localClass.inStaticContext()) { 757 emitThis(gen, localClass.enclosingType()); 758 } 759 } 760 private void ClassInstanceExpr.emitInnerMemberEnclosing(CodeGeneration gen, TypeDecl innerClass) { 761 if (hasPrevExpr()) { 762 prevExpr().createBCode(gen); 763 gen.emitDup(); 764 int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;"); 765 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); 766 gen.emitPop(); 767 } else { 768 TypeDecl enclosing = hostType(); 769 while (enclosing != null && !enclosing.hasType(innerClass.name())) { 770 enclosing = enclosing.enclosingType(); 771 } 772 if (enclosing == null) { 773 throw new Error(errorPrefix() + "Could not find enclosing for " + this); 774 } else { 775 emitThis(gen, enclosing); 776 } 777 } 778 } 779 public void ClassInstanceExpr.createBCode(CodeGeneration gen) { 780 type().emitNew(gen); 781 type().emitDup(gen); 782 783 // 15.9.2 first part 784 if (type().isAnonymous()) { 785 if (type().isAnonymousInNonStaticContext()) { 786 if (type().inExplicitConstructorInvocation()) { 787 gen.emit(Bytecode.ALOAD_1); 788 } else { 789 gen.emit(Bytecode.ALOAD_0); 790 } 791 } 792 // 15.9.2 second part 793 ClassDecl C = (ClassDecl) type(); 794 TypeDecl S = C.superclass(); 795 if (S.isLocalClass()) { 796 if (!type().inStaticContext()) { 797 emitLocalEnclosing(gen, S); 798 } 799 } else if (S.isInnerType()) { 800 emitInnerMemberEnclosing(gen, S); 801 } 802 } else if (type().isLocalClass()) { 803 if (!type().inStaticContext()) { 804 emitLocalEnclosing(gen, type()); 805 } 806 } else if (type().isInnerType()) { 807 emitInnerMemberEnclosing(gen, type()); 808 } 809 /* 810 // 15.9.2 first part 811 if (type().isAnonymous()) { 812 if (type().isAnonymousInNonStaticContext()) { 813 if (type().inExplicitConstructorInvocation()) { 814 gen.emit(Bytecode.ALOAD_1); 815 } else { 816 gen.emit(Bytecode.ALOAD_0); 817 } 818 } 819 if (type().needsSuperEnclosing()) { 820 // 15.9.2 second part 821 ClassDecl C = (ClassDecl) type(); 822 TypeDecl S = C.superclass(); 823 if (S.isLocalClass()) { 824 emitLocalEnclosing(gen, S); 825 } else if (S.isInnerType()) { 826 emitInnerMemberEnclosing(gen, S); 827 } 828 } 829 } else if (type().isLocalClass()) { 830 emitLocalEnclosing(gen, type()); 831 } else if (type().isInnerType()) { 832 emitInnerMemberEnclosing(gen, type()); 833 } 834 */ 835 836 for (int i = 0; i < getNumArg(); ++i) { 837 getArg(i).createBCode(gen); 838 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 839 } 840 841 if (decl().isPrivate() && type() != hostType()) { 842 gen.emit(Bytecode.ACONST_NULL); 843 decl().createAccessor().emitInvokeConstructor(gen); 844 } else { 845 decl().emitInvokeConstructor(gen); 846 } 847 } 848 849 public void ArrayCreationExpr.createBCode(CodeGeneration gen) { 850 if (hasArrayInit()){ 851 getArrayInit().createBCode(gen); 852 } else { 853 getTypeAccess().createBCode(gen); // push array sizes 854 if (type().componentType().isPrimitive()) { 855 gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor()); 856 } else { 857 if (numArrays() == 1) { 858 String n = type().componentType().arrayTypeDescriptor(); 859 int index = gen.constantPool().addClass(n); 860 gen.emit(Bytecode.ANEWARRAY).add2(index); 861 } else { 862 String n = type().arrayTypeDescriptor(); 863 int index = gen.constantPool().addClass(n); 864 gen.emit(Bytecode.MULTIANEWARRAY, 1 - numArrays()).add2(index).add(numArrays()); 865 } 866 } 867 } 868 } 869 870 public void ArrayInit.createBCode(CodeGeneration gen) { 871 IntegerLiteral.push(gen, getNumInit()); 872 if (type().componentType().isPrimitive()) { 873 gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor()); 874 } else { 875 String n = type().componentType().arrayTypeDescriptor(); 876 int index = gen.constantPool().addClass(n); 877 gen.emit(Bytecode.ANEWARRAY).add2(index); 878 } 879 for (int i = 0; i < getNumInit(); i++) { 880 gen.emitDup(); 881 IntegerLiteral.push(gen, i); 882 getInit(i).createBCode(gen); 883 if (getInit(i) instanceof ArrayInit) { 884 gen.emit(Bytecode.AASTORE); 885 } else { 886 getInit(i).type().emitAssignConvTo(gen, expectedType()); // AssignConversion 887 gen.emit(expectedType().arrayStore()); 888 } 889 } 890 } 891 892 public void ArrayTypeAccess.createBCode(CodeGeneration gen) { 893 getAccess().createBCode(gen); 894 } 895 public void ArrayTypeWithSizeAccess.createBCode(CodeGeneration gen) { 896 getAccess().createBCode(gen); 897 getExpr().createBCode(gen); 898 } 899 900 syn String TypeDecl.arrayTypeDescriptor() { throw new Error("Operation not supported"); } 901 eq ArrayDecl.arrayTypeDescriptor() = typeDescriptor(); 902 eq ClassDecl.arrayTypeDescriptor() = constantPoolName(); 903 eq InterfaceDecl.arrayTypeDescriptor() = constantPoolName(); 904 905 syn int TypeDecl.arrayPrimitiveTypeDescriptor() { error(); return -1; } 906 eq BooleanType.arrayPrimitiveTypeDescriptor() = 4; // T_BOOLEAN 907 eq CharType.arrayPrimitiveTypeDescriptor() = 5; // T_CHAR 908 eq FloatType.arrayPrimitiveTypeDescriptor() = 6; // T_FLOAT 909 eq DoubleType.arrayPrimitiveTypeDescriptor() = 7; // T_DOUBLE 910 eq ByteType.arrayPrimitiveTypeDescriptor() = 8; // T_BYTE 911 eq ShortType.arrayPrimitiveTypeDescriptor() = 9; // T_SHORT 912 eq IntType.arrayPrimitiveTypeDescriptor() = 10; // T_INT 913 eq LongType.arrayPrimitiveTypeDescriptor() = 11; // T_LONG 914 915 public void Unary.createBCode(CodeGeneration gen) { 916 super.createBCode(gen); 917 emitOperation(gen); 918 } 919 920 public void CastExpr.createBCode(CodeGeneration gen) { 921 getExpr().createBCode(gen); 922 getExpr().type().emitCastTo(gen, type()); 923 } 924 925 // TODO: consider using IINC or WIDE,IINC 926 927 public void Unary.emitPostfix(CodeGeneration gen, int constant) { 928 Expr operand = getOperand(); 929 while (operand instanceof ParExpr) { 930 operand = ((ParExpr) operand).getExpr(); 931 } 932 Access access = ((Access) operand).lastAccess(); 933 access.createAssignLoadDest(gen); 934 if (needsPush()) { 935 access.createPushAssignmentResult(gen); 936 } 937 TypeDecl type = access.type().binaryNumericPromotion(typeInt()); 938 type.emitPushConstant(gen, constant); 939 type.add(gen); 940 type.emitCastTo(gen, access.type()); 941 access.emitStore(gen); 942 } 943 public void PostIncExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, 1); } 944 public void PostDecExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, -1); } 945 946 public void Unary.emitPrefix(CodeGeneration gen, int constant) { 947 Expr operand = getOperand(); 948 while (operand instanceof ParExpr) { 949 operand = ((ParExpr) operand).getExpr(); 950 } 951 Access access = ((Access) operand).lastAccess(); 952 access.createAssignLoadDest(gen); 953 TypeDecl type = access.type().binaryNumericPromotion(typeInt()); 954 type.emitPushConstant(gen, constant); 955 type.add(gen); 956 type.emitCastTo(gen, access.type()); 957 if (needsPush()) { 958 access.createPushAssignmentResult(gen); 959 } 960 access.emitStore(gen); 961 } 962 public void PreIncExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, 1); } 963 public void PreDecExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, -1); } 964 965 public void Binary.createBCode(CodeGeneration gen) { 966 getLeftOperand().createBCode(gen); 967 getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 968 getRightOperand().createBCode(gen); 969 getRightOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 970 emitOperation(gen); 971 } 972 973 public void Binary.emitShiftExpr(CodeGeneration gen) { 974 getLeftOperand().createBCode(gen); 975 getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 976 getRightOperand().createBCode(gen); 977 getRightOperand().type().emitCastTo(gen, typeInt()); 978 emitOperation(gen); 979 } 980 public void LShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 981 public void RShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 982 public void URShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 983 984 public void AddExpr.createBCode(CodeGeneration gen) { 985 if (!type().isString()) { 986 super.createBCode(gen); 987 } else if (isConstant()) { 988 StringLiteral.push(gen, constant().stringValue()); 989 } else { 990 TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer"); 991 String classname = stringBuffer.constantPoolName(); 992 String desc; 993 int index; 994 TypeDecl argumentType; 995 if (firstStringAddPart()) { 996 stringBuffer.emitNew(gen); // new StringBuffer 997 gen.emitDup(); // dup 998 desc = "()V"; 999 index = gen.constantPool().addMethodref(classname, "<init>", desc); 1000 gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer() 1001 getLeftOperand().createBCode(gen); // left 1002 argumentType = getLeftOperand().type().stringPromotion(); 1003 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 1004 index = gen.constantPool().addMethodref(classname, "append", desc); 1005 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 1006 } else { 1007 getLeftOperand().createBCode(gen); 1008 } 1009 getRightOperand().createBCode(gen); // right 1010 argumentType = getRightOperand().type().stringPromotion(); 1011 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 1012 index = gen.constantPool().addMethodref(classname, "append", desc); 1013 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 1014 if (lastStringAddPart()) { 1015 desc = "()" + type().typeDescriptor(); 1016 index = gen.constantPool().addMethodref(classname, "toString", desc); 1017 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString 1018 } 1019 } 1020 } 1021 1022 syn boolean Expr.canBeTrue() = !isFalse(); 1023 eq CastExpr.canBeTrue() = getExpr().canBeTrue(); 1024 eq ParExpr.canBeTrue() = getExpr().canBeTrue(); 1025 eq AbstractDot.canBeTrue() = lastAccess().canBeTrue(); 1026 eq OrLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() || getRightOperand().canBeTrue(); 1027 eq AndLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() && getRightOperand().canBeTrue(); 1028 eq ConditionalExpr.canBeTrue() = 1029 type().isBoolean() 1030 && (getCondition().canBeTrue() && getTrueExpr().canBeTrue() 1031 || getCondition().canBeFalse() && getFalseExpr().canBeTrue()); 1032 eq LogNotExpr.canBeTrue() = getOperand().canBeFalse(); 1033 1034 syn boolean Expr.canBeFalse() = !isTrue(); 1035 eq CastExpr.canBeFalse() = getExpr().canBeFalse(); 1036 eq ParExpr.canBeFalse() = getExpr().canBeFalse(); 1037 eq AbstractDot.canBeFalse() = lastAccess().canBeFalse(); 1038 eq OrLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() && getRightOperand().canBeFalse(); 1039 eq AndLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() || getRightOperand().canBeFalse(); 1040 eq ConditionalExpr.canBeFalse() = 1041 type().isBoolean() 1042 && (getCondition().canBeTrue() && getTrueExpr().canBeFalse() 1043 || getCondition().canBeFalse() && getFalseExpr().canBeFalse()); 1044 eq LogNotExpr.canBeFalse() = getOperand().canBeTrue(); 1045 1046 public void RelationalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1047 public void LogNotExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1048 public void LogicalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1049 1050 protected void Expr.emitBooleanCondition(CodeGeneration gen) { 1051 int end_label = -1; 1052 int false_label = -1; 1053 if (!isConstant()) { 1054 false_label = gen.constantPool().newLabel(); 1055 branchFalse(gen, false_label); 1056 } 1057 if (canBeTrue()) { 1058 BooleanLiteral.push(gen, true); 1059 if (canBeFalse()) { 1060 end_label = gen.constantPool().newLabel(); 1061 gen.emitGoto(end_label); 1062 gen.changeStackDepth(-1); // discard value from stack depth computation 1063 } 1064 } 1065 if (false_label != -1) { 1066 gen.addLabel(false_label); 1067 } 1068 if (canBeFalse()) { 1069 BooleanLiteral.push(gen, false); 1070 } 1071 if (end_label != -1) { 1072 gen.addLabel(end_label); 1073 } 1074 } 1075 1076 public void ConditionalExpr.createBCode(CodeGeneration gen) { 1077 int end_label = -1; 1078 int false_label = -1; 1079 if (!getCondition().isConstant()) { 1080 false_label = gen.constantPool().newLabel(); 1081 getCondition().branchFalse(gen, false_label); 1082 } 1083 if (getCondition().canBeTrue()) { 1084 getTrueExpr().createBCode(gen); 1085 getTrueExpr().type().emitCastTo(gen, type()); 1086 if (getCondition().canBeFalse()) { 1087 end_label = gen.constantPool().newLabel(); 1088 gen.emitGoto(end_label); 1089 gen.changeStackDepth(-type().variableSize()); 1090 } 1091 } 1092 if (false_label != -1) { 1093 gen.addLabel(false_label); 1094 } 1095 if (getCondition().canBeFalse()) { 1096 getFalseExpr().createBCode(gen); 1097 getFalseExpr().type().emitCastTo(gen, type()); 1098 } 1099 if (end_label != -1) { 1100 gen.addLabel(end_label); 1101 } 1102 } 1103 1104 /** 1105 * Generate a conditional branch statement. The branch should be taken if the 1106 * expression evaluates to true. May in some cases not result in an actual 1107 * branch statement if the branch would never be taken. 1108 * @param gen code generator 1109 * @param target target label to jump to if the condition was true 1110 */ 1111 public void Expr.branchTrue(CodeGeneration gen, int target) { 1112 // branch when true 1113 if (isConstant()) { 1114 if (isTrue()) { 1115 gen.emitGoto(target); 1116 //gen.GOTO(target); 1117 } // else { fallthrough } 1118 } else { 1119 createBCode(gen); 1120 gen.emitCompare(Bytecode.IFNE, target); 1121 //gen.IFNE(target);// branch if value != 0 1122 } 1123 } 1124 1125 public void ParExpr.branchTrue(CodeGeneration gen, int target) { 1126 // branch when true 1127 getExpr().branchTrue(gen, target); 1128 } 1129 1130 public void AbstractDot.branchTrue(CodeGeneration gen, int target) { 1131 // branch when true 1132 lastAccess().branchTrue(gen, target); 1133 } 1134 1135 public void LogNotExpr.branchTrue(CodeGeneration gen, int target) { 1136 // branch when true 1137 getOperand().branchFalse(gen, target); 1138 } 1139 1140 public void AndLogicalExpr.branchTrue(CodeGeneration gen, int target) { 1141 // branch when true 1142 Expr left = getLeftOperand(); 1143 Expr right = getRightOperand(); 1144 int skip_lbl = -1; 1145 if (!left.isConstant()) { 1146 skip_lbl = gen.constantPool().newLabel(); 1147 left.branchFalse(gen, skip_lbl); 1148 } 1149 if (left.canBeTrue()) { 1150 right.branchTrue(gen, target); 1151 } 1152 if (skip_lbl != -1) { 1153 gen.addLabel(skip_lbl); 1154 } 1155 } 1156 1157 public void OrLogicalExpr.branchTrue(CodeGeneration gen, int target) { 1158 // branch when true 1159 Expr left = getLeftOperand(); 1160 Expr right = getRightOperand(); 1161 if (!left.isFalse()) { 1162 left.branchTrue(gen, target); 1163 } 1164 if (left.canBeFalse()) { 1165 right.branchTrue(gen, target); 1166 } 1167 } 1168 1169 public void ConditionalExpr.branchTrue(CodeGeneration gen, int target) { 1170 // branch when true 1171 int else_label = -1; 1172 int end_label = -1; 1173 if (!getCondition().isConstant()) { 1174 else_label = gen.constantPool().newLabel(); 1175 getCondition().branchFalse(gen, else_label); 1176 } 1177 if (getCondition().canBeTrue()) { 1178 getTrueExpr().branchTrue(gen, target); 1179 if (getCondition().canBeFalse() && getTrueExpr().canBeFalse()) { 1180 end_label = gen.constantPool().newLabel(); 1181 gen.emitGoto(end_label); 1182 //gen.GOTO(end_label); 1183 } 1184 } 1185 if (else_label != -1) { 1186 gen.addLabel(else_label); 1187 } 1188 if (getCondition().canBeFalse()) { 1189 getFalseExpr().branchTrue(gen, target); 1190 } 1191 if (end_label != -1) { 1192 gen.addLabel(end_label); 1193 } 1194 } 1195 1196 public void RelationalExpr.branchTrue(CodeGeneration gen, int target) { 1197 // branch when true 1198 if (isConstant()) { 1199 if (isTrue()) { 1200 gen.emitGoto(target); 1201 //gen.GOTO(target); 1202 } 1203 } else { 1204 TypeDecl type = getLeftOperand().type(); 1205 if (type.isNumericType()) { 1206 type = binaryNumericPromotedType(); 1207 getLeftOperand().createBCode(gen); 1208 getLeftOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1209 getRightOperand().createBCode(gen); 1210 getRightOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1211 } else { 1212 getLeftOperand().createBCode(gen); 1213 getRightOperand().createBCode(gen); 1214 } 1215 compareBranch(gen, target, type); 1216 } 1217 } 1218 1219 /** 1220 * Generate a conditional branch statement. The branch should be taken if the 1221 * expression evaluates to false. May in some cases not result in an actual 1222 * branch statement if the branch would never be taken. 1223 * @param gen code generator 1224 * @param target target label to jump to if the condition was false 1225 */ 1226 public void Expr.branchFalse(CodeGeneration gen, int target) { 1227 // branch when false 1228 if (isConstant()) { 1229 if (isFalse()) { 1230 gen.emitGoto(target); 1231 //gen.GOTO(target); 1232 } // else { fallthrough } 1233 } else { 1234 createBCode(gen); 1235 gen.emitCompare(Bytecode.IFEQ, target); 1236 //gen.IFEQ(target);// branch if value == 0 1237 } 1238 } 1239 1240 public void ParExpr.branchFalse(CodeGeneration gen, int target) { 1241 // branch when false 1242 getExpr().branchFalse(gen, target); 1243 } 1244 1245 public void AbstractDot.branchFalse(CodeGeneration gen, int target) { 1246 // branch when false 1247 lastAccess().branchFalse(gen, target); 1248 } 1249 1250 public void LogNotExpr.branchFalse(CodeGeneration gen, int target) { 1251 // branch when false 1252 getOperand().branchTrue(gen, target); 1253 } 1254 1255 public void AndLogicalExpr.branchFalse(CodeGeneration gen, int target) { 1256 // branch when false 1257 Expr left = getLeftOperand(); 1258 Expr right = getRightOperand(); 1259 if (!left.isTrue()) { 1260 left.branchFalse(gen, target); 1261 } 1262 if (left.canBeTrue()) { 1263 right.branchFalse(gen, target); 1264 } 1265 } 1266 1267 public void OrLogicalExpr.branchFalse(CodeGeneration gen, int target) { 1268 // branch when false 1269 Expr left = getLeftOperand(); 1270 Expr right = getRightOperand(); 1271 int skip_lbl = -1; 1272 if (!left.isConstant()) { 1273 skip_lbl = gen.constantPool().newLabel(); 1274 left.branchTrue(gen, skip_lbl); 1275 } 1276 if (left.canBeFalse()) { 1277 right.branchFalse(gen, target); 1278 } 1279 if (skip_lbl != -1) { 1280 gen.addLabel(skip_lbl); 1281 } 1282 } 1283 1284 public void ConditionalExpr.branchFalse(CodeGeneration gen, int target) { 1285 // branch when false 1286 int else_label = -1; 1287 int end_label = -1; 1288 if (!getCondition().isConstant()) { 1289 else_label = gen.constantPool().newLabel(); 1290 getCondition().branchFalse(gen, else_label); 1291 } 1292 if (getCondition().canBeTrue()) { 1293 getTrueExpr().branchFalse(gen, target); 1294 if (getCondition().canBeFalse() && getTrueExpr().canBeTrue()) { 1295 end_label = gen.constantPool().newLabel(); 1296 gen.emitGoto(end_label); 1297 //gen.GOTO(end_label); 1298 } 1299 } 1300 if (else_label != -1) { 1301 gen.addLabel(else_label); 1302 } 1303 if (getCondition().canBeFalse()) { 1304 getFalseExpr().branchFalse(gen, target); 1305 } 1306 if (end_label != -1) { 1307 gen.addLabel(end_label); 1308 } 1309 } 1310 1311 public void RelationalExpr.branchFalse(CodeGeneration gen, int target) { 1312 // branch when false 1313 if (isConstant()) { 1314 if (isFalse()) { 1315 gen.emitGoto(target); 1316 //gen.GOTO(target); 1317 } 1318 } else { 1319 TypeDecl type = getLeftOperand().type(); 1320 if (type.isNumericType()) { 1321 type = binaryNumericPromotedType(); 1322 getLeftOperand().createBCode(gen); 1323 getLeftOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1324 getRightOperand().createBCode(gen); 1325 getRightOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1326 } else { 1327 getLeftOperand().createBCode(gen); 1328 getRightOperand().createBCode(gen); 1329 } 1330 compareNotBranch(gen, target, type); 1331 } 1332 } 1333 1334 public void RelationalExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { 1335 throw new Error("compareBranch not implemented for " + getClass().getName()); 1336 } 1337 public void LTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); } 1338 public void LEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); } 1339 public void GEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); } 1340 public void GTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); } 1341 public void EQExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); } 1342 public void NEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); } 1343 1344 public void RelationalExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { 1345 throw new Error("compareNotBranch not implemented for " + getClass().getName()); 1346 } 1347 public void LTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGEInv(gen, label); } 1348 public void LEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGTInv(gen, label); } 1349 public void GEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLTInv(gen, label); } 1350 public void GTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLEInv(gen, label); } 1351 public void EQExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); } 1352 public void NEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); } 1353 1354 public void InstanceOfExpr.createBCode(CodeGeneration gen) { 1355 getExpr().createBCode(gen); 1356 gen.emitInstanceof(getTypeAccess().type()); 1357 } 1358 1359 public void Stmt.createBCode(CodeGeneration gen) { 1360 gen.addLineNumberEntryAtCurrentPC(this); 1361 } 1362 1363 public void Block.createBCode(CodeGeneration gen) { 1364 //super.createBCode(gen); 1365 for (int i = 0; i < getNumStmt(); i++) { 1366 try { 1367 getStmt(i).createBCode(gen); 1368 } catch (Exception e) { 1369 e.printStackTrace(); 1370 throw new Error("Error generating code for " + errorPrefix() + " " + getStmt(i)); 1371 } 1372 } 1373 gen.addVariableScopeLabel(variableScopeEndLabel(gen)); 1374 } 1375 1376 public void EmptyStmt.createBCode(CodeGeneration gen) { 1377 super.createBCode(gen); 1378 } 1379 1380 syn lazy int LabeledStmt.label() = hostType().constantPool().newLabel(); 1381 syn lazy int LabeledStmt.end_label() = hostType().constantPool().newLabel(); 1382 public void LabeledStmt.createBCode(CodeGeneration gen) { 1383 super.createBCode(gen); 1384 gen.addLabel(label()); 1385 getStmt().createBCode(gen); 1386 gen.addLabel(end_label()); 1387 } 1388 1389 public void ExprStmt.createBCode(CodeGeneration gen) { 1390 super.createBCode(gen); 1391 getExpr().createBCode(gen); 1392 if (needsPop()) { 1393 getExpr().type().emitPop(gen); 1394 } 1395 } 1396 1397 syn lazy DefaultCase SwitchStmt.defaultCase() { 1398 for (int i= 0; i < getBlock().getNumStmt(); i++) { 1399 if (getBlock().getStmt(i) instanceof DefaultCase) { 1400 return (DefaultCase) getBlock().getStmt(i); 1401 } 1402 } 1403 return null; 1404 } 1405 1406 syn lazy int SwitchStmt.end_label() = hostType().constantPool().newLabel(); 1407 1408 public void SwitchStmt.createBCode(CodeGeneration gen) { 1409 super.createBCode(gen); 1410 int switch_label = gen.constantPool().newLabel(); 1411 1412 getExpr().createBCode(gen); 1413 1414 TreeMap<Integer, ConstCase> map = new TreeMap<Integer, ConstCase>(); 1415 for (int i = 0; i < getBlock().getNumStmt(); i++) { 1416 if (getBlock().getStmt(i) instanceof ConstCase) { 1417 ConstCase ca = (ConstCase) getBlock().getStmt(i); 1418 map.put(ca.getValue().constant().intValue(), ca); 1419 } 1420 } 1421 1422 int low = map.isEmpty() ? 0 : map.firstKey(); 1423 int high = map.isEmpty() ? 0 : map.lastKey(); 1424 1425 int tableSwitchSize = 4 * (3 + (high - low + 1)); 1426 int lookupSwitchSize = 4 * (2 + 2 * map.size()); 1427 int pad; 1428 int switchSize; 1429 int switchPos; 1430 boolean tableSwitch = tableSwitchSize < lookupSwitchSize; 1431 1432 gen.addLabel(switch_label); 1433 1434 // Select the switch type which produces the smallest switch instr. 1435 if (tableSwitch) { 1436 // TABLESWITCH 1437 gen.emit(Bytecode.TABLESWITCH); 1438 switchSize = tableSwitchSize; 1439 } else { 1440 // LOOKUPSWITCH 1441 gen.emit(Bytecode.LOOKUPSWITCH); 1442 switchSize = lookupSwitchSize; 1443 } 1444 1445 pad = emitPad(gen); 1446 switchPos = gen.pos(); 1447 1448 // leave room for the address table 1449 gen.skip(switchSize); 1450 1451 getBlock().createBCode(gen); 1452 1453 // write jump address table 1454 int endpos = gen.pos(); 1455 gen.setPos(switchPos); 1456 if (tableSwitch) { 1457 int defaultOffset = defaultOffset(gen, switch_label); 1458 int numCase = high - low + 1; 1459 if (defaultOffset == 0) { 1460 defaultOffset = 1 + pad + switchSize; 1461 } 1462 gen.add4(defaultOffset); 1463 gen.add4(low); 1464 gen.add4(high); 1465 for (int i = low; i <= high; i++) { 1466 ConstCase ca = map.get(i); 1467 if (ca != null) { 1468 int offset = gen.addressOf(ca.label()) 1469 - gen.addressOf(switch_label); 1470 gen.add4(offset); 1471 } else { 1472 gen.add4(defaultOffset); 1473 } 1474 } 1475 } else { 1476 int defaultOffset = defaultOffset(gen, switch_label); 1477 if (defaultOffset == 0) { 1478 defaultOffset = 1 + pad + switchSize; 1479 } 1480 gen.add4(defaultOffset); 1481 gen.add4(map.size()); 1482 for (ConstCase ca : map.values()) { 1483 gen.add4(ca.getValue().constant().intValue()); 1484 int offset = gen.addressOf(ca.label()) 1485 - gen.addressOf(switch_label); 1486 gen.add4(offset); 1487 } 1488 } 1489 gen.setPos(endpos); 1490 1491 gen.addLabel(end_label()); 1492 } 1493 1494 syn int SwitchStmt.numCase() { 1495 int result = 0; 1496 for (int i = 0; i < getBlock().getNumStmt(); i++) { 1497 if (getBlock().getStmt(i) instanceof Case) { 1498 result++; 1499 } 1500 } 1501 return result; 1502 } 1503 1504 private int SwitchStmt.emitPad(CodeGeneration gen) { 1505 int pad = (4 - (gen.pos() % 4)) % 4; 1506 for (int i = 0; i < pad; i++) { 1507 gen.emit(Bytecode.NOP); 1508 } 1509 if (gen.pos() % 4 != 0) { 1510 throw new Error("Switch not at 4-byte boundary:" + gen.pos()); 1511 } 1512 return pad; 1513 } 1514 1515 /** 1516 * Calculate offset to the default label. 1517 * @return bytecode offset to default label (or zero if there is no 1518 * default label) 1519 */ 1520 private int SwitchStmt.defaultOffset(CodeGeneration gen, int switch_label) { 1521 DefaultCase defaultCase = defaultCase(); 1522 if (defaultCase != null) { 1523 int offset = gen.addressOf(defaultCase.label()) 1524 - gen.addressOf(switch_label); 1525 return offset; 1526 } 1527 return 0; 1528 } 1529 1530 syn lazy int Case.label() = hostType().constantPool().newLabel(); 1531 1532 public void Case.createBCode(CodeGeneration gen) { 1533 gen.addLabel(label()); 1534 } 1535 1536 syn lazy int IfStmt.else_branch_label() = hostType().constantPool().newLabel(); 1537 syn lazy int IfStmt.then_branch_label() = hostType().constantPool().newLabel(); 1538 syn lazy int IfStmt.end_label() = hostType().constantPool().newLabel(); 1539 public void IfStmt.createBCode(CodeGeneration gen) { 1540 super.createBCode(gen); 1541 int elseBranch = else_branch_label(); 1542 int thenBranch = then_branch_label(); 1543 int endBranch = end_label(); 1544 if (!getCondition().isConstant()) { 1545 getCondition().branchFalse(gen, elseBranch); 1546 } 1547 gen.addLabel(thenBranch); 1548 if (getCondition().canBeTrue()) { 1549 getThen().createBCode(gen); 1550 if (getThen().canCompleteNormally() && hasElse() && getCondition().canBeFalse()) { 1551 gen.emitGoto(endBranch); 1552 } 1553 } 1554 gen.addLabel(elseBranch); 1555 if (hasElse() && getCondition().canBeFalse()) { 1556 getElse().createBCode(gen); 1557 } 1558 gen.addLabel(endBranch); 1559 } 1560 1561 syn lazy int WhileStmt.cond_label() = hostType().constantPool().newLabel(); 1562 syn lazy int WhileStmt.end_label() = hostType().constantPool().newLabel(); 1563 syn lazy int WhileStmt.stmt_label() = hostType().constantPool().newLabel(); 1564 1565 public void WhileStmt.createBCode(CodeGeneration gen) { 1566 super.createBCode(gen); 1567 gen.addLabel(cond_label()); 1568 if (!getCondition().isConstant()) { 1569 getCondition().branchFalse(gen, end_label()); 1570 } 1571 gen.addLabel(stmt_label()); 1572 if (getCondition().canBeTrue()) { 1573 getStmt().createBCode(gen); 1574 if (getStmt().canCompleteNormally()) { 1575 gen.emitGoto(cond_label()); 1576 } 1577 } 1578 gen.addLabel(end_label()); 1579 } 1580 1581 syn lazy int DoStmt.begin_label() = hostType().constantPool().newLabel(); 1582 syn lazy int DoStmt.cond_label() = hostType().constantPool().newLabel(); 1583 syn lazy int DoStmt.end_label() = hostType().constantPool().newLabel(); 1584 1585 public void DoStmt.createBCode(CodeGeneration gen) { 1586 super.createBCode(gen); 1587 gen.addLabel(begin_label()); 1588 getStmt().createBCode(gen); 1589 gen.addLabel(cond_label()); 1590 getCondition().branchTrue(gen, begin_label()); 1591 gen.addLabel(end_label()); 1592 } 1593 1594 syn lazy int ForStmt.cond_label() = hostType().constantPool().newLabel(); 1595 syn lazy int ForStmt.begin_label() = hostType().constantPool().newLabel(); 1596 syn lazy int ForStmt.update_label() = hostType().constantPool().newLabel(); 1597 syn lazy int ForStmt.end_label() = hostType().constantPool().newLabel(); 1598 1599 public void ForStmt.createBCode(CodeGeneration gen) { 1600 super.createBCode(gen); 1601 for (int i=0; i<getNumInitStmt(); i++) { 1602 getInitStmt(i).createBCode(gen); 1603 } 1604 gen.addLabel(cond_label()); 1605 if (!getCondition().isConstant()) { 1606 getCondition().branchFalse(gen, end_label()); 1607 } 1608 if (getCondition().canBeTrue()) { 1609 gen.addLabel(begin_label()); 1610 getStmt().createBCode(gen); 1611 gen.addLabel(update_label()); 1612 for (int i=0; i<getNumUpdateStmt(); i++) { 1613 getUpdateStmt(i).createBCode(gen); 1614 } 1615 gen.emitGoto(cond_label()); 1616 } 1617 gen.addLabel(end_label()); 1618 gen.addVariableScopeLabel(variableScopeEndLabel(gen)); 1619 } 1620 1621 syn int Stmt.break_label() { 1622 throw new UnsupportedOperationException("Can not break at this statement of type " + getClass().getName()); 1623 } 1624 eq ForStmt.break_label() = end_label(); 1625 eq WhileStmt.break_label() = end_label(); 1626 eq DoStmt.break_label() = end_label(); 1627 eq LabeledStmt.break_label() = end_label(); 1628 eq SwitchStmt.break_label() = end_label(); 1629 eq TryStmt.break_label() = label_end(); 1630 syn lazy int SynchronizedStmt.start_label() = hostType().constantPool().newLabel(); 1631 1632 public void BreakStmt.createBCode(CodeGeneration gen) { 1633 super.createBCode(gen); 1634 if (hasFinally()) { 1635 int nextRange = gen.constantPool().newLabel(); 1636 getFinally().createBCode(gen); 1637 gen.emitGoto(targetStmt().break_label()); 1638 gen.addLabel(nextRange); 1639 gen.monitorRangesStart(this, nextRange); 1640 } else { 1641 gen.emitGoto(targetStmt().break_label()); 1642 } 1643 } 1644 1645 syn int Stmt.continue_label() { 1646 throw new UnsupportedOperationException("Can not continue at this statement"); 1647 } 1648 eq ForStmt.continue_label() = update_label(); 1649 eq WhileStmt.continue_label() = cond_label(); 1650 eq DoStmt.continue_label() = cond_label(); 1651 eq LabeledStmt.continue_label() = getStmt().continue_label(); 1652 1653 // TODO: test continue in try-statement!!! 1654 eq TryStmt.continue_label() = label_end(); 1655 1656 public void ContinueStmt.createBCode(CodeGeneration gen) { 1657 super.createBCode(gen); 1658 if (hasFinally()) { 1659 int nextRange = gen.constantPool().newLabel(); 1660 getFinally().createBCode(gen); 1661 gen.emitGoto(targetStmt().continue_label()); 1662 gen.addLabel(nextRange); 1663 gen.monitorRangesStart(this, nextRange); 1664 } else { 1665 gen.emitGoto(targetStmt().continue_label()); 1666 } 1667 } 1668 1669 public void ReturnStmt.createBCode(CodeGeneration gen) { 1670 super.createBCode(gen); 1671 if (hasResult()) { 1672 TypeDecl type = null; 1673 BodyDecl b = enclosingBodyDecl(); 1674 if (b instanceof MethodDecl) { 1675 type = ((MethodDecl) b).type(); 1676 } else { 1677 throw new Error("Can not create code that returns value within non method"); 1678 } 1679 getResult().createBCode(gen); 1680 getResult().type().emitCastTo(gen, type); 1681 if (hasFinally()) { 1682 int nextRange = gen.constantPool().newLabel(); 1683 type.emitStoreLocal(gen, resultSaveLocalNum()); 1684 getFinally().createBCode(gen); 1685 type.emitLoadLocal(gen, resultSaveLocalNum()); 1686 type.emitReturn(gen); 1687 gen.addLabel(nextRange); 1688 gen.monitorRangesStart(this, nextRange); 1689 } else { 1690 type.emitReturn(gen); 1691 } 1692 } else { 1693 if (hasFinally()) { 1694 int nextRange = gen.constantPool().newLabel(); 1695 getFinally().createBCode(gen); 1696 gen.emitReturn(); 1697 gen.addLabel(nextRange); 1698 gen.monitorRangesStart(this, nextRange); 1699 } else { 1700 gen.emitReturn(); 1701 } 1702 } 1703 } 1704 1705 public void ThrowStmt.createBCode(CodeGeneration gen) { 1706 super.createBCode(gen); 1707 getExpr().createBCode(gen); 1708 gen.emitThrow(); 1709 } 1710 1711 syn lazy int TryStmt.fallthrough_label() = 1712 hasNonEmptyFinally() ? hostType().constantPool().newLabel() : label_end(); 1713 1714 public void TryStmt.createBCode(CodeGeneration gen) { 1715 int block_top_lbl = gen.constantPool().newLabel(); 1716 int block_end_lbl = gen.constantPool().newLabel(); 1717 int fallthrough_lbl = fallthrough_label(); 1718 int handler_lbl = gen.constantPool().newLabel(); 1719 boolean needsHandler = false; 1720 1721 super.createBCode(gen); 1722 gen.addLabel(block_top_lbl); 1723 getBlock().createBCode(gen); 1724 gen.addLabel(block_end_lbl); 1725 1726 if (getBlock().canCompleteNormally()) { 1727 gen.emitGoto(fallthrough_lbl); 1728 } 1729 1730 for (int i = 0; i < getNumCatchClause(); i++) { 1731 CatchClause cc = getCatchClause(i); 1732 cc.createBCode(gen); 1733 cc.exceptionTableEntries(gen, block_top_lbl, block_end_lbl); 1734 if (cc.getBlock().canCompleteNormally()) { 1735 gen.emitGoto(fallthrough_lbl); 1736 } 1737 if (hasNonEmptyFinally()) { 1738 int cc_end_lbl = gen.constantPool().newLabel(); 1739 gen.addLabel(cc_end_lbl); 1740 needsHandler = true; 1741 gen.addException(cc.label(), cc_end_lbl, handler_lbl, 1742 CodeGeneration.ExceptionEntry.CATCH_ALL); 1743 } 1744 } 1745 1746 if (hasNonEmptyFinally()) { 1747 1748 emitExceptionHandler(gen, block_top_lbl, block_end_lbl, handler_lbl, 1749 needsHandler); 1750 1751 // fallthrough finally 1752 gen.addLabel(fallthrough_lbl); 1753 getFinally().createBCode(gen); 1754 } 1755 1756 gen.addLabel(label_end()); 1757 } 1758 1759 /** 1760 * Outer finally host with a finally block that can complete normally 1761 */ 1762 syn FinallyHost TryStmt.outerFinallyHost() { 1763 // find outer finally 1764 FinallyHost outer = this; 1765 Iterator<FinallyHost> iter = finallyIterator(); 1766 while (iter.hasNext()) { 1767 outer = iter.next(); 1768 } 1769 return outer; 1770 } 1771 1772 /** 1773 * Generate catch-all (finally) 1774 */ 1775 public void TryStmt.emitExceptionHandler(CodeGeneration gen, int start_lbl, int end_lbl, int handler_lbl, boolean needsHandler) { 1776 int top_pc = gen.addressOf(start_lbl); 1777 int end_pc = gen.addressOf(end_lbl); 1778 if (needsHandler || top_pc != end_pc) { 1779 // catch-all exception handler (finally) 1780 gen.addLabel(handler_lbl); 1781 gen.changeStackDepth(1); 1782 int num = getBlock().localNum(); 1783 gen.emitStoreReference(num); 1784 getExceptionHandler().createBCode(gen); 1785 gen.emitLoadReference(num); 1786 gen.emit(Bytecode.ATHROW); 1787 1788 gen.addException(start_lbl, end_lbl, handler_lbl, 1789 CodeGeneration.ExceptionEntry.CATCH_ALL); 1790 } 1791 } 1792 1793 public void SynchronizedStmt.emitMonitorEnter(CodeGeneration gen) { 1794 gen.emitDup(); 1795 int num = localNum(); 1796 gen.emitStoreReference(num); 1797 gen.emit(Bytecode.MONITORENTER); 1798 } 1799 1800 syn lazy int CatchClause.label() = hostType().constantPool().newLabel(); 1801 public void BasicCatch.createBCode(CodeGeneration gen) { 1802 gen.addLabel(label()); 1803 // add 1 to stack depth 1804 gen.changeStackDepth(1); 1805 getParameter().type().emitStoreLocal(gen, getParameter().localNum()); 1806 getBlock().createBCode(gen); 1807 } 1808 1809 protected int SynchronizedStmt.monitorId = -1; 1810 1811 public void SynchronizedStmt.createBCode(CodeGeneration gen) { 1812 int lbl_start = gen.constantPool().newLabel(); 1813 super.createBCode(gen); 1814 getExpr().createBCode(gen); 1815 1816 monitorId = gen.monitorEnter(this); 1817 gen.addLabel(lbl_start); 1818 gen.monitorRangeStart(monitorId, lbl_start); 1819 1820 getBlock().createBCode(gen); 1821 1822 if (getBlock().canCompleteNormally()) { 1823 getMonitorExit().createBCode(gen); 1824 gen.emitGoto(label_end()); 1825 } 1826 1827 gen.monitorExit(); 1828 1829 gen.addLabel(label_end()); 1830 } 1831 1832 /** 1833 * Checks if the branch statement leaves the monitor. 1834 * @return <code>true</code> if the branch leaves the monitor 1835 */ 1836 inh boolean Stmt.leavesMonitor(Stmt branch, SynchronizedStmt monitor); 1837 1838 eq BodyDecl.getChild().leavesMonitor(Stmt branch, SynchronizedStmt monitor) { 1839 throw new Error("Enclosing monitor not found!"); 1840 } 1841 1842 eq SynchronizedStmt.getChild().leavesMonitor(Stmt branch, SynchronizedStmt monitor) { 1843 if (monitor == this) { 1844 return true; 1845 } else { 1846 return leavesMonitor(branch, monitor); 1847 } 1848 } 1849 1850 eq BranchTargetStmt.getChild().leavesMonitor(Stmt branch, SynchronizedStmt monitor) { 1851 if (potentialTargetOf(branch)) { 1852 return false; 1853 } else { 1854 return leavesMonitor(branch, monitor); 1855 } 1856 } 1857 1858 /** 1859 * Assert statement bytecode is generated through the transformed 1860 * version of the assert statement! 1861 * 1862 * @see java4/backend/Transformations.jrag 1863 */ 1864 public void AssertStmt.createBCode(CodeGeneration gen) { 1865 throw new UnsupportedOperationException("Assert not yet implemented"); 1866 } 1867 1868 public void LocalClassDeclStmt.createBCode(CodeGeneration gen) { 1869 } 1870 1871 public void ClassAccess.createBCode(CodeGeneration gen) { 1872 if (prevExpr().type().isPrimitiveType() || prevExpr().type().isVoid()) { 1873 TypeDecl typeDecl = lookupType("java.lang", prevExpr().type().primitiveClassName()); 1874 SimpleSet c = typeDecl.memberFields("TYPE"); 1875 FieldDeclaration f = (FieldDeclaration) c.iterator().next(); 1876 f.emitLoadField(gen, typeDecl); 1877 } else { 1878 FieldDeclaration f = hostType().topLevelType().createStaticClassField(prevExpr().type().referenceClassFieldName()); 1879 // add method to perform lookup as a side-effect 1880 MethodDecl m = hostType().topLevelType().createStaticClassMethod(); 1881 1882 int next_label = gen.constantPool().newLabel(); 1883 int end_label = gen.constantPool().newLabel(); 1884 f.emitLoadField(gen, hostType()); 1885 gen.emitBranchNonNull(next_label); 1886 1887 // emit string literal 1888 1889 StringLiteral.push(gen, prevExpr().type().jvmName()); 1890 m.emitInvokeMethod(gen, hostType()); 1891 gen.emitDup(); 1892 f.emitStoreField(gen, hostType()); 1893 gen.emitGoto(end_label); 1894 gen.addLabel(next_label); 1895 gen.changeStackDepth(-1); 1896 f.emitLoadField(gen, hostType()); 1897 gen.addLabel(end_label); 1898 } 1899 } 1900 1901 /** 1902 * Generate bytecode for the monitor exit call. 1903 */ 1904 public void MonitorExit.createBCode(CodeGeneration gen) { 1905 gen.monitorRangeEnd(monitor.monitorId, 1906 hostType().constantPool().newLabel()); 1907 } 1908 1909 /** 1910 * Generate exception handler for monitor closing. 1911 * @param gen 1912 */ 1913 public void MonitorExit.emitMonitorExitHandler(CodeGeneration gen) { 1914 int handler_lbl = handler_label(); 1915 int end_lbl = handler_end_label(); 1916 1917 gen.changeStackDepth(1); 1918 int num = localNum() + 1; 1919 1920 // handler start 1921 gen.addLabel(handler_lbl); 1922 1923 gen.emitStoreReference(num); 1924 1925 gen.emitLoadReference(monitor.localNum()); 1926 gen.emit(Bytecode.MONITOREXIT); 1927 1928 // handler end 1929 gen.addLabel(end_lbl); 1930 1931 gen.emitLoadReference(num); 1932 gen.emit(Bytecode.ATHROW); 1933 1934 // add exception handler for the monitor closing 1935 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101 1936 gen.addException(handler_lbl, end_lbl, handler_lbl, 1937 CodeGeneration.ExceptionEntry.CATCH_ALL); 1938 1939 } 1940 }