001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     * this list of conditions and the following disclaimer.
009     *
010     * 2. Redistributions in binary form must reproduce the above copyright notice,
011     * this list of conditions and the following disclaimer in the documentation
012     * and/or other materials provided with the distribution.
013     *
014     * 3. Neither the name of the copyright holder nor the names of its
015     * contributors may be used to endorse or promote products derived from this
016     * software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028     * POSSIBILITY OF SUCH DAMAGE.
029     */
030    
031    aspect CodeGeneration {
032    
033      public void ASTNode.setSourceLineNumber(int i) {
034        setStart(ASTNode.makePosition(i, 1));
035      }
036    
037      syn int ASTNode.sourceLineNumber() = getStart() != 0 ? getLine(getStart()) : -1;
038      eq ReturnStmt.sourceLineNumber() {
039        int num = super.sourceLineNumber();
040        if (num != -1) {
041          return num;
042        }
043        if (hasResult()) {
044          num = getResult().findFirstSourceLineNumber();
045          if (num != -1) {
046            return num;
047          }
048        }
049        return getLine(getParent().getParent().getEnd());
050      }
051      eq ExprStmt.sourceLineNumber() = getExpr().findFirstSourceLineNumber();
052      eq Access.sourceLineNumber() = findFirstSourceLineNumber();
053    
054      protected int ASTNode.findFirstSourceLineNumber() {
055        if (getStart() != 0) {
056          return getLine(getStart());
057        }
058        for (int i = 0; i < getNumChild(); i++) {
059          int num = getChild(i).findFirstSourceLineNumber();
060          if (num != -1) {
061            return num;
062          }
063        }
064        return -1;
065      }
066    
067      inh int VariableDeclaration.variableScopeEndLabel(CodeGeneration gen);
068      syn lazy int Block.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel();
069      eq Block.getStmt(int i).variableScopeEndLabel(CodeGeneration gen) = variableScopeEndLabel(gen);
070      syn lazy int ForStmt.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel();
071      eq ForStmt.getInitStmt(int i).variableScopeEndLabel(CodeGeneration gen) = variableScopeEndLabel(gen);
072      eq Program.getChild(int i).variableScopeEndLabel(CodeGeneration gen) {
073        throw new Error("variableScopeEndLabel not valid from here");
074      }
075    
076      /*************************************************************
077       * Emit methods
078       *************************************************************/
079    
080      // push constants
081    
082      public static void IntegerLiteral.push(CodeGeneration gen, int value) {
083        switch(value) {
084          case -1:
085            gen.emit(Bytecode.ICONST_M1);
086            break;
087          case 0:
088            gen.emit(Bytecode.ICONST_0);
089            break;
090          case 1:
091            gen.emit(Bytecode.ICONST_1);
092            break;
093          case 2:
094            gen.emit(Bytecode.ICONST_2);
095            break;
096          case 3:
097            gen.emit(Bytecode.ICONST_3);
098            break;
099          case 4:
100            gen.emit(Bytecode.ICONST_4);
101            break;
102          case 5:
103            gen.emit(Bytecode.ICONST_5);
104            break;
105          default:
106            if (value >= -128 && value <= 127) {
107              gen.emit(Bytecode.BIPUSH).add(value);
108            } else if (value >= -32768 && value <= 32767) {
109              gen.emit(Bytecode.SIPUSH).add2(value);
110            } else {
111              int index = gen.constantPool().addConstant(value);
112              if (index < 256) {
113                gen.emit(Bytecode.LDC).add(index);
114              } else {
115                gen.emit(Bytecode.LDC_W).add2(index);
116              }
117            }
118        }
119      }
120      public static void LongLiteral.push(CodeGeneration gen, long value) {
121        if (value == 0) {
122          gen.emit(Bytecode.LCONST_0);
123        } else if (value == 1) {
124          gen.emit(Bytecode.LCONST_1);
125        } else {
126          int index = gen.constantPool().addConstant(value);
127          gen.emit(Bytecode.LDC2_W).add2(index);
128        }
129      }
130      public static void DoubleLiteral.push(CodeGeneration gen, double value) {
131        if (value == 0) {
132          gen.emit(Bytecode.DCONST_0);
133        } else if (value == 1) {
134          gen.emit(Bytecode.DCONST_1);
135        } else {
136          int index = gen.constantPool().addConstant(value);
137          gen.emit(Bytecode.LDC2_W).add2(index);
138        }
139      }
140      public static void FloatingPointLiteral.push(CodeGeneration gen, float value) {
141        if (value == 0) {
142          gen.emit(Bytecode.FCONST_0);
143        } else if (value == 1) {
144          gen.emit(Bytecode.FCONST_1);
145        } else if (value == 2) {
146          gen.emit(Bytecode.FCONST_2);
147        } else {
148          int index = gen.constantPool().addConstant(value);
149          if (index < 256) {
150            gen.emit(Bytecode.LDC).add(index);
151          } else {
152            gen.emit(Bytecode.LDC_W).add2(index);
153          }
154        }
155      }
156      public static void StringLiteral.push(CodeGeneration gen, String value) {
157        int index = gen.constantPool().addConstant(value);
158        if (index < 256) {
159          gen.emit(Bytecode.LDC).add(index);
160        } else {
161          gen.emit(Bytecode.LDC_W).add2(index);
162        }
163      }
164    
165      public static void BooleanLiteral.push(CodeGeneration gen, boolean value) {
166        gen.emit(value ? Bytecode.ICONST_1 : Bytecode.ICONST_0);
167      }
168    
169      public void TypeDecl.emitPushConstant(CodeGeneration gen, int value) { }
170      public void IntegralType.emitPushConstant(CodeGeneration gen, int value) { IntegerLiteral.push(gen, value); }
171      public void LongType.emitPushConstant(CodeGeneration gen, int value) { LongLiteral.push(gen, value); }
172      public void DoubleType.emitPushConstant(CodeGeneration gen, int value) { DoubleLiteral.push(gen, value); }
173      public void FloatType.emitPushConstant(CodeGeneration gen, int value) { FloatingPointLiteral.push(gen, value); }
174    
175      // push literals
176    
177      public void Literal.emitPushConstant(CodeGeneration gen) {
178        System.err.println("ERROR: Tried to generate bytecode for: " + getClass().getName());
179      }
180    
181      public void IntegerLiteral.emitPushConstant(CodeGeneration gen) {
182        type().emitPushConstant(gen, constant().intValue());
183      }
184    
185      public void CharacterLiteral.emitPushConstant(CodeGeneration gen) {
186        type().emitPushConstant(gen, constant().intValue());
187      }
188    
189      public void FloatingPointLiteral.emitPushConstant(CodeGeneration gen) {
190        FloatingPointLiteral.push(gen, constant().floatValue());
191      }
192    
193      public void LongLiteral.emitPushConstant(CodeGeneration gen) {
194        LongLiteral.push(gen, constant().longValue());
195      }
196    
197      public void DoubleLiteral.emitPushConstant(CodeGeneration gen) {
198        DoubleLiteral.push(gen, constant().doubleValue());
199      }
200    
201      public void StringLiteral.emitPushConstant(CodeGeneration gen) {
202        StringLiteral.push(gen, getLITERAL());
203      }
204    
205      public void NullLiteral.emitPushConstant(CodeGeneration gen) {
206        gen.emit(Bytecode.ACONST_NULL);
207      }
208    
209      public void BooleanLiteral.emitPushConstant(CodeGeneration gen) {
210        BooleanLiteral.push(gen, constant().booleanValue());
211      }
212    
213      public void ASTNode.error() {
214        Throwable t = new Throwable();
215        StackTraceElement[] ste = new Throwable().getStackTrace();
216        String s = ste[1].toString();
217        throw new Error(s+" Cannot create bytecode for:"+getClass().getName());
218      }
219    
220      public void Constant.createBCode(CodeGeneration gen) {
221        if (this instanceof ConstantInt) {
222          IntegerLiteral.push(gen, intValue());
223        } else if (this instanceof ConstantLong) {
224          LongLiteral.push(gen, longValue());
225        } else if (this instanceof ConstantFloat) {
226          FloatingPointLiteral.push(gen, floatValue());
227        } else if (this instanceof ConstantDouble) {
228          DoubleLiteral.push(gen, doubleValue());
229        } else if (this instanceof ConstantChar) {
230          IntegerLiteral.push(gen, intValue());
231        } else if (this instanceof ConstantBoolean) {
232          BooleanLiteral.push(gen, booleanValue());
233        } else if (this instanceof ConstantString) {
234          StringLiteral.push(gen, stringValue());
235        }
236      }
237    
238      // return
239    
240      public void TypeDecl.emitReturn(CodeGeneration gen)      { error(); }
241      public void VoidType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.RETURN);}
242      public void PrimitiveType.emitReturn(CodeGeneration gen) { gen.emit(Bytecode.IRETURN);}
243      public void LongType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.LRETURN);}
244      public void FloatType.emitReturn(CodeGeneration gen)     { gen.emit(Bytecode.FRETURN);}
245      public void DoubleType.emitReturn(CodeGeneration gen)    { gen.emit(Bytecode.DRETURN);}
246      public void ReferenceType.emitReturn(CodeGeneration gen) { gen.emit(Bytecode.ARETURN);}
247      public void NullType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.ARETURN);}
248    
249      syn byte TypeDecl.arrayLoad() {
250        throw new Error("Cannot create array load for TypeDecl");
251      }
252      eq ReferenceType.arrayLoad() = Bytecode.AALOAD;
253      eq IntType.arrayLoad() = Bytecode.IALOAD;
254      eq LongType.arrayLoad() = Bytecode.LALOAD;
255      eq FloatType.arrayLoad() = Bytecode.FALOAD;
256      eq DoubleType.arrayLoad() = Bytecode.DALOAD;
257      eq ByteType.arrayLoad() = Bytecode.BALOAD;
258      eq CharType.arrayLoad() = Bytecode.CALOAD;
259      eq ShortType.arrayLoad() = Bytecode.SALOAD;
260      eq BooleanType.arrayLoad() = Bytecode.BALOAD;
261    
262      public void TypeDecl.emitLoadLocal(CodeGeneration gen, int pos) {error();}
263      public void PrimitiveType.emitLoadLocal(CodeGeneration gen, int pos) {
264        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
265        if (pos == 0) {
266          gen.emit(Bytecode.ILOAD_0);
267        } else if (pos == 1) {
268          gen.emit(Bytecode.ILOAD_1);
269        } else if (pos == 2) {
270          gen.emit(Bytecode.ILOAD_2);
271        } else if (pos == 3) {
272          gen.emit(Bytecode.ILOAD_3);
273        } else if (pos < 256) {
274          gen.emit(Bytecode.ILOAD).add(pos);
275        } else {
276          gen.emit(Bytecode.WIDE).emit(Bytecode.ILOAD).add2(pos);
277        }
278      }
279      public void LongType.emitLoadLocal(CodeGeneration gen, int pos) {
280        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
281        if (pos == 0) {
282          gen.emit(Bytecode.LLOAD_0);
283        } else if (pos == 1) {
284          gen.emit(Bytecode.LLOAD_1);
285        } else if (pos == 2) {
286          gen.emit(Bytecode.LLOAD_2);
287        } else if (pos == 3) {
288          gen.emit(Bytecode.LLOAD_3);
289        } else if (pos < 256) {
290          gen.emit(Bytecode.LLOAD).add(pos);
291        } else {
292          gen.emit(Bytecode.WIDE).emit(Bytecode.LLOAD).add2(pos);
293        }
294      }
295      public void FloatType.emitLoadLocal(CodeGeneration gen, int pos) {
296        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
297        if (pos == 0) {
298          gen.emit(Bytecode.FLOAD_0);
299        } else if (pos == 1) {
300          gen.emit(Bytecode.FLOAD_1);
301        } else if (pos == 2) {
302          gen.emit(Bytecode.FLOAD_2);
303        } else if (pos == 3) {
304          gen.emit(Bytecode.FLOAD_3);
305        } else if (pos < 256) {
306          gen.emit(Bytecode.FLOAD).add(pos);
307        } else {
308          gen.emit(Bytecode.WIDE).emit(Bytecode.FLOAD).add2(pos);
309        }
310      }
311      public void DoubleType.emitLoadLocal(CodeGeneration gen, int pos) {
312        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
313        if (pos == 0) {
314          gen.emit(Bytecode.DLOAD_0);
315        } else if (pos == 1) {
316          gen.emit(Bytecode.DLOAD_1);
317        } else if (pos == 2) {
318          gen.emit(Bytecode.DLOAD_2);
319        } else if (pos == 3) {
320          gen.emit(Bytecode.DLOAD_3);
321        } else if (pos < 256) {
322          gen.emit(Bytecode.DLOAD).add(pos);
323        } else {
324          gen.emit(Bytecode.WIDE).emit(Bytecode.DLOAD).add2(pos);
325        }
326      }
327      public void ReferenceType.emitLoadLocal(CodeGeneration gen, int pos) {
328        gen.emitLoadReference(pos);
329      }
330      public void NullType.emitLoadLocal(CodeGeneration gen, int pos) {
331        gen.emitLoadReference(pos);
332      }
333    
334      public void FieldDeclaration.emitLoadField(CodeGeneration gen, TypeDecl typeDecl) {
335        if (hostType().isArrayDecl() && name().equals("length")) {
336          gen.emit(Bytecode.ARRAYLENGTH);
337          return;
338        }
339        String classname = typeDecl.constantPoolName();
340        String      desc = type().typeDescriptor();
341        String      name = name();
342        int index = gen.constantPool().addFieldref(classname, name, desc);
343        if (isStatic()) {
344          gen.emit(Bytecode.GETSTATIC, type().variableSize()).add2(index);
345        } else {
346          gen.emit(Bytecode.GETFIELD, type().variableSize() - 1).add2(index);
347        }
348      }
349    
350    
351      // emit store
352    
353      public void Expr.emitStore(CodeGeneration gen) { error("emitStore called with " + getClass().getName()); }
354      public void AbstractDot.emitStore(CodeGeneration gen) { lastAccess().emitStore(gen); }
355    
356      public void VarAccess.emitStore(CodeGeneration gen) {
357        Variable v = decl();
358        if (v instanceof VariableDeclaration) {
359          VariableDeclaration decl = (VariableDeclaration) v;
360          if (isDUbefore(v)) {
361             gen.addLocalVariableEntryAtCurrentPC(decl.name(), decl.type().typeDescriptor(), decl.localNum(), decl.variableScopeEndLabel(gen));
362          }
363          decl.type().emitStoreLocal(gen, decl.localNum());
364        } else if (v instanceof ParameterDeclaration) {
365          ParameterDeclaration decl = (ParameterDeclaration) v;
366          decl.type().emitStoreLocal(gen, decl.localNum());
367        } else if (v instanceof FieldDeclaration) {
368          FieldDeclaration f = (FieldDeclaration) v;
369          if (f.isPrivate() && !hostType().hasField(v.name())) {
370            f.createAccessorWrite(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType());
371          } else {
372            f.emitStoreField(gen, fieldQualifierType());
373          }
374        }
375      }
376    
377      public void ArrayAccess.emitStore(CodeGeneration gen) {
378        gen.emit(type().arrayStore());
379      }
380      syn byte TypeDecl.arrayStore() {
381        throw new Error("Cannot create array load for TypeDecl");
382      }
383      eq ReferenceType.arrayStore() = Bytecode.AASTORE;
384      eq IntType.arrayStore() = Bytecode.IASTORE;
385      eq LongType.arrayStore() = Bytecode.LASTORE;
386      eq FloatType.arrayStore() = Bytecode.FASTORE;
387      eq DoubleType.arrayStore() = Bytecode.DASTORE;
388      eq ByteType.arrayStore() = Bytecode.BASTORE;
389      eq CharType.arrayStore() = Bytecode.CASTORE;
390      eq ShortType.arrayStore() = Bytecode.SASTORE;
391      eq BooleanType.arrayStore() = Bytecode.BASTORE;
392    
393      public void FieldDeclaration.emitStoreField(CodeGeneration gen, TypeDecl typeDecl) {
394        String classname = typeDecl.constantPoolName();
395        String      desc = type().typeDescriptor();
396        String      name = name();
397        int index = gen.constantPool().addFieldref(classname, name, desc);
398        if (isStatic()) {
399          gen.emit(Bytecode.PUTSTATIC, -type().variableSize()).add2(index);
400        } else {
401          gen.emit(Bytecode.PUTFIELD, -type().variableSize() - 1).add2(index);
402        }
403      }
404    
405      public void TypeDecl.emitStoreLocal(CodeGeneration gen, int pos) {error();}
406      public void PrimitiveType.emitStoreLocal(CodeGeneration gen, int pos) {
407        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
408        if (pos == 0) {
409          gen.emit(Bytecode.ISTORE_0);
410        } else if (pos == 1) {
411          gen.emit(Bytecode.ISTORE_1);
412        } else if (pos == 2) {
413          gen.emit(Bytecode.ISTORE_2);
414        } else if (pos == 3) {
415          gen.emit(Bytecode.ISTORE_3);
416        } else if (pos < 256) {
417          gen.emit(Bytecode.ISTORE).add(pos);
418        } else {
419          gen.emit(Bytecode.WIDE).emit(Bytecode.ISTORE).add2(pos);
420        }
421      }
422      public void LongType.emitStoreLocal(CodeGeneration gen, int pos) {
423        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
424        if (pos == 0) {
425          gen.emit(Bytecode.LSTORE_0);
426        } else if (pos == 1) {
427          gen.emit(Bytecode.LSTORE_1);
428        } else if (pos == 2) {
429          gen.emit(Bytecode.LSTORE_2);
430        } else if (pos == 3) {
431          gen.emit(Bytecode.LSTORE_3);
432        } else if (pos < 256) {
433          gen.emit(Bytecode.LSTORE).add(pos);
434        } else {
435          gen.emit(Bytecode.WIDE).emit(Bytecode.LSTORE).add2(pos);
436        }
437      }
438      public void FloatType.emitStoreLocal(CodeGeneration gen, int pos) {
439        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
440        if (pos == 0) {
441          gen.emit(Bytecode.FSTORE_0);
442        } else if (pos == 1) {
443          gen.emit(Bytecode.FSTORE_1);
444        } else if (pos == 2) {
445          gen.emit(Bytecode.FSTORE_2);
446        } else if (pos == 3) {
447          gen.emit(Bytecode.FSTORE_3);
448        } else if (pos < 256) {
449          gen.emit(Bytecode.FSTORE).add(pos);
450        } else {
451          gen.emit(Bytecode.WIDE).emit(Bytecode.FSTORE).add2(pos);
452        }
453      }
454      public void DoubleType.emitStoreLocal(CodeGeneration gen, int pos) {
455        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
456        if (pos == 0) {
457          gen.emit(Bytecode.DSTORE_0);
458        } else if (pos == 1) {
459          gen.emit(Bytecode.DSTORE_1);
460        } else if (pos == 2) {
461          gen.emit(Bytecode.DSTORE_2);
462        } else if (pos == 3) {
463          gen.emit(Bytecode.DSTORE_3);
464        } else if (pos < 256) {
465          gen.emit(Bytecode.DSTORE).add(pos);
466        } else {
467          gen.emit(Bytecode.WIDE).emit(Bytecode.DSTORE).add2(pos);
468        }
469      }
470      public void ReferenceType.emitStoreLocal(CodeGeneration gen, int pos) {
471        gen.emitStoreReference(pos);
472      }
473      public void NullType.emitStoreLocal(CodeGeneration gen, int pos) {
474        gen.emitStoreReference(pos);
475      }
476    
477      // exceptions
478    
479      inh TypeDecl TryStmt.typeThrowable();
480    
481      public void TypeDecl.emitDup(CodeGeneration gen)      { gen.emit(Bytecode.DUP); }
482      public void VoidType.emitDup(CodeGeneration gen)      { }
483      public void DoubleType.emitDup(CodeGeneration gen)    { gen.emit(Bytecode.DUP2); }
484      public void LongType.emitDup(CodeGeneration gen)      { gen.emit(Bytecode.DUP2); }
485    
486      public void TypeDecl.emitDup_x1(CodeGeneration gen)   { gen.emit(Bytecode.DUP_X1); }
487      public void VoidType.emitDup_x1(CodeGeneration gen)   { }
488      public void DoubleType.emitDup_x1(CodeGeneration gen) { gen.emit(Bytecode.DUP2_X1); }
489      public void LongType.emitDup_x1(CodeGeneration gen)   { gen.emit(Bytecode.DUP2_X1); }
490    
491      public void TypeDecl.emitDup_x2(CodeGeneration gen)   { gen.emit(Bytecode.DUP_X2); }
492      public void VoidType.emitDup_x2(CodeGeneration gen)   { }
493      public void DoubleType.emitDup_x2(CodeGeneration gen) { gen.emit(Bytecode.DUP2_X2); }
494      public void LongType.emitDup_x2(CodeGeneration gen)   { gen.emit(Bytecode.DUP2_X2); }
495    
496      public void TypeDecl.emitPop(CodeGeneration gen)      { gen.emit(Bytecode.POP); }
497      public void VoidType.emitPop(CodeGeneration gen)      { }
498      public void DoubleType.emitPop(CodeGeneration gen)    { gen.emit(Bytecode.POP2); }
499      public void LongType.emitPop(CodeGeneration gen)      { gen.emit(Bytecode.POP2); }
500    
501    
502      // emitInvoke
503    
504      public void MethodDecl.emitInvokeMethod(CodeGeneration gen, TypeDecl hostType) {
505        if (hostType.isInterfaceDecl()) {
506          String classname = hostType.constantPoolName();
507          String      desc = descName();
508          String      name = name();
509          int index = gen.constantPool().addInterfaceMethodref(classname, name, desc);
510          int numArg = 1; // instance
511          for (int i = 0; i < getNumParameter(); i++) {
512            numArg += getParameter(i).type().variableSize();
513          }
514          int stackChange = type().variableSize() - numArg;
515          gen.emit(Bytecode.INVOKEINTERFACE, stackChange)
516                .add2(index).add(numArg).add(0);
517        } else {
518          String classname = hostType.constantPoolName();
519          String      desc = descName();
520          String      name = name();
521          int index = gen.constantPool().addMethodref(classname, name, desc);
522          int stackChange = type().variableSize();
523          for (int i = 0; i < getNumParameter(); i++) {
524              stackChange -= getParameter(i).type().variableSize();
525          }
526          if (isStatic()) {
527            gen.emit(Bytecode.INVOKESTATIC, stackChange).add2(index);
528          } else {
529            stackChange -= 1;
530            gen.emit(Bytecode.INVOKEVIRTUAL, stackChange).add2(index);
531          }
532        }
533      }
534    
535      public void MethodDecl.emitInvokeSpecialMethod(CodeGeneration gen, TypeDecl hostType) {
536        String classname = hostType.constantPoolName();
537        String      desc = descName();
538        String      name = name();
539        int index = gen.constantPool().addMethodref(classname, name, desc);
540        int stackChange = type().variableSize() - 1;
541        for (int i = 0; i < getNumParameter(); i++) {
542          stackChange -= getParameter(i).type().variableSize();
543        }
544        gen.emit(Bytecode.INVOKESPECIAL, stackChange).add2(index);
545      }
546    
547      public void ConstructorDecl.emitInvokeConstructor(CodeGeneration gen) {
548        int stackChange = -1;
549        for (int i = 0; i < getNumParameter(); i++) {
550          stackChange -= getParameter(i).type().variableSize();
551        }
552        if (hostType().needsEnclosing()) {
553          stackChange -= 1;
554        }
555        if (hostType().needsSuperEnclosing()) {
556          stackChange -= 1;
557        }
558        String classname = hostType().constantPoolName();
559        String      desc = descName();
560        String      name = "<init>";
561        int index = gen.constantPool().addMethodref(classname, name, desc);
562        gen.emit(Bytecode.INVOKESPECIAL, stackChange).add2(index);
563      }
564    
565      // emitNew
566    
567      public void TypeDecl.emitNew(CodeGeneration gen) {
568        int index = gen.constantPool().addClass(constantPoolName());
569        gen.emit(Bytecode.NEW).add2(index);
570      }
571    }
572    aspect CodeGenerationConversions {
573      void TypeDecl.emitAssignConvTo(CodeGeneration gen, TypeDecl type) {
574        if (!type.isIntegralType() || !isIntegralType() || type.isLong()) {
575          emitCastTo(gen, type);
576        }
577      }
578    
579      void TypeDecl.emitCastTo(CodeGeneration gen, TypeDecl type) { throw new Error("CastTo not implemented for " + getClass().getName()); }
580      void ReferenceType.emitCastTo(CodeGeneration gen, TypeDecl type) { if (!instanceOf(type) && !type.isNull()) gen.emitCheckCast(type); }
581      void IntType.emitCastTo(CodeGeneration gen, TypeDecl type)      { type.intToThis(gen); }
582      void FloatType.emitCastTo(CodeGeneration gen, TypeDecl type)    { type.floatToThis(gen); }
583      void DoubleType.emitCastTo(CodeGeneration gen, TypeDecl type)   { type.doubleToThis(gen); }
584      void LongType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.longToThis(gen); }
585      void ByteType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.byteToThis(gen); }
586      void ShortType.emitCastTo(CodeGeneration gen, TypeDecl type)    { type.shortToThis(gen); }
587      void CharType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.charToThis(gen); }
588      void BooleanType.emitCastTo(CodeGeneration gen, TypeDecl type)  { }
589      void NullType.emitCastTo(CodeGeneration gen, TypeDecl type)     { }
590    
591      void TypeDecl.intToThis(CodeGeneration gen) { throw new Error("intToThis not implemented for " + getClass().getName()); }
592      void IntType.intToThis(CodeGeneration gen)    { }
593      void LongType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2L); }
594      void FloatType.intToThis(CodeGeneration gen)  { gen.emit(Bytecode.I2F); }
595      void DoubleType.intToThis(CodeGeneration gen) { gen.emit(Bytecode.I2D); }
596      void ByteType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2B); }
597      void CharType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2C); }
598      void ShortType.intToThis(CodeGeneration gen)  { gen.emit(Bytecode.I2S); }
599    
600      void TypeDecl.floatToThis(CodeGeneration gen) { throw new Error("floatToThis not implemented for " + getClass().getName()); }
601      void IntType.floatToThis(CodeGeneration gen)    { gen.emit(Bytecode.F2I); }
602      void ByteType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2I).emit(Bytecode.I2B); }
603      void ShortType.floatToThis(CodeGeneration gen)  { gen.emit(Bytecode.F2I).emit(Bytecode.I2S); }
604      void CharType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2I).emit(Bytecode.I2C); }
605      void FloatType.floatToThis(CodeGeneration gen)  { }
606      void LongType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2L); }
607      void DoubleType.floatToThis(CodeGeneration gen) { gen.emit(Bytecode.F2D); }
608    
609      void TypeDecl.doubleToThis(CodeGeneration gen) { throw new Error("doubleToThis not implemented for " + getClass().getName()); }
610      void IntType.doubleToThis(CodeGeneration gen)    { gen.emit(Bytecode.D2I); }
611      void ByteType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2I).emit(Bytecode.I2B); }
612      void ShortType.doubleToThis(CodeGeneration gen)  { gen.emit(Bytecode.D2I).emit(Bytecode.I2S); }
613      void CharType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2I).emit(Bytecode.I2C); }
614      void FloatType.doubleToThis(CodeGeneration gen)  { gen.emit(Bytecode.D2F); }
615      void LongType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2L); }
616      void DoubleType.doubleToThis(CodeGeneration gen) { }
617    
618      void TypeDecl.longToThis(CodeGeneration gen) { throw new Error("longToThis not implemented for " + getClass().getName()); }
619      void IntType.longToThis(CodeGeneration gen)    { gen.emit(Bytecode.L2I); }
620      void ByteType.longToThis(CodeGeneration gen)   { gen.emit(Bytecode.L2I).emit(Bytecode.I2B); }
621      void ShortType.longToThis(CodeGeneration gen)  { gen.emit(Bytecode.L2I).emit(Bytecode.I2S); }
622      void CharType.longToThis(CodeGeneration gen)   { gen.emit(Bytecode.L2I).emit(Bytecode.I2C); }
623      void FloatType.longToThis(CodeGeneration gen)  { gen.emit(Bytecode.L2F); }
624      void LongType.longToThis(CodeGeneration gen)   { }
625      void DoubleType.longToThis(CodeGeneration gen) { gen.emit(Bytecode.L2D); }
626    
627      void TypeDecl.byteToThis(CodeGeneration gen) { throw new Error("byteToThis not implemented for " + getClass().getName()); }
628      void IntegralType.byteToThis(CodeGeneration gen) { }
629      void CharType.byteToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2C); }
630      void FloatType.byteToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
631      void LongType.byteToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
632      void DoubleType.byteToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D);}
633    
634      void TypeDecl.charToThis(CodeGeneration gen) { throw new Error("charToThis not implemented for " + getClass().getName()); }
635      void IntegralType.charToThis(CodeGeneration gen) { }
636      void ByteType.charToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2B); }
637      void ShortType.charToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2S); }
638      void FloatType.charToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
639      void LongType.charToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
640      void DoubleType.charToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D);}
641    
642      void TypeDecl.shortToThis(CodeGeneration gen) { throw new Error("shortToThis not implemented for " + getClass().getName()); }
643      void IntegralType.shortToThis(CodeGeneration gen) { }
644      void ByteType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2B); }
645      void CharType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2C); }
646      void FloatType.shortToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
647      void LongType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
648      void DoubleType.shortToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D); }
649    
650    }
651    
652    aspect CodeGenerationBinaryOperations {
653      // emit the desired operation on the operand(s) on the stack
654      void Expr.emitOperation(CodeGeneration gen) {error();}
655      // unary
656      void MinusExpr.emitOperation(CodeGeneration gen)  { type().neg(gen); }
657      void PlusExpr.emitOperation(CodeGeneration gen)   { }
658      void BitNotExpr.emitOperation(CodeGeneration gen) { type().bitNot(gen); }
659      void LogNotExpr.emitOperation(CodeGeneration gen) { type().logNot(gen); }
660    
661      // binary
662      void AddExpr.emitOperation(CodeGeneration gen) { type().add(gen); }
663      void SubExpr.emitOperation(CodeGeneration gen) { type().sub(gen); }
664      void MulExpr.emitOperation(CodeGeneration gen) { type().mul(gen); }
665      void DivExpr.emitOperation(CodeGeneration gen) { type().div(gen); }
666      void ModExpr.emitOperation(CodeGeneration gen) { type().rem(gen); }
667    
668      void LShiftExpr.emitOperation(CodeGeneration gen)     { type().shl(gen); }
669      void RShiftExpr.emitOperation(CodeGeneration gen)     { type().shr(gen); }
670      void URShiftExpr.emitOperation(CodeGeneration gen)    { type().ushr(gen); }
671      void OrBitwiseExpr.emitOperation(CodeGeneration gen)  { type().bitor(gen); }
672      void AndBitwiseExpr.emitOperation(CodeGeneration gen) { type().bitand(gen); }
673      void XorBitwiseExpr.emitOperation(CodeGeneration gen) { type().bitxor(gen); }
674    
675      void TypeDecl.neg(CodeGeneration gen) { error(); }
676      void IntegralType.neg(CodeGeneration gen) { gen.emit(Bytecode.INEG); }
677      void LongType.neg(CodeGeneration gen)     { gen.emit(Bytecode.LNEG); }
678      void FloatType.neg(CodeGeneration gen)    { gen.emit(Bytecode.FNEG); }
679      void DoubleType.neg(CodeGeneration gen)   { gen.emit(Bytecode.DNEG); }
680    
681      void TypeDecl.bitNot(CodeGeneration gen) { error(); }
682      void IntegralType.bitNot(CodeGeneration gen) { gen.emit(Bytecode.ICONST_M1).emit(Bytecode.IXOR); }
683      void LongType.bitNot(CodeGeneration gen)     { emitPushConstant(gen, -1); gen.emit(Bytecode.LXOR); }
684    
685      void TypeDecl.logNot(CodeGeneration gen) { error();}
686      void BooleanType.logNot(CodeGeneration gen) { gen.emit(Bytecode.ICONST_1).emit(Bytecode.IXOR); }
687    
688      void TypeDecl.add(CodeGeneration gen) {error();}
689      void LongType.add(CodeGeneration gen) {gen.emit(Bytecode.LADD);}
690      void FloatType.add(CodeGeneration gen) {gen.emit(Bytecode.FADD);}
691      void DoubleType.add(CodeGeneration gen) {gen.emit(Bytecode.DADD);}
692      void IntegralType.add(CodeGeneration gen) {gen.emit(Bytecode.IADD);}
693    
694      void TypeDecl.sub(CodeGeneration gen) {error();}
695      void LongType.sub(CodeGeneration gen) {gen.emit(Bytecode.LSUB);}
696      void FloatType.sub(CodeGeneration gen) {gen.emit(Bytecode.FSUB);}
697      void DoubleType.sub(CodeGeneration gen) {gen.emit(Bytecode.DSUB);}
698      void IntegralType.sub(CodeGeneration gen) {gen.emit(Bytecode.ISUB);}
699    
700      void TypeDecl.mul(CodeGeneration gen) {error();}
701      void LongType.mul(CodeGeneration gen) {gen.emit(Bytecode.LMUL);}
702      void FloatType.mul(CodeGeneration gen) {gen.emit(Bytecode.FMUL);}
703      void DoubleType.mul(CodeGeneration gen) {gen.emit(Bytecode.DMUL);}
704      void IntegralType.mul(CodeGeneration gen) {gen.emit(Bytecode.IMUL);}
705    
706      void TypeDecl.div(CodeGeneration gen) {error();}
707      void LongType.div(CodeGeneration gen) {gen.emit(Bytecode.LDIV);}
708      void FloatType.div(CodeGeneration gen) {gen.emit(Bytecode.FDIV);}
709      void DoubleType.div(CodeGeneration gen) {gen.emit(Bytecode.DDIV);}
710      void IntegralType.div(CodeGeneration gen) {gen.emit(Bytecode.IDIV);}
711    
712      void TypeDecl.rem(CodeGeneration gen) {error();}
713      void LongType.rem(CodeGeneration gen) {gen.emit(Bytecode.LREM);}
714      void FloatType.rem(CodeGeneration gen) {gen.emit(Bytecode.FREM);}
715      void DoubleType.rem(CodeGeneration gen) {gen.emit(Bytecode.DREM);}
716      void IntegralType.rem(CodeGeneration gen) {gen.emit(Bytecode.IREM);}
717    
718      void TypeDecl.shl(CodeGeneration gen) {error();}
719      void LongType.shl(CodeGeneration gen) {gen.emit(Bytecode.LSHL);}
720      void IntegralType.shl(CodeGeneration gen) {gen.emit(Bytecode.ISHL);}
721    
722      void TypeDecl.shr(CodeGeneration gen) {error();}
723      void LongType.shr(CodeGeneration gen) {gen.emit(Bytecode.LSHR);}
724      void IntegralType.shr(CodeGeneration gen) {gen.emit(Bytecode.ISHR);}
725    
726      void TypeDecl.ushr(CodeGeneration gen) {error();}
727      void LongType.ushr(CodeGeneration gen) {gen.emit(Bytecode.LUSHR);}
728      void IntegralType.ushr(CodeGeneration gen) {gen.emit(Bytecode.IUSHR);}
729    
730      void TypeDecl.bitand(CodeGeneration gen) {error();}
731      void LongType.bitand(CodeGeneration gen) {gen.emit(Bytecode.LAND);}
732      void IntegralType.bitand(CodeGeneration gen) {gen.emit(Bytecode.IAND);}
733      void BooleanType.bitand(CodeGeneration gen) {gen.emit(Bytecode.IAND);}
734    
735      void TypeDecl.bitor(CodeGeneration gen) {error();}
736      void LongType.bitor(CodeGeneration gen) {gen.emit(Bytecode.LOR);}
737      void IntegralType.bitor(CodeGeneration gen) {gen.emit(Bytecode.IOR);}
738      void BooleanType.bitor(CodeGeneration gen) {gen.emit(Bytecode.IOR);}
739    
740      void TypeDecl.bitxor(CodeGeneration gen) {error();}
741      void LongType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.LXOR);}
742      void IntegralType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.IXOR);}
743      void BooleanType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.IXOR);}
744    }
745    
746    aspect CodeGenerationBranch {
747      public void TypeDecl.branchLT(CodeGeneration gen, int label) { throw new Error("branchLT not supported for " + getClass().getName()); }
748      public void DoubleType.branchLT(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFLT, label); }
749      public void FloatType.branchLT(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFLT, label); }
750      public void LongType.branchLT(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFLT, label); }
751      public void IntegralType.branchLT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLT, label); }
752    
753      public void TypeDecl.branchLTInv(CodeGeneration gen, int label)   { branchLT(gen, label); }
754      public void DoubleType.branchLTInv(CodeGeneration gen, int label) { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFLT, label); }
755      public void FloatType.branchLTInv(CodeGeneration gen, int label)  { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFLT, label); }
756    
757      public void TypeDecl.branchLE(CodeGeneration gen, int label) { throw new Error("branchLE not supported for " + getClass().getName()); }
758      public void DoubleType.branchLE(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFLE, label); }
759      public void FloatType.branchLE(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFLE, label); }
760      public void LongType.branchLE(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFLE, label); }
761      public void IntegralType.branchLE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLE, label); }
762    
763      public void TypeDecl.branchLEInv(CodeGeneration gen, int label)   { branchLE(gen, label); }
764      public void DoubleType.branchLEInv(CodeGeneration gen, int label) { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFLE, label); }
765      public void FloatType.branchLEInv(CodeGeneration gen, int label)  { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFLE, label); }
766    
767      public void TypeDecl.branchGE(CodeGeneration gen, int label) { throw new Error("branchGE not supported for " + getClass().getName()); }
768      public void DoubleType.branchGE(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFGE, label); }
769      public void FloatType.branchGE(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFGE, label); }
770      public void LongType.branchGE(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFGE, label); }
771      public void IntegralType.branchGE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGE, label); }
772    
773      public void TypeDecl.branchGEInv(CodeGeneration gen, int label)   { branchGE(gen, label); }
774      public void DoubleType.branchGEInv(CodeGeneration gen, int label) { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFGE, label); }
775      public void FloatType.branchGEInv(CodeGeneration gen, int label)  { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFGE, label); }
776    
777      public void TypeDecl.branchGT(CodeGeneration gen, int label) { throw new Error("branchGT not supported for " + getClass().getName()); }
778      public void DoubleType.branchGT(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFGT, label); }
779      public void FloatType.branchGT(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFGT, label); }
780      public void LongType.branchGT(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFGT, label); }
781      public void IntegralType.branchGT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGT, label); }
782    
783      public void TypeDecl.branchGTInv(CodeGeneration gen, int label)   { branchGT(gen, label); }
784      public void DoubleType.branchGTInv(CodeGeneration gen, int label) { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFGT, label); }
785      public void FloatType.branchGTInv(CodeGeneration gen, int label)  { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFGT, label); }
786    
787      public void TypeDecl.branchEQ(CodeGeneration gen, int label) { throw new Error("branchEQ not supported for " + getClass().getName()); }
788      public void DoubleType.branchEQ(CodeGeneration gen, int label)    { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFEQ, label); }
789      public void FloatType.branchEQ(CodeGeneration gen, int label)     { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFEQ, label); }
790      public void LongType.branchEQ(CodeGeneration gen, int label)      { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFEQ, label); }
791      public void IntegralType.branchEQ(CodeGeneration gen, int label)  { gen.emitCompare(Bytecode.IF_ICMPEQ, label); }
792      public void BooleanType.branchEQ(CodeGeneration gen, int label)   { gen.emitCompare(Bytecode.IF_ICMPEQ, label); }
793      public void ReferenceType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPEQ, label); }
794      public void NullType.branchEQ(CodeGeneration gen, int label)      { gen.emitCompare(Bytecode.IF_ACMPEQ, label); }
795    
796      public void TypeDecl.branchNE(CodeGeneration gen, int label) { throw new Error("branchNE not supported for " + getClass().getName()); }
797      public void DoubleType.branchNE(CodeGeneration gen, int label)    { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFNE, label); }
798      public void FloatType.branchNE(CodeGeneration gen, int label)     { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFNE, label); }
799      public void LongType.branchNE(CodeGeneration gen, int label)      { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFNE, label); }
800      public void IntegralType.branchNE(CodeGeneration gen, int label)  { gen.emitCompare(Bytecode.IF_ICMPNE, label); }
801      public void BooleanType.branchNE(CodeGeneration gen, int label)   { gen.emitCompare(Bytecode.IF_ICMPNE, label); }
802      public void ReferenceType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPNE, label); }
803      public void NullType.branchNE(CodeGeneration gen, int label)      { gen.emitCompare(Bytecode.IF_ACMPNE, label); }
804    }