import java.util.*; import java.io.*; aspect CreateBCode { syn lazy boolean TypeDecl.hasClinit() { for(int i = 0; i < getNumBodyDecl(); i++) { BodyDecl b = getBodyDecl(i); if(b instanceof FieldDeclaration) { FieldDeclaration f = (FieldDeclaration)b; if(f.isStatic() && f.hasAbstractVarInit()) { return true; } } else if(b instanceof StaticInitializer) { return true; } } return false; } syn lazy CodeGeneration TypeDecl.bytecodes(ConstantPool constantPool) { CodeGeneration gen = new CodeGeneration(constantPool); for(int i = 0; i < getNumBodyDecl(); i++) { BodyDecl b = getBodyDecl(i); if(b instanceof FieldDeclaration && b.isBytecodeField()) { FieldDeclaration f = (FieldDeclaration)b; if(f.isStatic() && f.hasAbstractVarInit()) { if(f.getAbstractVarInit() instanceof VarInit) { Expr e = ((VarInit)f.getAbstractVarInit()).getExpr(); e.createBCode(gen); e.type().emitAssignConvTo(gen, f.type()); f.emitStore(gen); } else { f.getAbstractVarInit().createBCode(gen); f.type().emitAssignConvTo(gen, f.type()); f.emitStore(gen); } } } else if(b instanceof StaticInitializer) { b.createBCode(gen); } } gen.addBytecode(Bytecode.RETURN); return gen; } syn lazy CodeGeneration MethodDecl.bytecodes(ConstantPool constantPool) { CodeGeneration gen = new CodeGeneration(constantPool); int label = gen.variableScopeLabel(); if(!isStatic()) gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); for(int i = 0; i < getNumParameter(); i++) { ParameterDeclaration p = (ParameterDeclaration)getParameter(i); gen.addLocalVariableEntryAtCurrentPC( p.name(), p.type().typeDescriptor(), p.localNum(), label ); } createBCode(gen); gen.emitReturn(this); gen.addVariableScopeLabel(label); return gen; } syn lazy CodeGeneration ConstructorDecl.bytecodes(ConstantPool constantPool) { CodeGeneration gen = new CodeGeneration(constantPool); int label = gen.variableScopeLabel(); gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label); for(int i = 0; i < getNumParameter(); i++) { ParameterDeclaration p = (ParameterDeclaration)getParameter(i); gen.addLocalVariableEntryAtCurrentPC( p.name(), p.type().typeDescriptor(), p.localNum(), label ); } createBCode(gen); gen.emitReturn(this); gen.addVariableScopeLabel(label); return gen; } public void MethodDecl.createBCode(CodeGeneration gen) { if(hasBlock()) { gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); getBlock().createBCode(gen); } } public void ConstructorDecl.createBCode(CodeGeneration gen) { boolean needsInit = true; if(hasConstructorInvocation()) { getConstructorInvocation().createBCode(gen); Stmt stmt = getConstructorInvocation(); if(stmt instanceof ExprStmt) { ExprStmt exprStmt = (ExprStmt)stmt; Expr expr = exprStmt.getExpr(); if(!(expr instanceof SuperConstructorAccess) && !(expr instanceof SuperConstructorDot)) needsInit = false; } } int enclosingIndex = 0; int localIndex = 1; if(hostType().isInnerType()) { TypeDecl type = hostType().enclosingType(); gen.emitLoadReference(0); gen.emitLoadReference(localIndex); gen.addBytecode(Bytecode.PUTFIELD, -2); String classname = hostType().constantPoolName(); String desc = type.typeDescriptor(); String name = "this$" + enclosingIndex; int index = gen.constantPool().addFieldref(classname, name, desc); int indexHi = index >> 8; int indexLo = index & 0xff; gen.add(indexHi).add(indexLo); enclosingIndex++; localIndex++; } for(int i = 0; i < getNumParameter(); i++) localIndex += getParameter(i).type().size(); for(Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); gen.emitLoadReference(0); v.type().emitLoad(gen, localIndex); gen.addBytecode(Bytecode.PUTFIELD, -1 - v.type().size()); String classname = hostType().constantPoolName(); String desc = v.type().typeDescriptor(); String name = "val$" + v.name(); int index = gen.constantPool().addFieldref(classname, name, desc); int indexHi = index >> 8; int indexLo = index & 0xff; gen.add(indexHi).add(indexLo); localIndex += v.type().size(); } if(needsInit) { TypeDecl typeDecl = hostType(); for(int i = 0; i < typeDecl.getNumBodyDecl(); i++) { BodyDecl b = typeDecl.getBodyDecl(i); if(b instanceof FieldDeclaration && b.isBytecodeField()) { FieldDeclaration f = (FieldDeclaration)b; if(!f.isStatic() && f.hasAbstractVarInit()) { if(f.getAbstractVarInit() instanceof VarInit) { Expr e = ((VarInit)f.getAbstractVarInit()).getExpr(); gen.addBytecode(Bytecode.ALOAD_0); e.createBCode(gen); e.type().emitAssignConvTo(gen, f.type()); f.emitStore(gen); } else { gen.addBytecode(Bytecode.ALOAD_0); f.getAbstractVarInit().createBCode(gen); f.type().emitAssignConvTo(gen, f.type()); f.emitStore(gen); // abstractvarinit är ArrayInit := AbstractVarInit*; } } } else if(b instanceof InstanceInitializer) { b.createBCode(gen); } } } gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum()); getBlock().createBCode(gen); } public void ASTNode.createBCode(CodeGeneration gen) { for (int i=0; i> 8; int indexLo = index & 0xff; gen.add(indexHi).add(indexLo); } while (!enclosing.hasMethod(name())); } } for (int i = 0; i < getNumArg(); ++i) { getArg(i).createBCode(gen); getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion } if(decl().isPrivate() && !hostType().hasMethod(name())) { decl().emitInvokeAccessor(gen); } else { if(!decl().isStatic() && isQualified() && ((AbstractDot)getParent()).getLeft().isSuperAccess()) { decl().emitInvokeSpecial(gen); } else decl().emitInvoke(gen); } } public void ConstructorAccess.createBCode(CodeGeneration gen) { ConstructorDecl c = decl(); int index = 0; // this gen.emitLoadReference(index++); // this$0 if(c.hostType().isInnerType()) gen.emitLoadReference(index++); // args for (int i = 0; i < getNumArg(); ++i) { getArg(i).createBCode(gen); getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion } // this$val for(Iterator iter = c.hostType().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); v.type().emitLoad(gen, index); index += v.type().size(); } gen.emitInvoke(decl()); } public void ClassInstanceDot.createBCode(CodeGeneration gen) { ClassInstanceExpr c = (ClassInstanceExpr)getRight(); c.type().emitNew(gen); c.type().emitDup(gen); getLeft().createBCode(gen); for (int i = 0; i < c.getNumArg(); ++i) { c.getArg(i).createBCode(gen); c.getArg(i).type().emitCastTo(gen, c.decl().getParameter(i).type()); // MethodInvocationConversion } for(Iterator iter = c.type().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); gen.emitLoadFrom(v, hostType()); } if(c.decl().isPrivate() && c.type() != hostType()) { gen.addBytecode(Bytecode.ACONST_NULL); c.decl().emitInvokeAccessor(gen); } else { c.decl().emitInvoke(gen); } } public void ClassInstanceExpr.createBCode(CodeGeneration gen) { type().emitNew(gen); type().emitDup(gen); if(type().isInnerType()) { gen.addBytecode(Bytecode.ALOAD_0); } for (int i = 0; i < getNumArg(); ++i) { getArg(i).createBCode(gen); getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion } for(Iterator iter = type().enclosingVariables().iterator(); iter.hasNext(); ) { Variable v = (Variable)iter.next(); gen.emitLoadFrom(v, hostType()); } if(decl().isPrivate() && type() != hostType()) { gen.addBytecode(Bytecode.ACONST_NULL); decl().emitInvokeAccessor(gen); } else { gen.emitInvoke(decl()); } } public void ArrayInstanceExpr.createBCode(CodeGeneration gen) { if(hasArrayInit()){ getArrayInit().createBCode(gen); } else { for (int i=0; i", desc); gen.addBytecode(Bytecode.INVOKESPECIAL, -1); gen.add(index >> 8).add(index & 0xff); // invokespecial StringBuffer() getLeftOperand().createBCode(gen); // left argumentType = getLeftOperand().type().stringPromotion(); desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); index = gen.constantPool().addMethodref(classname, "append", desc); gen.addBytecode(Bytecode.INVOKEVIRTUAL, -argumentType.size()); gen.add(index >> 8).add(index & 0xff); // StringBuffer.append } else { getLeftOperand().createBCode(gen); } getRightOperand().createBCode(gen); // right argumentType = getRightOperand().type().stringPromotion(); desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor(); index = gen.constantPool().addMethodref(classname, "append", desc); gen.addBytecode(Bytecode.INVOKEVIRTUAL, -argumentType.size()); gen.add(index >> 8).add(index & 0xff); // StringBuffer.append if(lastStringAddPart()) { desc = "()" + type().typeDescriptor(); index = gen.constantPool().addMethodref(classname, "toString", desc); gen.addBytecode(Bytecode.INVOKEVIRTUAL, 0); gen.add(index >> 8).add(index & 0xff); // StringBuffer.toString } } else { super.createBCode(gen); } } public void RelationalExpr.createBCode(CodeGeneration gen) { TypeDecl type = getLeftOperand().type(); if(type.isNumericType()) type = binaryNumericPromotedType(); getLeftOperand().createBCode(gen); getLeftOperand().type().emitCastTo(gen, type); // Binary numeric promotion getRightOperand().createBCode(gen); getRightOperand().type().emitCastTo(gen, type); // Binary numeric promotion int true_label = true_label(gen); int false_label = false_label(gen); compareBranch(gen, true_label, type); gen.emitGoto(false_label); if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(false_label); BooleanType.push(gen, false); gen.emitGoto(end_label); gen.addLabel(true_label); gen.changeStackDepth(-1); // discard false from stack depth computation BooleanType.push(gen, true); gen.addLabel(end_label); } } public void TypeDecl.branchLT(CodeGeneration gen, int label) { throw new Error("branchLT not supported for " + getClass().getName()); } public void DoubleType.branchLT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPG); gen.emitCompare(Bytecode.IFLT, label); } public void FloatType.branchLT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPG); gen.emitCompare(Bytecode.IFLT, label); } public void LongType.branchLT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFLT, label); } public void IntegralType.branchLT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLT, label); } public void TypeDecl.branchLE(CodeGeneration gen, int label) { throw new Error("branchLE not supported for " + getClass().getName()); } public void DoubleType.branchLE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPG); gen.emitCompare(Bytecode.IFLE, label); } public void FloatType.branchLE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPG); gen.emitCompare(Bytecode.IFLE, label); } public void LongType.branchLE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFLE, label); } public void IntegralType.branchLE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLE, label); } public void TypeDecl.branchGE(CodeGeneration gen, int label) { throw new Error("branchGE not supported for " + getClass().getName()); } public void DoubleType.branchGE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPL); gen.emitCompare(Bytecode.IFGE, label); } public void FloatType.branchGE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPL); gen.emitCompare(Bytecode.IFGE, label); } public void LongType.branchGE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFGE, label); } public void IntegralType.branchGE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGE, label); } public void TypeDecl.branchGT(CodeGeneration gen, int label) { throw new Error("branchGT not supported for " + getClass().getName()); } public void DoubleType.branchGT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPL); gen.emitCompare(Bytecode.IFGT, label); } public void FloatType.branchGT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPL); gen.emitCompare(Bytecode.IFGT, label); } public void LongType.branchGT(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFGT, label); } public void IntegralType.branchGT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGT, label); } public void TypeDecl.branchEQ(CodeGeneration gen, int label) { throw new Error("branchEQ not supported for " + getClass().getName()); } public void DoubleType.branchEQ(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPL); gen.emitCompare(Bytecode.IFEQ, label); } public void FloatType.branchEQ(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPL); gen.emitCompare(Bytecode.IFEQ, label); } public void LongType.branchEQ(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFEQ, label); } public void IntegralType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPEQ, label); } public void BooleanType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPEQ, label); } public void ReferenceType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPEQ, label); } public void NullType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPEQ, label); } public void TypeDecl.branchNE(CodeGeneration gen, int label) { throw new Error("branchNE not supported for " + getClass().getName()); } public void DoubleType.branchNE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.DCMPL); gen.emitCompare(Bytecode.IFNE, label); } public void FloatType.branchNE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.FCMPL); gen.emitCompare(Bytecode.IFNE, label); } public void LongType.branchNE(CodeGeneration gen, int label) { gen.addBytecode(Bytecode.LCMP); gen.emitCompare(Bytecode.IFNE, label); } public void IntegralType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPNE, label); } public void BooleanType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPNE, label); } public void ReferenceType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPNE, label); } public void NullType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPNE, label); } public void RelationalExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { throw new Error("compareBranch not supported for " + getClass().getName()); } public void LTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); } public void LEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); } public void GEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); } public void GTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); } public void EQExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); } public void NEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); } inh int Expr.condition_false_label(CodeGeneration gen); eq Program.getCompilationUnit(int i).condition_false_label(CodeGeneration gen) { throw new Error("condition_false_label not implemented"); } eq IfStmt.getCondition().condition_false_label(CodeGeneration gen) = else_branch_label(gen); eq QuestionColonExpr.getCondition().condition_false_label(CodeGeneration gen) = else_branch_label(gen); eq WhileStmt.getCondition().condition_false_label(CodeGeneration gen) = end_label(gen); eq DoStmt.getCondition().condition_false_label(CodeGeneration gen) = end_label(gen); eq ForStmt.getCondition().condition_false_label(CodeGeneration gen) = end_label(gen); eq LogNotExpr.getOperand().condition_false_label(CodeGeneration gen) = true_label(gen); eq RelationalExpr.getLeftOperand().condition_false_label(CodeGeneration gen) = false_label(gen); eq RelationalExpr.getRightOperand().condition_false_label(CodeGeneration gen) = false_label(gen); eq QuestionColonExpr.getTrueExpr().condition_false_label(CodeGeneration gen) = false_label(gen); eq QuestionColonExpr.getFalseExpr().condition_false_label(CodeGeneration gen) = false_label(gen); inh int Expr.condition_true_label(CodeGeneration gen); eq Program.getCompilationUnit(int i).condition_true_label(CodeGeneration gen) { throw new Error("condition_true_label not implemented"); } eq IfStmt.getCondition().condition_true_label(CodeGeneration gen) = then_branch_label(gen); eq QuestionColonExpr.getCondition().condition_true_label(CodeGeneration gen) = then_branch_label(gen); eq WhileStmt.getCondition().condition_true_label(CodeGeneration gen) = stmt_label(gen); eq DoStmt.getCondition().condition_true_label(CodeGeneration gen) = begin_label(gen); eq ForStmt.getCondition().condition_true_label(CodeGeneration gen) = begin_label(gen); eq LogNotExpr.getOperand().condition_true_label(CodeGeneration gen) = false_label(gen); eq RelationalExpr.getLeftOperand().condition_true_label(CodeGeneration gen) = true_label(gen); eq RelationalExpr.getRightOperand().condition_true_label(CodeGeneration gen) = true_label(gen); eq QuestionColonExpr.getTrueExpr().condition_true_label(CodeGeneration gen) = true_label(gen); eq QuestionColonExpr.getFalseExpr().condition_true_label(CodeGeneration gen) = true_label(gen); syn boolean Expr.isCodegenFalse() = isFalse(); eq AndLogicalExpr.isCodegenFalse() = getLeftOperand().isCodegenFalse() || getRightOperand().isCodegenFalse(); eq OrLogicalExpr.isCodegenFalse() = getLeftOperand().isCodegenFalse() && getRightOperand().isCodegenFalse(); eq ParExpr.isCodegenFalse() = getExpr().isCodegenFalse(); eq LogNotExpr.isCodegenFalse() = getOperand().isCodegenTrue(); eq QuestionColonExpr.isCodegenFalse() = getCondition().isCodegenTrue() && getTrueExpr().isCodegenFalse() || getCondition().isCodegenFalse() && getFalseExpr().isCodegenFalse() || getTrueExpr().isCodegenFalse() && getFalseExpr().isCodegenFalse(); syn boolean Expr.isCodegenTrue() = isTrue(); eq AndLogicalExpr.isCodegenTrue() = getLeftOperand().isCodegenTrue() && getRightOperand().isCodegenTrue(); eq OrLogicalExpr.isCodegenTrue() = getLeftOperand().isCodegenTrue() || getRightOperand().isCodegenTrue(); eq ParExpr.isCodegenTrue() = getExpr().isCodegenTrue(); eq LogNotExpr.isCodegenTrue() = getOperand().isCodegenFalse(); eq QuestionColonExpr.isCodegenTrue() = getCondition().isCodegenTrue() && getTrueExpr().isCodegenTrue() || getCondition().isCodegenFalse() && getFalseExpr().isCodegenTrue() || getTrueExpr().isCodegenTrue() && getFalseExpr().isCodegenTrue(); syn boolean Expr.lastIsFalse() = isFalse(); eq ParExpr.lastIsFalse() = getExpr().lastIsFalse(); eq AndLogicalExpr.lastIsFalse() = getLeftOperand().lastIsFalse() || getRightOperand().lastIsFalse(); public void LogNotExpr.createBCode(CodeGeneration gen) { int false_label = false_label(gen); int true_label = true_label(gen); getOperand().createBCode(gen); if(!getOperand().endsWithBranch()) gen.emitOperation(this); else if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } } public void AndLogicalExpr.createBCode(CodeGeneration gen) { int false_label = false_label(gen); int true_label = true_label(gen); if(!getLeftOperand().isTrue()) { getLeftOperand().createBCode(gen); if(!getLeftOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, false_label); } gen.addLabel(next_test_label(gen)); if(!getLeftOperand().lastIsFalse() && !getRightOperand().isTrue()) { getRightOperand().createBCode(gen); if(!getRightOperand().endsWithBranch()) { gen.emitCompare(Bytecode.IFEQ, false_label); } } gen.emitGoto(true_label); if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } /* int false_label = condition_false_label(gen); if(false_label != 0) { if(!getLeftOperand().isTrue()) { getLeftOperand().createBCode(gen); if(!getLeftOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, false_label); } if(!getLeftOperand().lastIsFalse()) { getRightOperand().createBCode(gen); if(!getRightOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, false_label); } } else { int end_label = gen.label(); BooleanType.push(gen, false); if(!getLeftOperand().isTrue()) { getLeftOperand().createBCode(gen); gen.emitCompare(Bytecode.IFEQ, end_label); } if(!getLeftOperand().lastIsFalse()) { getRightOperand().createBCode(gen); gen.emitCompare(Bytecode.IFEQ, end_label); } gen.emitPop(); BooleanType.push(gen, true); gen.addLabel(end_label); } */ } syn boolean ASTNode.isComplexLogical() = false; eq OrLogicalExpr.isComplexLogical() = true; eq AndLogicalExpr.isComplexLogical() = true; eq LogNotExpr.isComplexLogical() = getOperand().isComplexLogical(); eq ParExpr.isComplexLogical() = getExpr().isComplexLogical(); syn boolean ASTNode.endsWithBranch() = false; eq OrLogicalExpr.endsWithBranch() = true; eq AndLogicalExpr.endsWithBranch() = true; eq LogNotExpr.endsWithBranch() = getOperand().endsWithBranch(); eq ParExpr.endsWithBranch() = getExpr().endsWithBranch(); eq RelationalExpr.endsWithBranch() = true; eq QuestionColonExpr.endsWithBranch() = type().isBoolean(); /* syn lazy int OrLogicalExpr.true_label(CodeGeneration gen) { if(isLastOrLogicalExpr()) return gen.label(); else { ASTNode node = this; while(!node.isLastOrLogicalExpr()) node = node.getParent(); return ((OrLogicalExpr)node).true_label(gen); } }*/ syn boolean ASTNode.isLastOrLogicalExpr() { if(getParent() instanceof OrLogicalExpr) return false; ASTNode node = getParent(); while(node instanceof ParExpr) node = node.getParent(); if(node instanceof OrLogicalExpr) return false; return true; } syn boolean ASTNode.isLogicalExpr() = false; eq Opt.isLogicalExpr() = getParent().isLogicalExpr(); eq List.isLogicalExpr() = getParent().isLogicalExpr(); eq OrLogicalExpr.isLogicalExpr() = true; eq AndLogicalExpr.isLogicalExpr() = true; eq LogNotExpr.isLogicalExpr() = true; eq IfStmt.isLogicalExpr() = true; eq QuestionColonExpr.isLogicalExpr() = true; eq WhileStmt.isLogicalExpr() = true; eq DoStmt.isLogicalExpr() = true; eq ForStmt.isLogicalExpr() = true; //eq RelationalExpr.isLogicalExpr() = true; eq RelationalExpr.isLogicalExpr() = false; syn boolean ASTNode.isTopLogicalExpr() { if(getParent().isLogicalExpr()) return false; ASTNode node = getParent(); while(node instanceof ParExpr) node = node.getParent(); if(node.isLogicalExpr()) return false; return true; } syn lazy int LogNotExpr.false_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_false_label(gen); syn lazy int LogNotExpr.true_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_true_label(gen); syn lazy int QuestionColonExpr.false_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_false_label(gen); syn lazy int QuestionColonExpr.true_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_true_label(gen); syn lazy int RelationalExpr.false_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_false_label(gen); syn lazy int RelationalExpr.true_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_true_label(gen); eq AndLogicalExpr.getLeftOperand().condition_false_label(CodeGeneration gen) = false_label(gen); eq AndLogicalExpr.getRightOperand().condition_false_label(CodeGeneration gen) = false_label(gen); eq AndLogicalExpr.getLeftOperand().condition_true_label(CodeGeneration gen) = next_test_label(gen); eq AndLogicalExpr.getRightOperand().condition_true_label(CodeGeneration gen) = true_label(gen); syn lazy int AndLogicalExpr.false_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_false_label(gen); syn lazy int AndLogicalExpr.true_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_true_label(gen); syn lazy int AndLogicalExpr.next_test_label(CodeGeneration gen) = gen.label(); eq OrLogicalExpr.getLeftOperand().condition_false_label(CodeGeneration gen) = next_test_label(gen); eq OrLogicalExpr.getLeftOperand().condition_true_label(CodeGeneration gen) = true_label(gen); eq OrLogicalExpr.getRightOperand().condition_false_label(CodeGeneration gen) = false_label(gen); eq OrLogicalExpr.getRightOperand().condition_true_label(CodeGeneration gen) = true_label(gen); syn lazy int OrLogicalExpr.false_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_false_label(gen); syn lazy int OrLogicalExpr.true_label(CodeGeneration gen) = isTopLogicalExpr() ? gen.label() : condition_true_label(gen); syn lazy int OrLogicalExpr.next_test_label(CodeGeneration gen) = gen.label(); public void OrLogicalExpr.createBCode(CodeGeneration gen) { int false_label = false_label(gen); int true_label = true_label(gen); if(!getLeftOperand().isCodegenFalse()) { getLeftOperand().createBCode(gen); if(!getLeftOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFNE, true_label); } gen.addLabel(next_test_label(gen)); if(!getLeftOperand().isTrue()) { getRightOperand().createBCode(gen); if(!getRightOperand().endsWithBranch()) { gen.emitCompare(Bytecode.IFNE, true_label); gen.emitGoto(false_label); /* if(!isLastOrLogicalExpr()) gen.emitCompare(Bytecode.IFNE, true_label); else gen.emitCompare(Bytecode.IFEQ, false_label); */ } } if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } /* int false_label = condition_false_label(gen); if(false_label != 0) { int true_label = true_label(gen); if(!getLeftOperand().isCodegenFalse()) { getLeftOperand().createBCode(gen); if(!getLeftOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFNE, true_label); } gen.addLabel(next_test_label(gen)); if(!getLeftOperand().isTrue()) { getRightOperand().createBCode(gen); if(!getRightOperand().endsWithBranch()) { if(!isLastOrLogicalExpr()) gen.emitCompare(Bytecode.IFNE, true_label); else gen.emitCompare(Bytecode.IFEQ, false_label); } } if(isLastOrLogicalExpr()) { gen.emitGoto(false_label); gen.addLabel(true_label); } } else { int end_label = gen.label(); int true_label = gen.label(); false_label = gen.label(); if(!getLeftOperand().isCodegenFalse()) { getLeftOperand().createBCode(gen); if(!getLeftOperand().endsWithBranch()) gen.emitCompare(Bytecode.IFNE, true_label); } gen.addLabel(next_test_label(gen)); if(!getLeftOperand().isTrue()) { getRightOperand().createBCode(gen); if(!getRightOperand().endsWithBranch()) { if(!isLastOrLogicalExpr()) gen.emitCompare(Bytecode.IFNE, true_label); else gen.emitCompare(Bytecode.IFEQ, false_label); } } gen.addLabel(false_label); BooleanType.push(gen, false); gen.emitGoto(end_label); gen.addLabel(true_label); BooleanType.push(gen, true); gen.addLabel(end_label); } */ } public void InstanceOfExpr.createBCode(CodeGeneration gen) { getExpr().createBCode(gen); gen.emitInstanceof(getTypeAccess().type()); } syn lazy int QuestionColonExpr.else_branch_label(CodeGeneration gen) = gen.label(); syn lazy int QuestionColonExpr.then_branch_label(CodeGeneration gen) = gen.label(); public void QuestionColonExpr.createBCode(CodeGeneration gen) { int elseBranch = else_branch_label(gen); int thenBranch = then_branch_label(gen); int endBranch = gen.label(); if(getCondition().isCodegenTrue()) { getTrueExpr().createBCode(gen); getTrueExpr().type().emitCastTo(gen, type()); if(type().isBoolean()) { if(!getTrueExpr().endsWithBranch()) { gen.emitCompare(Bytecode.IFEQ, false_label(gen)); gen.emitGoto(true_label(gen)); } if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label(gen)); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label(gen)); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } } } else if(getCondition().isCodegenFalse()) { getFalseExpr().createBCode(gen); getFalseExpr().type().emitCastTo(gen, type()); if(type().isBoolean()) { if(!getFalseExpr().endsWithBranch()) { gen.emitCompare(Bytecode.IFEQ, false_label(gen)); gen.emitGoto(true_label(gen)); } if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label(gen)); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label(gen)); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } } } else { if(type().isBoolean()) { getCondition().createBCode(gen); if(!getCondition().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, elseBranch); gen.addLabel(thenBranch); getTrueExpr().createBCode(gen); getTrueExpr().type().emitCastTo(gen, type()); if(!getTrueExpr().endsWithBranch()) { gen.emitCompare(Bytecode.IFEQ, false_label(gen)); gen.emitGoto(true_label(gen)); } gen.addLabel(elseBranch); getFalseExpr().createBCode(gen); getFalseExpr().type().emitCastTo(gen, type()); if(!getFalseExpr().endsWithBranch()) { gen.emitCompare(Bytecode.IFEQ, false_label(gen)); gen.emitGoto(true_label(gen)); } if(isTopLogicalExpr()) { int end_label = gen.label(); gen.addLabel(true_label(gen)); BooleanType.push(gen, true); gen.emitGoto(end_label); gen.addLabel(false_label(gen)); BooleanType.push(gen, false); gen.addLabel(end_label); gen.changeStackDepth(-1); } } else { getCondition().createBCode(gen); if(!getCondition().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, elseBranch); gen.addLabel(thenBranch); getTrueExpr().createBCode(gen); getTrueExpr().type().emitCastTo(gen, type()); if(!getTrueExpr().endsWithBranch()) gen.emitGoto(endBranch); gen.addLabel(elseBranch); gen.changeStackDepth(-type().size()); // discard true expr from stack depth computation getFalseExpr().createBCode(gen); getFalseExpr().type().emitCastTo(gen, type()); gen.addLabel(endBranch); } } } /* public void QuestionColonExpr.createBCode(CodeGeneration gen) { int false_label = gen.label(); int end_label = gen.label(); getCondition().createBCode(gen); gen.emitCompare(Bytecode.IFEQ, false_label); getTrueExpr().createBCode(gen); getTrueExpr().type().emitCastTo(gen, type()); gen.emitGoto(end_label); gen.addLabel(false_label); gen.changeStackDepth(-type().size()); // discard true expr from stack depth computation getFalseExpr().createBCode(gen); getFalseExpr().type().emitCastTo(gen, type()); gen.addLabel(end_label); } */ public void Stmt.createBCode(CodeGeneration gen) { gen.addLineNumberEntryAtCurrentPC(this); } public void Block.createBCode(CodeGeneration gen) { //super.createBCode(gen); for(int i = 0; i < getNumStmt(); i++) getStmt(i).createBCode(gen); gen.addVariableScopeLabel(variableScopeEndLabel(gen)); } public void EmptyStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); } syn lazy int LabelStmt.label(CodeGeneration gen) = gen.label(); syn lazy int LabelStmt.end_label(CodeGeneration gen) = gen.label(); public void LabelStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); gen.addLabel(label(gen)); getStmt().createBCode(gen); gen.addLabel(end_label(gen)); } public void ExprStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); getExpr().createBCode(gen); if(needsPop()) getExpr().type().emitPop(gen); } syn lazy DefaultCase SwitchStmt.defaultCase() { for(int i= 0; i < getNumCase(); i++) { if(getCase(i) instanceof DefaultCase) return (DefaultCase)getCase(i); } return null; } syn lazy int SwitchStmt.end_label(CodeGeneration gen) = gen.label(); public void SwitchStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); int cond_label = gen.label(); int switch_label = gen.label(); gen.emitGoto(cond_label); for(int i= 0; i < getNumCase(); i++) { getCase(i).createBCode(gen); } gen.emitGoto(end_label(gen)); gen.addLabel(cond_label); getExpr().createBCode(gen); TreeMap map = new TreeMap(); for(int i = 0; i < getNumCase(); i++) { Case c = getCase(i); if(c instanceof ConstCase) { ConstCase ca = (ConstCase)c; map.put(new Integer(ca.getValue().constant().intValue()), ca); } } long low = map.isEmpty() ? 0 : ((Integer)map.firstKey()).intValue(); long high = map.isEmpty() ? 0 : ((Integer)map.lastKey()).intValue(); long tableSwitchSize = 8L + (high - low + 1L) * 4L; long lookupSwitchSize = 4L + map.size() * 8L; gen.addLabel(switch_label); if(tableSwitchSize < lookupSwitchSize) { gen.addBytecode(Bytecode.TABLESWITCH); int pad = emitPad(gen); int defaultOffset = defaultOffset(gen, switch_label); if(defaultOffset == 0) { defaultOffset = 1 + pad + 4 + 4 + 4 + 4 * getNumCase(); } gen.add4(defaultOffset); gen.add4((int)low); gen.add4((int)high); for(long i = low; i <= high; i++) { ConstCase ca = (ConstCase)map.get(new Integer((int)i)); if(ca != null) { int offset = gen.addressOf(ca.label(gen)) - gen.addressOf(switch_label); gen.add4(offset); } else { gen.add4(defaultOffset); } } } else { gen.addBytecode(Bytecode.LOOKUPSWITCH); int pad = emitPad(gen); int defaultOffset = defaultOffset(gen, switch_label); if(defaultOffset == 0) { defaultOffset = 1 + pad + 4 + 4 + 8 * getNumCase(); } gen.add4(defaultOffset); gen.add4(map.size()); for(Iterator iter = map.values().iterator(); iter.hasNext(); ) { ConstCase ca = (ConstCase)iter.next(); gen.add4(ca.getValue().constant().intValue()); int offset = gen.addressOf(ca.label(gen)) - gen.addressOf(switch_label); gen.add4(offset); } } gen.addLabel(end_label(gen)); } private int SwitchStmt.emitPad(CodeGeneration gen) { int pad = (4 - (gen.pos() % 4)) % 4; for(int i = 0; i < pad; i++) gen.addBytecode(Bytecode.NOP); if(gen.pos() % 4 != 0) throw new Error("Switch not at 4-byte boundary:" + gen.pos()); return pad; } private int SwitchStmt.defaultOffset(CodeGeneration gen, int switch_label) { boolean hasDefault = defaultCase() != null; if(hasDefault) { int offset = gen.addressOf(defaultCase().label(gen)) - gen.addressOf(switch_label); return offset; } return 0; } syn lazy int Case.label(CodeGeneration gen) = gen.label(); public void Case.createBCode(CodeGeneration gen) { gen.addLabel(label(gen)); for(int i = 0; i < getNumStmt(); i++) getStmt(i).createBCode(gen); } syn lazy int IfStmt.else_branch_label(CodeGeneration gen) = gen.label(); syn lazy int IfStmt.then_branch_label(CodeGeneration gen) = gen.label(); public void IfStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); int elseBranch = else_branch_label(gen); int thenBranch = then_branch_label(gen); int endBranch = gen.label(); if(getCondition().isCodegenTrue()) { getThen().createBCode(gen); } else if(getCondition().isCodegenFalse()) { if(hasElse()) getElse().createBCode(gen); } else { getCondition().createBCode(gen); if(!getCondition().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, elseBranch); gen.addLabel(thenBranch); getThen().createBCode(gen); if(getThen().canCompleteNormally()) gen.emitGoto(endBranch); gen.addLabel(elseBranch); if(hasElse()) getElse().createBCode(gen); gen.addLabel(endBranch); } } syn lazy int WhileStmt.cond_label(CodeGeneration gen) = gen.label(); syn lazy int WhileStmt.end_label(CodeGeneration gen) = gen.label(); syn lazy int WhileStmt.stmt_label(CodeGeneration gen) = gen.label(); public void WhileStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); gen.addLabel(cond_label(gen)); if(getCondition().isCodegenTrue()) { getStmt().createBCode(gen); gen.emitGoto(cond_label(gen)); if(canCompleteNormally()) { gen.addLabel(end_label(gen)); } } else if(getCondition().isCodegenFalse()) { } else { if(canCompleteNormally()) { getCondition().createBCode(gen); if(!getCondition().endsWithBranch()) gen.emitCompare(Bytecode.IFEQ, end_label(gen)); } gen.addLabel(stmt_label(gen)); getStmt().createBCode(gen); gen.emitGoto(cond_label(gen)); if(canCompleteNormally()) { gen.addLabel(end_label(gen)); } } } syn lazy int DoStmt.begin_label(CodeGeneration gen) = gen.label(); syn lazy int DoStmt.cond_label(CodeGeneration gen) = gen.label(); syn lazy int DoStmt.end_label(CodeGeneration gen) = gen.label(); public void DoStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); gen.addLabel(begin_label(gen)); getStmt().createBCode(gen); gen.addLabel(cond_label(gen)); if(getCondition().isCodegenTrue()) { gen.emitGoto(begin_label(gen)); } else if(getCondition().isCodegenFalse()) { } else { getCondition().createBCode(gen); if(!getCondition().endsWithBranch()) gen.emitCompare(Bytecode.IFNE, begin_label(gen)); } gen.addLabel(end_label(gen)); } syn lazy int ForStmt.cond_label(CodeGeneration gen) = gen.label(); syn lazy int ForStmt.begin_label(CodeGeneration gen) = gen.label(); syn lazy int ForStmt.update_label(CodeGeneration gen) = gen.label(); syn lazy int ForStmt.end_label(CodeGeneration gen) = gen.label(); public void ForStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); for (int i=0; i 0) { gen.emitJsr(label_finally_block(gen)); if(canCompleteNormally()) gen.emitGoto(label_end(gen)); //gen.addBytecode(Bytecode.RETURN); } gen.addLabel(label_finally(gen)); if(hasFinally()) { if(getBlock().canCompleteNormally()) { gen.emitJsr(label_finally_block(gen)); if(canCompleteNormally()) gen.emitGoto(label_end(gen)); } gen.addLabel(label_exception_handler(gen)); emitExceptionHandler(gen); gen.addLabel(label_finally_block(gen)); emitFinallyBlock(gen); } gen.addLabel(label_end(gen)); gen.createExceptionTable(this); } syn lazy int Catch.label(CodeGeneration gen) = gen.label(); public void Catch.createBCode(CodeGeneration gen) { gen.addLabel(label(gen)); // add 1 to stack depth gen.changeStackDepth(1); getParameter().emitStore(gen); getBlock().createBCode(gen); } syn lazy int SynchronizeStmt.label_begin(CodeGeneration gen) = gen.label(); syn lazy int SynchronizeStmt.label_end(CodeGeneration gen) = gen.label(); syn lazy int SynchronizeStmt.label_finally(CodeGeneration gen) = gen.label(); syn lazy int SynchronizeStmt.label_finally_block(CodeGeneration gen) = gen.label(); syn lazy int SynchronizeStmt.label_exception_handler(CodeGeneration gen) = gen.label(); public void SynchronizeStmt.createBCode(CodeGeneration gen) { super.createBCode(gen); getExpr().createBCode(gen); emitMonitorEnter(gen); gen.addLabel(label_begin(gen)); getBlock().createBCode(gen); gen.addLabel(label_finally(gen)); if(getBlock().canCompleteNormally()) { gen.emitJsr(label_finally_block(gen)); gen.emitGoto(label_end(gen)); } gen.addLabel(label_exception_handler(gen)); emitExceptionHandler(gen); gen.addLabel(label_finally_block(gen)); emitFinallyBlock(gen); gen.addLabel(label_end(gen)); gen.createExceptionTable(this); } public void AssertStmt.createBCode(CodeGeneration gen) { throw new UnsupportedOperationException("Assert not implemented yet"); } public void LocalClassDeclStmt.createBCode(CodeGeneration gen) { } }