001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.util.*; 011 import java.io.*; 012 aspect CreateBCode { 013 inh TypeDecl CatchClause.hostType(); 014 015 public abstract void CatchClause.exceptionTableEntries(CodeGeneration gen, TryStmt tryStmt); 016 017 public void BasicCatch.exceptionTableEntries(CodeGeneration gen, TryStmt tryStmt) { 018 gen.addException( 019 gen.addressOf(tryStmt.label_begin()), 020 gen.addressOf(tryStmt.label_block_end()), 021 gen.addressOf(label()), 022 gen.constantPool().addClass(getParameter().type().constantPoolName()) 023 ); 024 } 025 026 syn lazy boolean TypeDecl.hasClinit() { 027 for(int i = 0; i < getNumBodyDecl(); i++) { 028 BodyDecl b = getBodyDecl(i); 029 if(b instanceof FieldDeclaration) { 030 FieldDeclaration f = (FieldDeclaration)b; 031 if(f.isStatic() && f.hasInit()) { 032 return true; 033 } 034 } 035 else if(b instanceof StaticInitializer) { 036 return true; 037 } 038 } 039 return false; 040 } 041 042 syn lazy CodeGeneration TypeDecl.bytecodes(ConstantPool constantPool) { 043 CodeGeneration gen = new CodeGeneration(constantPool); 044 generateBytecodes(gen); 045 if(!gen.numberFormatError()) 046 return gen; 047 gen = new CodeGeneration(constantPool, true); 048 generateBytecodes(gen); 049 if(!gen.numberFormatError()) 050 return gen; 051 throw new Error("Could not generate code for initializers in " + hostType().typeName()); 052 } 053 private void TypeDecl.generateBytecodes(CodeGeneration gen) { 054 for(int i = 0; i < getNumBodyDecl(); i++) { 055 BodyDecl b = getBodyDecl(i); 056 if(b instanceof FieldDeclaration && b.isBytecodeField() && b.generate()) { 057 FieldDeclaration f = (FieldDeclaration)b; 058 if(f.isStatic() && f.hasInit()) { 059 f.getInit().createBCode(gen); 060 f.getInit().type().emitAssignConvTo(gen, f.type()); // AssignConversion 061 f.emitStoreField(gen, this); 062 } 063 } 064 else if(b instanceof StaticInitializer) { 065 b.createBCode(gen); 066 } 067 } 068 gen.emitReturn(); 069 } 070 071 syn lazy CodeGeneration MethodDecl.bytecodes(ConstantPool constantPool) { 072 //if(options().verbose()) 073 // System.out.println("Generating bytecodes for " + signature() + " in " + hostType().fullName()); 074 CodeGeneration gen = new CodeGeneration(constantPool); 075 generateBytecodes(gen); 076 if(!gen.numberFormatError()) 077 return gen; 078 gen = new CodeGeneration(constantPool, true); 079 generateBytecodes(gen); 080 if(!gen.numberFormatError()) 081 return gen; 082 throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName()); 083 } 084 private void MethodDecl.generateBytecodes(CodeGeneration gen) { 085 int label = gen.variableScopeLabel(); 086 if(!isStatic()) 087 gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); 088 for(int i = 0; i < getNumParameter(); i++) { 089 ParameterDeclaration p = (ParameterDeclaration)getParameter(i); 090 gen.addLocalVariableEntryAtCurrentPC( 091 p.name(), p.type().typeDescriptor(), p.localNum(), label 092 ); 093 } 094 createBCode(gen); 095 if(type() instanceof VoidType) // TODO: canCompleteNormally check as well 096 gen.emitReturn(); 097 gen.addVariableScopeLabel(label); 098 } 099 100 syn lazy CodeGeneration ConstructorDecl.bytecodes(ConstantPool constantPool) { 101 CodeGeneration gen = new CodeGeneration(constantPool); 102 generateBytecodes(gen); 103 if(!gen.numberFormatError()) 104 return gen; 105 gen = new CodeGeneration(constantPool, true); 106 generateBytecodes(gen); 107 if(!gen.numberFormatError()) 108 return gen; 109 throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName()); 110 } 111 private void ConstructorDecl.generateBytecodes(CodeGeneration gen) { 112 int label = gen.variableScopeLabel(); 113 gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); 114 for(int i = 0; i < getNumParameter(); i++) { 115 ParameterDeclaration p = (ParameterDeclaration)getParameter(i); 116 gen.addLocalVariableEntryAtCurrentPC( 117 p.name(), p.type().typeDescriptor(), p.localNum(), label 118 ); 119 } 120 createBCode(gen); 121 gen.emitReturn(); 122 gen.addVariableScopeLabel(label); 123 } 124 125 public void MethodDecl.createBCode(CodeGeneration gen) { 126 try { 127 if(hasBlock()) { 128 gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); 129 getBlock().createBCode(gen); 130 } 131 } catch (Error e) { 132 System.err.println(hostType().typeName() + ": " + this); 133 throw e; 134 } 135 } 136 137 public void ConstructorDecl.createBCode(CodeGeneration gen) { 138 try { 139 boolean needsInit = true; 140 141 if(hasConstructorInvocation()) { 142 getConstructorInvocation().createBCode(gen); 143 Stmt stmt = getConstructorInvocation(); 144 if(stmt instanceof ExprStmt) { 145 ExprStmt exprStmt = (ExprStmt)stmt; 146 Expr expr = exprStmt.getExpr(); 147 if(!expr.isSuperConstructorAccess()) 148 needsInit = false; 149 150 } 151 } 152 153 if(needsEnclosing()) { 154 gen.emitLoadReference(0); 155 gen.emitLoadReference(1); 156 String classname = hostType().constantPoolName(); 157 String desc = enclosing().typeDescriptor(); 158 String name = "this$0"; 159 int index = gen.constantPool().addFieldref(classname, name, desc); 160 gen.emit(Bytecode.PUTFIELD, -2).add2(index); 161 } 162 163 int localIndex = offsetFirstEnclosingVariable(); 164 for(Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) { 165 Variable v = (Variable)iter.next(); 166 gen.emitLoadReference(0); 167 v.type().emitLoadLocal(gen, localIndex); 168 String classname = hostType().constantPoolName(); 169 String desc = v.type().typeDescriptor(); 170 String name = "val$" + v.name(); 171 int index = gen.constantPool().addFieldref(classname, name, desc); 172 gen.emit(Bytecode.PUTFIELD, -1 - v.type().variableSize()).add2(index); 173 localIndex += v.type().variableSize(); 174 } 175 176 if(needsInit) { 177 TypeDecl typeDecl = hostType(); 178 for(int i = 0; i < typeDecl.getNumBodyDecl(); i++) { 179 BodyDecl b = typeDecl.getBodyDecl(i); 180 if(b instanceof FieldDeclaration && b.isBytecodeField() && b.generate()) { 181 FieldDeclaration f = (FieldDeclaration)b; 182 if(!f.isStatic() && f.hasInit()) { 183 gen.emit(Bytecode.ALOAD_0); 184 f.getInit().createBCode(gen); 185 f.getInit().type().emitAssignConvTo(gen, f.type()); // AssignConversion 186 f.emitStoreField(gen, hostType()); 187 } 188 } 189 else if(b instanceof InstanceInitializer) { 190 b.createBCode(gen); 191 } 192 } 193 } 194 gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); 195 getBlock().createBCode(gen); 196 } catch (Error e) { 197 System.err.println(hostType().typeName() + ": " + this); 198 throw e; 199 } 200 } 201 202 public void ASTNode.createBCode(CodeGeneration gen) { 203 for (int i=0; i<getNumChild(); i++) 204 getChild(i).createBCode(gen); 205 } 206 207 public void Literal.createBCode(CodeGeneration gen) { 208 emitPushConstant(gen); 209 } 210 211 protected boolean Expr.needsPush() { 212 ASTNode n = getParent(); 213 while(n instanceof ParExpr) 214 n = n.getParent(); 215 return !(n instanceof ExprStmt); 216 } 217 218 syn boolean ExprStmt.needsPop() = getExpr().needsPop(); 219 syn boolean Expr.needsPop() = true; 220 eq AbstractDot.needsPop() = lastAccess().needsPop(); 221 eq ConstructorAccess.needsPop() = false; 222 223 eq ParExpr.needsPop() = getExpr().needsPop(); 224 //eq AssignExpr.needsPop() = false; // if dest is instance variable that needs accessor 225 eq AssignExpr.needsPop() = getDest().isVarAccessWithAccessor(); 226 eq PreIncExpr.needsPop() = false; 227 eq PostIncExpr.needsPop() = getOperand().isVarAccessWithAccessor(); 228 eq PreDecExpr.needsPop() = false; 229 eq PostDecExpr.needsPop() = getOperand().isVarAccessWithAccessor(); 230 231 syn boolean Expr.isVarAccessWithAccessor() = false; 232 eq ParExpr.isVarAccessWithAccessor() = getExpr().isVarAccessWithAccessor(); 233 eq AbstractDot.isVarAccessWithAccessor() = lastAccess().isVarAccessWithAccessor(); 234 eq VarAccess.isVarAccessWithAccessor() = decl() instanceof FieldDeclaration && 235 decl().isInstanceVariable() && requiresAccessor(); 236 237 public void VariableDeclaration.createBCode(CodeGeneration gen) { 238 super.createBCode(gen); 239 if(hasInit()) { 240 gen.addLocalVariableEntryAtCurrentPC(name(), type().typeDescriptor(), localNum(), variableScopeEndLabel(gen)); 241 getInit().createBCode(gen); 242 getInit().type().emitAssignConvTo(gen, type()); // AssignConversion 243 type().emitStoreLocal(gen, localNum()); 244 } 245 } 246 247 // simple assign expression 248 public void AssignSimpleExpr.createBCode(CodeGeneration gen) { 249 getDest().createAssignSimpleLoadDest(gen); 250 getSource().createBCode(gen); 251 getSource().type().emitAssignConvTo(gen, getDest().type()); // AssignConversion 252 if(needsPush()) { 253 getDest().createPushAssignmentResult(gen); 254 } 255 getDest().emitStore(gen); 256 } 257 258 // compund assign expression 259 public void AssignExpr.createBCode(CodeGeneration gen) { 260 TypeDecl dest = getDest().type(); 261 TypeDecl source = getSource().type(); 262 TypeDecl type; 263 if(dest.isNumericType() && source.isNumericType()) 264 type = dest.binaryNumericPromotion(source); 265 else 266 type = dest; 267 getDest().createAssignLoadDest(gen); 268 dest.emitCastTo(gen, type); 269 getSource().createBCode(gen); 270 source.emitCastTo(gen, type); 271 createAssignOp(gen, type); 272 type.emitCastTo(gen, dest); 273 if(needsPush()) { 274 getDest().createPushAssignmentResult(gen); 275 } 276 getDest().emitStore(gen); 277 } 278 279 // string addition assign expression 280 public void AssignPlusExpr.createBCode(CodeGeneration gen) { 281 TypeDecl dest = getDest().type(); 282 TypeDecl source = getSource().type(); 283 if(dest.isString()) { 284 getDest().createAssignLoadDest(gen); 285 286 // new StringBuffer() 287 TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer"); 288 String classname = stringBuffer.constantPoolName(); 289 String desc; 290 int index; 291 TypeDecl argumentType; 292 stringBuffer.emitNew(gen); // new StringBuffer 293 gen.emitDup(); // dup 294 desc = "()V"; 295 index = gen.constantPool().addMethodref(classname, "<init>", desc); 296 gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer() 297 298 gen.emitSwap(); 299 300 // append 301 argumentType = dest.stringPromotion(); 302 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 303 index = gen.constantPool().addMethodref(classname, "append", desc); 304 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 305 306 getSource().createBCode(gen); 307 308 // typed append 309 argumentType = source.stringPromotion(); 310 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 311 index = gen.constantPool().addMethodref(classname, "append", desc); 312 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 313 314 // toString 315 desc = "()" + type().typeDescriptor(); 316 index = gen.constantPool().addMethodref(classname, "toString", desc); 317 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString 318 319 if(needsPush()) { 320 getDest().createPushAssignmentResult(gen); 321 } 322 getDest().emitStore(gen); 323 } 324 else { 325 super.createBCode(gen); 326 } 327 } 328 329 // shift assign expression 330 public void AssignExpr.emitShiftExpr(CodeGeneration gen) { 331 TypeDecl dest = getDest().type(); 332 TypeDecl source = getSource().type(); 333 TypeDecl type = dest.unaryNumericPromotion(); 334 getDest().createAssignLoadDest(gen); 335 dest.emitCastTo(gen, type); 336 getSource().createBCode(gen); 337 source.emitCastTo(gen, typeInt()); 338 createAssignOp(gen, type); 339 type.emitCastTo(gen, dest); 340 if(needsPush()) { 341 getDest().createPushAssignmentResult(gen); 342 } 343 getDest().emitStore(gen); 344 } 345 public void AssignLShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 346 public void AssignRShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 347 public void AssignURShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 348 349 // load left hand side of destination in a simple assign expression 350 public void Expr.createAssignSimpleLoadDest(CodeGeneration gen) { 351 } 352 public void AbstractDot.createAssignSimpleLoadDest(CodeGeneration gen) { 353 lastAccess().createAssignSimpleLoadDest(gen); 354 } 355 public void VarAccess.createAssignSimpleLoadDest(CodeGeneration gen) { 356 createLoadQualifier(gen); 357 } 358 public void ArrayAccess.createAssignSimpleLoadDest(CodeGeneration gen) { 359 prevExpr().createBCode(gen); 360 getExpr().createBCode(gen); 361 } 362 363 /** 364 * duplicate top value on stack and store below destination element 365 */ 366 public void Expr.createPushAssignmentResult(CodeGeneration gen) { 367 } 368 public void AbstractDot.createPushAssignmentResult(CodeGeneration gen) { 369 lastAccess().createPushAssignmentResult(gen); 370 } 371 public void VarAccess.createPushAssignmentResult(CodeGeneration gen) { 372 if(hostType().needsAccessorFor(decl())) 373 return; 374 if(decl().isInstanceVariable()) 375 type().emitDup_x1(gen); 376 else 377 type().emitDup(gen); 378 } 379 public void ArrayAccess.createPushAssignmentResult(CodeGeneration gen) { 380 type().emitDup_x2(gen); 381 } 382 383 // load left hand side of destination in a compound assign expression 384 public void Expr.createAssignLoadDest(CodeGeneration gen) { 385 } 386 public void AbstractDot.createAssignLoadDest(CodeGeneration gen) { 387 lastAccess().createAssignLoadDest(gen); 388 } 389 public void VarAccess.createAssignLoadDest(CodeGeneration gen) { 390 createLoadQualifier(gen); 391 Variable v = decl(); 392 if(v.isInstanceVariable()) 393 gen.emitDup(); 394 if(v instanceof VariableDeclaration) { 395 VariableDeclaration decl = (VariableDeclaration)v; 396 decl.type().emitLoadLocal(gen, decl.localNum()); 397 } 398 else if(v instanceof ParameterDeclaration) { 399 ParameterDeclaration decl = (ParameterDeclaration)v; 400 decl.type().emitLoadLocal(gen, decl.localNum()); 401 } 402 else if(v instanceof FieldDeclaration) { 403 FieldDeclaration f = (FieldDeclaration)v; 404 if(requiresAccessor()) 405 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 406 else 407 f.emitLoadField(gen, fieldQualifierType()); 408 } 409 } 410 public void ArrayAccess.createAssignLoadDest(CodeGeneration gen) { 411 prevExpr().createBCode(gen); 412 gen.emitDup(); 413 getExpr().createBCode(gen); 414 typeInt().emitDup_x1(gen); 415 gen.emit(type().arrayLoad()); 416 } 417 418 // select the typed operation for a compound assign expression 419 public void AssignExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { 420 throw new Error("Operation createAssignOp is not implemented for " + getClass().getName()); 421 } 422 public void AssignMulExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.mul(gen); } 423 public void AssignDivExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.div(gen); } 424 public void AssignModExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.rem(gen); } 425 public void AssignPlusExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.add(gen); } 426 public void AssignMinusExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.sub(gen); } 427 public void AssignLShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.shl(gen); } 428 public void AssignRShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.shr(gen); } 429 public void AssignURShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.ushr(gen); } 430 public void AssignAndExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitand(gen); } 431 public void AssignXorExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitxor(gen); } 432 public void AssignOrExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.bitor(gen); } 433 434 public void AbstractDot.createBCode(CodeGeneration gen) { 435 lastAccess().createBCode(gen); 436 } 437 438 public void VarAccess.createBCode(CodeGeneration gen) { 439 Variable v = decl(); 440 if(v instanceof VariableDeclaration) { 441 VariableDeclaration decl = (VariableDeclaration)v; 442 if(decl.hostType() == hostType()) 443 decl.type().emitLoadLocal(gen, decl.localNum()); 444 else 445 emitLoadLocalInNestedClass(gen, decl); 446 } 447 else if(v instanceof ParameterDeclaration) { 448 ParameterDeclaration decl = (ParameterDeclaration)v; 449 if(decl.hostType() == hostType()) 450 decl.type().emitLoadLocal(gen, decl.localNum()); 451 else 452 emitLoadLocalInNestedClass(gen, decl); 453 } 454 else if(v instanceof FieldDeclaration) { 455 FieldDeclaration f = (FieldDeclaration)v; 456 createLoadQualifier(gen); 457 if(f.isConstant() && (f.type().isPrimitive() || f.type().isString())) { 458 if(!f.isStatic()) 459 fieldQualifierType().emitPop(gen); 460 f.constant().createBCode(gen); 461 } 462 else if(requiresAccessor()) 463 f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType()); 464 else 465 f.emitLoadField(gen, fieldQualifierType()); 466 } 467 } 468 469 syn boolean TypeDecl.needsAccessorFor(Variable v) { 470 if(!(v instanceof FieldDeclaration)) 471 return false; 472 FieldDeclaration f = (FieldDeclaration)v; 473 if(f.isConstant() && (f.type().isPrimitive() || f.type().isString())) 474 return false; 475 return f.isPrivate() && !hasField(v.name()); 476 } 477 478 inh boolean Access.inExplicitConstructorInvocation(); 479 public void Access.emitLoadLocalInNestedClass(CodeGeneration gen, Variable v) { 480 if(inExplicitConstructorInvocation() && enclosingBodyDecl() instanceof ConstructorDecl) { 481 ConstructorDecl c = (ConstructorDecl)enclosingBodyDecl(); 482 v.type().emitLoadLocal(gen, c.localIndexOfEnclosingVariable(v)); 483 } 484 else { 485 String classname = hostType().constantPoolName(); 486 String desc = v.type().typeDescriptor(); 487 String name = "val$" + v.name(); 488 int index = gen.constantPool().addFieldref(classname, name, desc); 489 gen.emit(Bytecode.ALOAD_0); 490 gen.emit(Bytecode.GETFIELD, v.type().variableSize() - 1).add2(index); 491 } 492 } 493 494 protected void VarAccess.createLoadQualifier(CodeGeneration gen) { 495 Variable v = decl(); 496 if(v instanceof FieldDeclaration) { 497 FieldDeclaration f = (FieldDeclaration)v; 498 if(hasPrevExpr()) { 499 // load explicit qualifier 500 prevExpr().createBCode(gen); 501 // pop qualifier stack element for class variables 502 // this qualifier must be computed to ensure side effects 503 if(!prevExpr().isTypeAccess() && f.isClassVariable()) 504 prevExpr().type().emitPop(gen); 505 } 506 else if(f.isInstanceVariable()) { 507 emitThis(gen, fieldQualifierType()); 508 } 509 } 510 } 511 512 public void MethodAccess.createBCode(CodeGeneration gen) { 513 createLoadQualifier(gen); 514 if(decl().type().isUnknown()) { 515 System.err.println("Could not bind " + this); 516 for (int i = 0; i < getNumArg(); ++i) { 517 System.err.println("Argument " + getArg(i) + " is of type " + getArg(i).type().typeName()); 518 if(getArg(i).varDecl() != null) System.err.println(getArg(i).varDecl() + " in " + getArg(i).varDecl().hostType().typeName()); 519 } 520 if(isQualified()) 521 System.err.println("Qualifier " + qualifier() + " is of type " + qualifier().type().typeName()); 522 throw new Error("Could not bind " + this); 523 } 524 if(decl().getNumParameter() != getNumArg()) { 525 System.out.println(this + " does not have the same number of arguments as " + decl()); 526 } 527 for (int i = 0; i < getNumArg(); ++i) { 528 getArg(i).createBCode(gen); 529 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 530 } 531 /* 532 if(decl().isPrivate() && !hostType().hasMethod(name())) { 533 decl().emitInvokeMethodAccessor(gen, methodQualifierType()); 534 } 535 536 else*/ { 537 if(!decl().isStatic() && isQualified() && prevExpr().isSuperAccess()) { 538 if(!hostType().instanceOf(prevExpr().type())) 539 decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget()); 540 else 541 decl().emitInvokeSpecialMethod(gen, methodQualifierType()); 542 } 543 else 544 decl().emitInvokeMethod(gen, methodQualifierType()); 545 } 546 } 547 548 protected void MethodAccess.createLoadQualifier(CodeGeneration gen) { 549 MethodDecl m = decl(); 550 if(hasPrevExpr()) { 551 // load explicit qualifier 552 prevExpr().createBCode(gen); 553 // pop qualifier stack element for class variables 554 // this qualifier must be computed to ensure side effects 555 if(m.isStatic() && !prevExpr().isTypeAccess()) 556 prevExpr().type().emitPop(gen); 557 } 558 else if(!m.isStatic()) { 559 // load implicit this qualifier 560 emitThis(gen, methodQualifierType()); 561 } 562 } 563 564 public void ArrayAccess.createBCode(CodeGeneration gen) { 565 prevExpr().createBCode(gen); 566 getExpr().createBCode(gen); 567 gen.emit(type().arrayLoad()); 568 } 569 570 public void ThisAccess.createBCode(CodeGeneration gen) { 571 emitThis(gen, decl()); 572 } 573 public void SuperAccess.createBCode(CodeGeneration gen) { 574 emitThis(gen, decl()); 575 } 576 577 // load this where hostType is the target this instance 578 // supporting inner classes and in explicit contructor invocations 579 public void Access.emitThis(CodeGeneration gen, TypeDecl targetDecl) { 580 if(targetDecl == hostType()) 581 gen.emit(Bytecode.ALOAD_0); 582 else { 583 TypeDecl enclosing = hostType(); 584 if(inExplicitConstructorInvocation()) { 585 gen.emit(Bytecode.ALOAD_1); 586 enclosing = enclosing.enclosing(); 587 } 588 else { 589 gen.emit(Bytecode.ALOAD_0); 590 } 591 while(enclosing != targetDecl) { 592 String classname = enclosing.constantPoolName(); 593 enclosing = enclosing.enclosingType(); 594 String desc = enclosing.typeDescriptor(); 595 int index = gen.constantPool().addFieldref(classname, "this$0", desc); 596 gen.emit(Bytecode.GETFIELD, 0).add2(index); 597 } 598 } 599 } 600 601 602 public void ConstructorAccess.createBCode(CodeGeneration gen) { 603 ConstructorDecl c = decl(); 604 int index = 0; 605 // this 606 gen.emitLoadReference(index++); 607 // this$0 608 if(c.needsEnclosing()) 609 gen.emitLoadReference(index++); 610 if(c.needsSuperEnclosing()) 611 gen.emitLoadReference(index++); 612 613 // args 614 for (int i = 0; i < getNumArg(); ++i) { 615 getArg(i).createBCode(gen); 616 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 617 } 618 if(decl().isPrivate() && decl().hostType() != hostType()) { 619 gen.emit(Bytecode.ACONST_NULL); 620 decl().createAccessor().emitInvokeConstructor(gen); 621 } 622 else { 623 decl().emitInvokeConstructor(gen); 624 } 625 } 626 627 public void SuperConstructorAccess.createBCode(CodeGeneration gen) { 628 ConstructorDecl c = decl(); 629 630 // this 631 gen.emit(Bytecode.ALOAD_0); 632 633 if(c.needsEnclosing()) { 634 if(hasPrevExpr() && !prevExpr().isTypeAccess()) { 635 prevExpr().createBCode(gen); 636 gen.emitDup(); 637 int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;"); 638 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); 639 gen.emitPop(); 640 } 641 else { 642 if(hostType().needsSuperEnclosing()) { 643 if(hostType().needsEnclosing()) 644 gen.emit(Bytecode.ALOAD_2); 645 else 646 gen.emit(Bytecode.ALOAD_1); 647 } 648 else { 649 emitThis(gen, superConstructorQualifier(c.hostType().enclosingType())); 650 } 651 } 652 } 653 654 // args 655 for (int i = 0; i < getNumArg(); ++i) { 656 getArg(i).createBCode(gen); 657 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 658 } 659 if(decl().isPrivate() && decl().hostType() != hostType()) { 660 gen.emit(Bytecode.ACONST_NULL); 661 decl().createAccessor().emitInvokeConstructor(gen); 662 } 663 else { 664 decl().emitInvokeConstructor(gen); 665 } 666 } 667 668 // 15.9.2 669 private void ClassInstanceExpr.emitLocalEnclosing(CodeGeneration gen, TypeDecl localClass) { 670 if(!localClass.inStaticContext()) { 671 emitThis(gen, localClass.enclosingType()); 672 } 673 } 674 private void ClassInstanceExpr.emitInnerMemberEnclosing(CodeGeneration gen, TypeDecl innerClass) { 675 if(hasPrevExpr()) { 676 prevExpr().createBCode(gen); 677 gen.emitDup(); 678 int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;"); 679 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); 680 gen.emitPop(); 681 } 682 else { 683 TypeDecl enclosing = hostType(); 684 while(enclosing != null && !enclosing.hasType(innerClass.name())) 685 enclosing = enclosing.enclosingType(); 686 if(enclosing == null) 687 throw new Error(errorPrefix() + "Could not find enclosing for " + this); 688 else 689 emitThis(gen, enclosing); 690 } 691 } 692 public void ClassInstanceExpr.createBCode(CodeGeneration gen) { 693 type().emitNew(gen); 694 type().emitDup(gen); 695 696 // 15.9.2 first part 697 if(type().isAnonymous()) { 698 if(type().isAnonymousInNonStaticContext()) { 699 if(type().inExplicitConstructorInvocation()) 700 gen.emit(Bytecode.ALOAD_1); 701 else 702 gen.emit(Bytecode.ALOAD_0); 703 } 704 // 15.9.2 second part 705 ClassDecl C = (ClassDecl)type(); 706 TypeDecl S = C.superclass(); 707 if(S.isLocalClass()) { 708 if(!type().inStaticContext()) 709 emitLocalEnclosing(gen, S); 710 } 711 else if(S.isInnerType()) { 712 emitInnerMemberEnclosing(gen, S); 713 } 714 } 715 else if(type().isLocalClass()) { 716 if(!type().inStaticContext()) 717 emitLocalEnclosing(gen, type()); 718 } 719 else if(type().isInnerType()) { 720 emitInnerMemberEnclosing(gen, type()); 721 } 722 /* 723 // 15.9.2 first part 724 if(type().isAnonymous()) { 725 if(type().isAnonymousInNonStaticContext()) { 726 if(type().inExplicitConstructorInvocation()) 727 gen.emit(Bytecode.ALOAD_1); 728 else 729 gen.emit(Bytecode.ALOAD_0); 730 } 731 if(type().needsSuperEnclosing()) { 732 // 15.9.2 second part 733 ClassDecl C = (ClassDecl)type(); 734 TypeDecl S = C.superclass(); 735 if(S.isLocalClass()) { 736 emitLocalEnclosing(gen, S); 737 } 738 else if(S.isInnerType()) { 739 emitInnerMemberEnclosing(gen, S); 740 } 741 } 742 } 743 else if(type().isLocalClass()) { 744 emitLocalEnclosing(gen, type()); 745 } 746 else if(type().isInnerType()) { 747 emitInnerMemberEnclosing(gen, type()); 748 } 749 */ 750 751 for (int i = 0; i < getNumArg(); ++i) { 752 getArg(i).createBCode(gen); 753 getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion 754 } 755 756 if(decl().isPrivate() && type() != hostType()) { 757 gen.emit(Bytecode.ACONST_NULL); 758 decl().createAccessor().emitInvokeConstructor(gen); 759 } 760 else { 761 decl().emitInvokeConstructor(gen); 762 } 763 } 764 765 public void ArrayCreationExpr.createBCode(CodeGeneration gen) { 766 if(hasArrayInit()){ 767 getArrayInit().createBCode(gen); 768 } 769 else { 770 getTypeAccess().createBCode(gen); // push array sizes 771 if(type().componentType().isPrimitive()) { 772 gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor()); 773 } 774 else { 775 if(numArrays() == 1) { 776 String n = type().componentType().arrayTypeDescriptor(); 777 int index = gen.constantPool().addClass(n); 778 gen.emit(Bytecode.ANEWARRAY).add2(index); 779 } 780 else { 781 String n = type().arrayTypeDescriptor(); 782 int index = gen.constantPool().addClass(n); 783 gen.emit(Bytecode.MULTIANEWARRAY, 1 - numArrays()).add2(index).add(numArrays()); 784 } 785 } 786 } 787 } 788 789 public void ArrayInit.createBCode(CodeGeneration gen) { 790 IntegerLiteral.push(gen, getNumInit()); 791 if(type().componentType().isPrimitive()) { 792 gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor()); 793 } 794 else { 795 String n = type().componentType().arrayTypeDescriptor(); 796 int index = gen.constantPool().addClass(n); 797 gen.emit(Bytecode.ANEWARRAY).add2(index); 798 } 799 for(int i = 0; i < getNumInit(); i++) { 800 gen.emitDup(); 801 IntegerLiteral.push(gen, i); 802 getInit(i).createBCode(gen); 803 if(getInit(i) instanceof ArrayInit) 804 gen.emit(Bytecode.AASTORE); 805 else { 806 getInit(i).type().emitAssignConvTo(gen, expectedType()); // AssignConversion 807 gen.emit(expectedType().arrayStore()); 808 } 809 } 810 } 811 812 public void ArrayTypeAccess.createBCode(CodeGeneration gen) { 813 getAccess().createBCode(gen); 814 } 815 public void ArrayTypeWithSizeAccess.createBCode(CodeGeneration gen) { 816 getAccess().createBCode(gen); 817 getExpr().createBCode(gen); 818 } 819 820 syn String TypeDecl.arrayTypeDescriptor() { throw new Error("Operation not supported"); } 821 eq ArrayDecl.arrayTypeDescriptor() = typeDescriptor(); 822 eq ClassDecl.arrayTypeDescriptor() = constantPoolName(); 823 eq InterfaceDecl.arrayTypeDescriptor() = constantPoolName(); 824 825 syn int TypeDecl.arrayPrimitiveTypeDescriptor() { error(); return -1; } 826 eq BooleanType.arrayPrimitiveTypeDescriptor() = 4; // T_BOOLEAN 827 eq CharType.arrayPrimitiveTypeDescriptor() = 5; // T_CHAR 828 eq FloatType.arrayPrimitiveTypeDescriptor() = 6; // T_FLOAT 829 eq DoubleType.arrayPrimitiveTypeDescriptor() = 7; // T_DOUBLE 830 eq ByteType.arrayPrimitiveTypeDescriptor() = 8; // T_BYTE 831 eq ShortType.arrayPrimitiveTypeDescriptor() = 9; // T_SHORT 832 eq IntType.arrayPrimitiveTypeDescriptor() = 10; // T_INT 833 eq LongType.arrayPrimitiveTypeDescriptor() = 11; // T_LONG 834 835 public void Unary.createBCode(CodeGeneration gen) { 836 super.createBCode(gen); 837 emitOperation(gen); 838 } 839 840 public void CastExpr.createBCode(CodeGeneration gen) { 841 getExpr().createBCode(gen); 842 getExpr().type().emitCastTo(gen, type()); 843 } 844 845 // TODO: consider using IINC or WIDE,IINC 846 847 public void Unary.emitPostfix(CodeGeneration gen, int constant) { 848 Expr operand = getOperand(); 849 while(operand instanceof ParExpr) 850 operand = ((ParExpr)operand).getExpr(); 851 Access access = ((Access)operand).lastAccess(); 852 access.createAssignLoadDest(gen); 853 if(needsPush()) 854 access.createPushAssignmentResult(gen); 855 TypeDecl type = access.type().binaryNumericPromotion(typeInt()); 856 type.emitPushConstant(gen, constant); 857 type.add(gen); 858 type.emitCastTo(gen, access.type()); 859 access.emitStore(gen); 860 } 861 public void PostIncExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, 1); } 862 public void PostDecExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, -1); } 863 864 public void Unary.emitPrefix(CodeGeneration gen, int constant) { 865 Expr operand = getOperand(); 866 while(operand instanceof ParExpr) 867 operand = ((ParExpr)operand).getExpr(); 868 Access access = ((Access)operand).lastAccess(); 869 access.createAssignLoadDest(gen); 870 TypeDecl type = access.type().binaryNumericPromotion(typeInt()); 871 type.emitPushConstant(gen, constant); 872 type.add(gen); 873 type.emitCastTo(gen, access.type()); 874 if(needsPush()) 875 access.createPushAssignmentResult(gen); 876 access.emitStore(gen); 877 } 878 public void PreIncExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, 1); } 879 public void PreDecExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, -1); } 880 881 public void Binary.createBCode(CodeGeneration gen) { 882 getLeftOperand().createBCode(gen); 883 getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 884 getRightOperand().createBCode(gen); 885 getRightOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 886 emitOperation(gen); 887 } 888 889 public void Binary.emitShiftExpr(CodeGeneration gen) { 890 getLeftOperand().createBCode(gen); 891 getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion 892 getRightOperand().createBCode(gen); 893 getRightOperand().type().emitCastTo(gen, typeInt()); 894 emitOperation(gen); 895 } 896 public void LShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 897 public void RShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 898 public void URShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); } 899 900 public void AddExpr.createBCode(CodeGeneration gen) { 901 if(!type().isString()) 902 super.createBCode(gen); 903 else if(isConstant()) { 904 StringLiteral.push(gen, constant().stringValue()); 905 } 906 else { 907 TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer"); 908 String classname = stringBuffer.constantPoolName(); 909 String desc; 910 int index; 911 TypeDecl argumentType; 912 if(firstStringAddPart()) { 913 stringBuffer.emitNew(gen); // new StringBuffer 914 gen.emitDup(); // dup 915 desc = "()V"; 916 index = gen.constantPool().addMethodref(classname, "<init>", desc); 917 gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer() 918 getLeftOperand().createBCode(gen); // left 919 argumentType = getLeftOperand().type().stringPromotion(); 920 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 921 index = gen.constantPool().addMethodref(classname, "append", desc); 922 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 923 } 924 else { 925 getLeftOperand().createBCode(gen); 926 } 927 getRightOperand().createBCode(gen); // right 928 argumentType = getRightOperand().type().stringPromotion(); 929 desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); 930 index = gen.constantPool().addMethodref(classname, "append", desc); 931 gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append 932 if(lastStringAddPart()) { 933 desc = "()" + type().typeDescriptor(); 934 index = gen.constantPool().addMethodref(classname, "toString", desc); 935 gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString 936 } 937 } 938 } 939 940 // branch to this label if the expression is false 941 syn lazy int Expr.false_label() = getParent().definesLabel() ? condition_false_label() : hostType().constantPool().newLabel(); 942 // branch to this label if the expression is true 943 syn lazy int Expr.true_label() = getParent().definesLabel() ? condition_true_label() : hostType().constantPool().newLabel(); 944 945 // these nodes defines labels for their children 946 syn boolean ASTNode.definesLabel() = false; 947 eq Opt.definesLabel() = getParent().definesLabel(); 948 eq List.definesLabel() = getParent().definesLabel(); 949 eq AbstractDot.definesLabel() = getParent().definesLabel(); 950 eq ParExpr.definesLabel() = getParent().definesLabel(); 951 952 eq LogNotExpr.definesLabel() = true; 953 eq ConditionalExpr.definesLabel() = true; 954 eq RelationalExpr.definesLabel() = false; 955 956 eq LogicalExpr.definesLabel() = true; 957 eq IfStmt.definesLabel() = true; 958 eq WhileStmt.definesLabel() = true; 959 eq DoStmt.definesLabel() = true; 960 eq ForStmt.definesLabel() = true; 961 962 // provide labels for these control statement conditions 963 eq IfStmt.getCondition().condition_false_label() = else_branch_label(); 964 eq IfStmt.getCondition().condition_true_label() = then_branch_label(); 965 eq WhileStmt.getCondition().condition_false_label() = end_label(); 966 eq WhileStmt.getCondition().condition_true_label() = stmt_label(); 967 eq DoStmt.getCondition().condition_false_label() = end_label(); 968 eq DoStmt.getCondition().condition_true_label() = begin_label(); 969 eq ForStmt.getCondition().condition_false_label() = end_label(); 970 eq ForStmt.getCondition().condition_true_label() = begin_label(); 971 972 // propagate labels downwards for complex boolean expressions 973 inh int Expr.condition_false_label(); 974 eq Program.getChild(int i).condition_false_label() { 975 throw new Error("condition_false_label not implemented"); 976 } 977 inh int Expr.condition_true_label(); 978 eq Program.getChild(int i).condition_true_label() { 979 throw new Error("condition_true_label not implemented"); 980 } 981 982 eq LogNotExpr.getOperand().condition_false_label() = true_label(); 983 eq LogNotExpr.getOperand().condition_true_label() = false_label(); 984 985 eq ConditionalExpr.getCondition().condition_false_label() = else_branch_label(); 986 eq ConditionalExpr.getCondition().condition_true_label() = then_branch_label(); 987 eq ConditionalExpr.getTrueExpr().condition_false_label() = false_label(); 988 eq ConditionalExpr.getTrueExpr().condition_true_label() = true_label(); 989 eq ConditionalExpr.getFalseExpr().condition_false_label() = false_label(); 990 eq ConditionalExpr.getFalseExpr().condition_true_label() = true_label(); 991 992 eq RelationalExpr.getLeftOperand().condition_false_label() = false_label(); 993 eq RelationalExpr.getLeftOperand().condition_true_label() = true_label(); 994 eq RelationalExpr.getRightOperand().condition_false_label() = false_label(); 995 eq RelationalExpr.getRightOperand().condition_true_label() = true_label(); 996 997 eq AndLogicalExpr.getLeftOperand().condition_false_label() = false_label(); 998 eq AndLogicalExpr.getLeftOperand().condition_true_label() = next_test_label(); 999 eq AndLogicalExpr.getRightOperand().condition_false_label() = false_label(); 1000 eq AndLogicalExpr.getRightOperand().condition_true_label() = true_label(); 1001 1002 eq OrLogicalExpr.getLeftOperand().condition_false_label() = next_test_label(); 1003 eq OrLogicalExpr.getLeftOperand().condition_true_label() = true_label(); 1004 eq OrLogicalExpr.getRightOperand().condition_false_label() = false_label(); 1005 eq OrLogicalExpr.getRightOperand().condition_true_label() = true_label(); 1006 1007 syn boolean Expr.canBeTrue() = !isFalse(); 1008 eq ParExpr.canBeTrue() = getExpr().canBeTrue(); 1009 eq AbstractDot.canBeTrue() = lastAccess().canBeTrue(); 1010 eq OrLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() || getRightOperand().canBeTrue(); 1011 eq AndLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() && getRightOperand().canBeTrue(); 1012 eq ConditionalExpr.canBeTrue() = type().isBoolean() && (getTrueExpr().canBeTrue() && getFalseExpr().canBeTrue() 1013 || getCondition().isTrue() && getTrueExpr().canBeTrue() 1014 || getCondition().isFalse() && getFalseExpr().canBeTrue()); 1015 eq LogNotExpr.canBeTrue() = getOperand().canBeFalse(); 1016 1017 syn boolean Expr.canBeFalse() = !isTrue(); 1018 eq ParExpr.canBeFalse() = getExpr().canBeFalse(); 1019 eq AbstractDot.canBeFalse() = lastAccess().canBeFalse(); 1020 eq OrLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() && getRightOperand().canBeFalse(); 1021 eq AndLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() || getRightOperand().canBeFalse(); 1022 eq ConditionalExpr.canBeFalse() = type().isBoolean() && (getTrueExpr().canBeFalse() && getFalseExpr().canBeFalse() 1023 || getCondition().isTrue() && getTrueExpr().canBeFalse() 1024 || getCondition().isFalse() && getFalseExpr().canBeFalse()); 1025 eq LogNotExpr.canBeFalse() = getOperand().canBeTrue(); 1026 1027 public void RelationalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1028 public void LogNotExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1029 public void LogicalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); } 1030 protected void Expr.emitBooleanCondition(CodeGeneration gen) { 1031 emitEvalBranch(gen); 1032 int end_label = hostType().constantPool().newLabel(); 1033 gen.addLabel(false_label()); 1034 BooleanLiteral.push(gen, false); 1035 gen.emitGoto(end_label); 1036 gen.changeStackDepth(-1); // discard false from stack depth computation 1037 gen.addLabel(true_label()); 1038 BooleanLiteral.push(gen, true); 1039 gen.addLabel(end_label); 1040 } 1041 1042 public void ConditionalExpr.createBCode(CodeGeneration gen) { 1043 if(type().isBoolean()) 1044 emitBooleanCondition(gen); 1045 else { 1046 int endBranch = hostType().constantPool().newLabel(); 1047 getCondition().emitEvalBranch(gen); 1048 if(getCondition().canBeTrue()) { 1049 gen.addLabel(then_branch_label()); 1050 getTrueExpr().createBCode(gen); 1051 getTrueExpr().type().emitCastTo(gen, type()); 1052 if(getCondition().canBeFalse()) { 1053 gen.changeStackDepth(-type().variableSize()); 1054 gen.emitGoto(endBranch); 1055 } 1056 } 1057 if(getCondition().canBeFalse()) { 1058 gen.addLabel(else_branch_label()); 1059 getFalseExpr().createBCode(gen); 1060 getFalseExpr().type().emitCastTo(gen, type()); 1061 } 1062 gen.addLabel(endBranch); 1063 } 1064 } 1065 syn lazy int ConditionalExpr.else_branch_label() = hostType().constantPool().newLabel(); 1066 syn lazy int ConditionalExpr.then_branch_label() = hostType().constantPool().newLabel(); 1067 1068 public void Expr.emitEvalBranch(CodeGeneration gen) { 1069 if(isTrue()) 1070 gen.emitGoto(true_label()); 1071 else if(isFalse()) 1072 gen.emitGoto(false_label()); 1073 else { 1074 createBCode(gen); 1075 gen.emitCompare(Bytecode.IFNE, true_label()); 1076 gen.emitGoto(false_label()); 1077 //gen.emitCompare(Bytecode.IFEQ, false_label()); 1078 //gen.emitGoto(true_label()); 1079 } 1080 } 1081 1082 public void ParExpr.emitEvalBranch(CodeGeneration gen) { getExpr().emitEvalBranch(gen); } 1083 public void AbstractDot.emitEvalBranch(CodeGeneration gen) { lastAccess().emitEvalBranch(gen); } 1084 public void LogNotExpr.emitEvalBranch(CodeGeneration gen) { getOperand().emitEvalBranch(gen); } 1085 1086 public void AndLogicalExpr.emitEvalBranch(CodeGeneration gen) { 1087 getLeftOperand().emitEvalBranch(gen); 1088 gen.addLabel(next_test_label()); 1089 if(getLeftOperand().canBeTrue()) { 1090 getRightOperand().emitEvalBranch(gen); 1091 if(getRightOperand().canBeTrue()) 1092 gen.emitGoto(true_label()); 1093 } 1094 } 1095 syn lazy int AndLogicalExpr.next_test_label() = hostType().constantPool().newLabel(); 1096 1097 public void OrLogicalExpr.emitEvalBranch(CodeGeneration gen) { 1098 getLeftOperand().emitEvalBranch(gen); 1099 gen.addLabel(next_test_label()); 1100 if(getLeftOperand().canBeFalse()) { 1101 getRightOperand().emitEvalBranch(gen); 1102 if(getRightOperand().canBeFalse()) 1103 gen.emitGoto(false_label()); 1104 } 1105 } 1106 syn lazy int OrLogicalExpr.next_test_label() = hostType().constantPool().newLabel(); 1107 1108 public void ConditionalExpr.emitEvalBranch(CodeGeneration gen) { 1109 int endBranch = hostType().constantPool().newLabel(); 1110 getCondition().emitEvalBranch(gen); 1111 gen.addLabel(then_branch_label()); 1112 if(getCondition().canBeTrue()) { 1113 getTrueExpr().emitEvalBranch(gen); 1114 gen.emitGoto(true_label()); 1115 } 1116 gen.addLabel(else_branch_label()); 1117 if(getCondition().canBeFalse()) { 1118 getFalseExpr().emitEvalBranch(gen); 1119 gen.emitGoto(true_label()); 1120 } 1121 } 1122 1123 public void RelationalExpr.emitEvalBranch(CodeGeneration gen) { 1124 if(isTrue()) 1125 gen.emitGoto(true_label()); 1126 else if(isFalse()) 1127 gen.emitGoto(false_label()); 1128 else { 1129 TypeDecl type = getLeftOperand().type(); 1130 if(type.isNumericType()) { 1131 type = binaryNumericPromotedType(); 1132 getLeftOperand().createBCode(gen); 1133 getLeftOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1134 getRightOperand().createBCode(gen); 1135 getRightOperand().type().emitCastTo(gen, type); // Binary numeric promotion 1136 } 1137 else { 1138 getLeftOperand().createBCode(gen); 1139 getRightOperand().createBCode(gen); 1140 } 1141 compareBranch(gen, true_label(), type); 1142 gen.emitGoto(false_label()); 1143 // compareNotBranch does not work for float comparison with NaN 1144 //compareNotBranch(gen, false_label(), type); 1145 //gen.emitGoto(true_label()); 1146 } 1147 } 1148 1149 public void RelationalExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { 1150 throw new Error("compareBranch not supported for " + getClass().getName()); 1151 } 1152 public void LTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); } 1153 public void LEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); } 1154 public void GEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); } 1155 public void GTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); } 1156 public void EQExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); } 1157 public void NEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); } 1158 1159 public void RelationalExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { 1160 throw new Error("compareBranch not supported for " + getClass().getName()); 1161 } 1162 public void LTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); } 1163 public void LEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); } 1164 public void GEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); } 1165 public void GTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); } 1166 public void EQExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); } 1167 public void NEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); } 1168 1169 public void InstanceOfExpr.createBCode(CodeGeneration gen) { 1170 getExpr().createBCode(gen); 1171 gen.emitInstanceof(getTypeAccess().type()); 1172 } 1173 1174 public void Stmt.createBCode(CodeGeneration gen) { 1175 gen.addLineNumberEntryAtCurrentPC(this); 1176 } 1177 1178 public void Block.createBCode(CodeGeneration gen) { 1179 //super.createBCode(gen); 1180 for(int i = 0; i < getNumStmt(); i++) { 1181 try { 1182 getStmt(i).createBCode(gen); 1183 } catch (Exception e) { 1184 e.printStackTrace(); 1185 throw new Error("Error generating code for " + errorPrefix() + " " + getStmt(i)); 1186 } 1187 } 1188 gen.addVariableScopeLabel(variableScopeEndLabel(gen)); 1189 } 1190 1191 public void EmptyStmt.createBCode(CodeGeneration gen) { 1192 super.createBCode(gen); 1193 } 1194 1195 syn lazy int LabeledStmt.label() = hostType().constantPool().newLabel(); 1196 syn lazy int LabeledStmt.end_label() = hostType().constantPool().newLabel(); 1197 public void LabeledStmt.createBCode(CodeGeneration gen) { 1198 super.createBCode(gen); 1199 gen.addLabel(label()); 1200 getStmt().createBCode(gen); 1201 gen.addLabel(end_label()); 1202 } 1203 1204 public void ExprStmt.createBCode(CodeGeneration gen) { 1205 super.createBCode(gen); 1206 getExpr().createBCode(gen); 1207 if(needsPop()) 1208 getExpr().type().emitPop(gen); 1209 } 1210 1211 syn lazy DefaultCase SwitchStmt.defaultCase() { 1212 for(int i= 0; i < getBlock().getNumStmt(); i++) { 1213 if(getBlock().getStmt(i) instanceof DefaultCase) 1214 return (DefaultCase)getBlock().getStmt(i); 1215 } 1216 return null; 1217 } 1218 1219 syn lazy int SwitchStmt.end_label() = hostType().constantPool().newLabel(); 1220 1221 public void SwitchStmt.createBCode(CodeGeneration gen) { 1222 super.createBCode(gen); 1223 int cond_label = hostType().constantPool().newLabel(); 1224 int switch_label = hostType().constantPool().newLabel(); 1225 1226 gen.emitGoto(cond_label); 1227 getBlock().createBCode(gen); 1228 if(canCompleteNormally()) 1229 gen.emitGoto(end_label()); 1230 gen.addLabel(cond_label); 1231 getExpr().createBCode(gen); 1232 1233 TreeMap map = new TreeMap(); 1234 for(int i = 0; i < getBlock().getNumStmt(); i++) { 1235 if(getBlock().getStmt(i) instanceof ConstCase) { 1236 ConstCase ca = (ConstCase)getBlock().getStmt(i); 1237 map.put(new Integer(ca.getValue().constant().intValue()), ca); 1238 } 1239 } 1240 1241 long low = map.isEmpty() ? 0 : ((Integer)map.firstKey()).intValue(); 1242 long high = map.isEmpty() ? 0 : ((Integer)map.lastKey()).intValue(); 1243 1244 long tableSwitchSize = 8L + (high - low + 1L) * 4L; 1245 long lookupSwitchSize = 4L + map.size() * 8L; 1246 1247 gen.addLabel(switch_label); 1248 if(tableSwitchSize < lookupSwitchSize) { 1249 gen.emit(Bytecode.TABLESWITCH); 1250 int pad = emitPad(gen); 1251 int defaultOffset = defaultOffset(gen, switch_label); 1252 if(defaultOffset == 0) { 1253 defaultOffset = 1 + pad + 4 + 4 + 4 + 4 * (int)(high - low + 1); 1254 } 1255 gen.add4(defaultOffset); 1256 gen.add4((int)low); 1257 gen.add4((int)high); 1258 for(long i = low; i <= high; i++) { 1259 ConstCase ca = (ConstCase)map.get(new Integer((int)i)); 1260 if(ca != null) { 1261 int offset = gen.addressOf(ca.label(gen)) 1262 - gen.addressOf(switch_label); 1263 gen.add4(offset); 1264 } 1265 else { 1266 gen.add4(defaultOffset); 1267 } 1268 } 1269 } 1270 else { 1271 gen.emit(Bytecode.LOOKUPSWITCH); 1272 int pad = emitPad(gen); 1273 int defaultOffset = defaultOffset(gen, switch_label); 1274 if(defaultOffset == 0) { 1275 defaultOffset = 1 + pad + 4 + 4 + 8 * numCase(); 1276 } 1277 gen.add4(defaultOffset); 1278 gen.add4(map.size()); 1279 for(Iterator iter = map.values().iterator(); iter.hasNext(); ) { 1280 ConstCase ca = (ConstCase)iter.next(); 1281 gen.add4(ca.getValue().constant().intValue()); 1282 int offset = gen.addressOf(ca.label(gen)) 1283 - gen.addressOf(switch_label); 1284 gen.add4(offset); 1285 } 1286 } 1287 gen.addLabel(end_label()); 1288 } 1289 1290 syn int SwitchStmt.numCase() { 1291 int result = 0; 1292 for(int i = 0; i < getBlock().getNumStmt(); i++) 1293 if(getBlock().getStmt(i) instanceof Case) 1294 result++; 1295 return result; 1296 } 1297 1298 private int SwitchStmt.emitPad(CodeGeneration gen) { 1299 int pad = (4 - (gen.pos() % 4)) % 4; 1300 for(int i = 0; i < pad; i++) 1301 gen.emit(Bytecode.NOP); 1302 if(gen.pos() % 4 != 0) 1303 throw new Error("Switch not at 4-byte boundary:" + gen.pos()); 1304 return pad; 1305 } 1306 private int SwitchStmt.defaultOffset(CodeGeneration gen, int switch_label) { 1307 boolean hasDefault = defaultCase() != null; 1308 if(hasDefault) { 1309 int offset = gen.addressOf(defaultCase().label(gen)) 1310 - gen.addressOf(switch_label); 1311 return offset; 1312 } 1313 return 0; 1314 } 1315 1316 syn lazy int Case.label(CodeGeneration gen) = hostType().constantPool().newLabel(); 1317 1318 public void Case.createBCode(CodeGeneration gen) { 1319 gen.addLabel(label(gen)); 1320 } 1321 1322 syn lazy int IfStmt.else_branch_label() = hostType().constantPool().newLabel(); 1323 syn lazy int IfStmt.then_branch_label() = hostType().constantPool().newLabel(); 1324 public void IfStmt.createBCode(CodeGeneration gen) { 1325 super.createBCode(gen); 1326 int elseBranch = else_branch_label(); 1327 int thenBranch = then_branch_label(); 1328 int endBranch = hostType().constantPool().newLabel(); 1329 getCondition().emitEvalBranch(gen); 1330 gen.addLabel(thenBranch); 1331 //if(getCondition().canBeTrue()) { 1332 getThen().createBCode(gen); 1333 if(getThen().canCompleteNormally() && hasElse() /*&& getCondition().canBeFalse()*/) 1334 gen.emitGoto(endBranch); 1335 //} 1336 gen.addLabel(elseBranch); 1337 if(hasElse() /*&& getCondition().canBeFalse()*/) 1338 getElse().createBCode(gen); 1339 gen.addLabel(endBranch); 1340 } 1341 1342 syn lazy int WhileStmt.cond_label() = hostType().constantPool().newLabel(); 1343 syn lazy int WhileStmt.end_label() = hostType().constantPool().newLabel(); 1344 syn lazy int WhileStmt.stmt_label() = hostType().constantPool().newLabel(); 1345 1346 public void WhileStmt.createBCode(CodeGeneration gen) { 1347 super.createBCode(gen); 1348 gen.addLabel(cond_label()); 1349 getCondition().emitEvalBranch(gen); 1350 gen.addLabel(stmt_label()); 1351 if(getCondition().canBeTrue()) { 1352 getStmt().createBCode(gen); 1353 if(getStmt().canCompleteNormally()) 1354 gen.emitGoto(cond_label()); 1355 } 1356 gen.addLabel(end_label()); 1357 } 1358 1359 syn lazy int DoStmt.begin_label() = hostType().constantPool().newLabel(); 1360 syn lazy int DoStmt.cond_label() = hostType().constantPool().newLabel(); 1361 syn lazy int DoStmt.end_label() = hostType().constantPool().newLabel(); 1362 1363 public void DoStmt.createBCode(CodeGeneration gen) { 1364 super.createBCode(gen); 1365 gen.addLabel(begin_label()); 1366 getStmt().createBCode(gen); 1367 gen.addLabel(cond_label()); 1368 getCondition().emitEvalBranch(gen); 1369 gen.addLabel(end_label()); 1370 } 1371 1372 syn lazy int ForStmt.cond_label() = hostType().constantPool().newLabel(); 1373 syn lazy int ForStmt.begin_label() = hostType().constantPool().newLabel(); 1374 syn lazy int ForStmt.update_label() = hostType().constantPool().newLabel(); 1375 syn lazy int ForStmt.end_label() = hostType().constantPool().newLabel(); 1376 1377 public void ForStmt.createBCode(CodeGeneration gen) { 1378 super.createBCode(gen); 1379 for (int i=0; i<getNumInitStmt(); i++) { 1380 getInitStmt(i).createBCode(gen); 1381 } 1382 gen.addLabel(cond_label()); 1383 getCondition().emitEvalBranch(gen); 1384 if(getCondition().canBeTrue()) { 1385 gen.addLabel(begin_label()); 1386 getStmt().createBCode(gen); 1387 gen.addLabel(update_label()); 1388 for (int i=0; i<getNumUpdateStmt(); i++) 1389 getUpdateStmt(i).createBCode(gen); 1390 gen.emitGoto(cond_label()); 1391 } 1392 if(canCompleteNormally()) { 1393 gen.addLabel(end_label()); 1394 } 1395 gen.addVariableScopeLabel(variableScopeEndLabel(gen)); 1396 } 1397 1398 syn int Stmt.break_label() { 1399 throw new UnsupportedOperationException("Can not break at this statement of type " + getClass().getName()); 1400 } 1401 eq ForStmt.break_label() = end_label(); 1402 eq WhileStmt.break_label() = end_label(); 1403 eq DoStmt.break_label() = end_label(); 1404 eq LabeledStmt.break_label() = end_label(); 1405 eq SwitchStmt.break_label() = end_label(); 1406 eq TryStmt.break_label() = label_finally(); 1407 1408 public void BreakStmt.createBCode(CodeGeneration gen) { 1409 super.createBCode(gen); 1410 for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) { 1411 FinallyHost stmt = (FinallyHost)iter.next(); 1412 gen.emitJsr(stmt.label_finally_block()); 1413 } 1414 gen.emitGoto(targetStmt().break_label()); 1415 } 1416 1417 syn int Stmt.continue_label() { 1418 throw new UnsupportedOperationException("Can not continue at this statement"); 1419 } 1420 eq ForStmt.continue_label() = update_label(); 1421 eq WhileStmt.continue_label() = cond_label(); 1422 eq DoStmt.continue_label() = cond_label(); 1423 eq LabeledStmt.continue_label() = getStmt().continue_label(); 1424 eq TryStmt.continue_label() = label_finally(); 1425 1426 public void ContinueStmt.createBCode(CodeGeneration gen) { 1427 super.createBCode(gen); 1428 for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) { 1429 FinallyHost stmt = (FinallyHost)iter.next(); 1430 gen.emitJsr(stmt.label_finally_block()); 1431 } 1432 gen.emitGoto(targetStmt().continue_label()); 1433 } 1434 1435 public void ReturnStmt.createBCode(CodeGeneration gen) { 1436 super.createBCode(gen); 1437 if(hasResult()) { 1438 TypeDecl type = null; 1439 BodyDecl b = enclosingBodyDecl(); 1440 if(b instanceof MethodDecl) { 1441 type = ((MethodDecl)b).type(); 1442 } 1443 else { 1444 throw new Error("Can not create code that returns value within non method"); 1445 } 1446 getResult().createBCode(gen); 1447 getResult().type().emitCastTo(gen, type); 1448 if(!finallyList().isEmpty()) { 1449 type.emitStoreLocal(gen, resultSaveLocalNum()); 1450 } 1451 for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) { 1452 FinallyHost stmt = (FinallyHost)iter.next(); 1453 gen.emitJsr(stmt.label_finally_block()); 1454 } 1455 if(!finallyList().isEmpty()) { 1456 type.emitLoadLocal(gen, resultSaveLocalNum()); 1457 } 1458 type.emitReturn(gen); 1459 } 1460 else { 1461 for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) { 1462 FinallyHost stmt = (FinallyHost)iter.next(); 1463 gen.emitJsr(stmt.label_finally_block()); 1464 } 1465 gen.emitReturn(); 1466 } 1467 } 1468 1469 public void ThrowStmt.createBCode(CodeGeneration gen) { 1470 super.createBCode(gen); 1471 getExpr().createBCode(gen); 1472 gen.emitThrow(); 1473 } 1474 syn lazy int FinallyHost.label_finally_block(); 1475 1476 syn lazy int TryStmt.label_begin() = hostType().constantPool().newLabel(); 1477 syn lazy int TryStmt.label_block_end() = hostType().constantPool().newLabel(); 1478 syn lazy int TryStmt.label_end() = hostType().constantPool().newLabel(); 1479 syn lazy int TryStmt.label_finally() = hostType().constantPool().newLabel(); 1480 eq TryStmt.label_finally_block() = hostType().constantPool().newLabel(); 1481 syn lazy int TryStmt.label_exception_handler() = hostType().constantPool().newLabel(); 1482 syn lazy int TryStmt.label_catch_end() = hostType().constantPool().newLabel(); 1483 1484 public void TryStmt.createBCode(CodeGeneration gen) { 1485 super.createBCode(gen); 1486 gen.addLabel(label_begin()); 1487 getBlock().createBCode(gen); 1488 if(getBlock().canCompleteNormally()) 1489 gen.emitGoto(label_finally()); 1490 gen.addLabel(label_block_end()); 1491 for(int i = 0; i < getNumCatchClause(); i++) { 1492 getCatchClause(i).createBCode(gen); 1493 if(getCatchClause(i).getBlock().canCompleteNormally()) { 1494 if(!hasFinally()) 1495 gen.emitGoto(label_finally()); 1496 else 1497 gen.emitGoto(label_catch_end()); 1498 } 1499 } 1500 1501 gen.addLabel(label_catch_end()); 1502 if(hasFinally() && getNumCatchClause() > 0) { 1503 gen.emitJsr(label_finally_block()); 1504 if(canCompleteNormally()) 1505 gen.emitGoto(label_end()); 1506 } 1507 1508 gen.addLabel(label_finally()); 1509 if(hasFinally()) { 1510 if(getBlock().canCompleteNormally()) { 1511 gen.emitJsr(label_finally_block()); 1512 if(canCompleteNormally()) 1513 gen.emitGoto(label_end()); 1514 } 1515 gen.addLabel(label_exception_handler()); 1516 emitExceptionHandler(gen); 1517 gen.addLabel(label_finally_block()); 1518 emitFinallyBlock(gen); 1519 } 1520 gen.addLabel(label_end()); 1521 gen.createExceptionTable(this); 1522 } 1523 1524 syn lazy int CatchClause.label() = hostType().constantPool().newLabel(); 1525 public void BasicCatch.createBCode(CodeGeneration gen) { 1526 gen.addLabel(label()); 1527 // add 1 to stack depth 1528 gen.changeStackDepth(1); 1529 getParameter().type().emitStoreLocal(gen, getParameter().localNum()); 1530 getBlock().createBCode(gen); 1531 } 1532 1533 syn lazy int SynchronizedStmt.label_begin() = hostType().constantPool().newLabel(); 1534 syn lazy int SynchronizedStmt.label_end() = hostType().constantPool().newLabel(); 1535 syn lazy int SynchronizedStmt.label_finally() = hostType().constantPool().newLabel(); 1536 eq SynchronizedStmt.label_finally_block() = hostType().constantPool().newLabel(); 1537 syn lazy int SynchronizedStmt.label_exception_handler() = hostType().constantPool().newLabel(); 1538 1539 public void SynchronizedStmt.createBCode(CodeGeneration gen) { 1540 super.createBCode(gen); 1541 getExpr().createBCode(gen); 1542 emitMonitorEnter(gen); 1543 gen.addLabel(label_begin()); 1544 getBlock().createBCode(gen); 1545 gen.addLabel(label_finally()); 1546 if(getBlock().canCompleteNormally()) { 1547 gen.emitJsr(label_finally_block()); 1548 gen.emitGoto(label_end()); 1549 } 1550 gen.addLabel(label_exception_handler()); 1551 emitExceptionHandler(gen); 1552 gen.addLabel(label_finally_block()); 1553 emitFinallyBlock(gen); 1554 gen.addLabel(label_end()); 1555 gen.createExceptionTable(this); 1556 } 1557 1558 /** 1559 * Assert statement bytecode is generated through the transformed 1560 * version of the assert statement! 1561 * 1562 * @see Java1.4Backend/Transformations.jrag 1563 */ 1564 public void AssertStmt.createBCode(CodeGeneration gen) { 1565 throw new UnsupportedOperationException("Assert not implemented yet"); 1566 } 1567 1568 public void LocalClassDeclStmt.createBCode(CodeGeneration gen) { 1569 } 1570 1571 public void ClassAccess.createBCode(CodeGeneration gen) { 1572 if(prevExpr().type().isPrimitiveType() || prevExpr().type().isVoid()) { 1573 TypeDecl typeDecl = lookupType("java.lang", prevExpr().type().primitiveClassName()); 1574 SimpleSet c = typeDecl.memberFields("TYPE"); 1575 FieldDeclaration f = (FieldDeclaration)c.iterator().next(); 1576 f.emitLoadField(gen, typeDecl); 1577 } 1578 else { 1579 FieldDeclaration f = hostType().topLevelType().createStaticClassField(prevExpr().type().referenceClassFieldName()); 1580 // add method to perform lookup as a side-effect 1581 MethodDecl m = hostType().topLevelType().createStaticClassMethod(); 1582 1583 int next_label = hostType().constantPool().newLabel(); 1584 int end_label = hostType().constantPool().newLabel(); 1585 f.emitLoadField(gen, hostType()); 1586 gen.emitBranchNonNull(next_label); 1587 1588 // emit string literal 1589 1590 StringLiteral.push(gen, prevExpr().type().jvmName()); 1591 m.emitInvokeMethod(gen, hostType()); 1592 gen.emitDup(); 1593 f.emitStoreField(gen, hostType()); 1594 gen.emitGoto(end_label); 1595 gen.addLabel(next_label); 1596 gen.changeStackDepth(-1); 1597 f.emitLoadField(gen, hostType()); 1598 gen.addLabel(end_label); 1599 } 1600 } 1601 }