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    aspect CodeGeneration {
011      public void ASTNode.setSourceLineNumber(int i) {
012        setStart(ASTNode.makePosition(i, 1));
013      }
014      
015      syn int ASTNode.sourceLineNumber() = getStart() != 0 ? getLine(getStart()) : -1;
016      eq ReturnStmt.sourceLineNumber() {
017        int num = super.sourceLineNumber();
018        if(num != -1)
019          return num;
020        if(hasResult()) {
021          num = getResult().findFirstSourceLineNumber();
022          if(num != -1)
023            return num;
024        }
025        return getLine(getParent().getParent().getEnd());
026      }
027      eq ExprStmt.sourceLineNumber() = getExpr().findFirstSourceLineNumber();
028      eq Access.sourceLineNumber() = findFirstSourceLineNumber();
029    
030      protected int ASTNode.findFirstSourceLineNumber() {
031        if(getStart() != 0)
032          return getLine(getStart());
033        for(int i = 0; i < getNumChild(); i++) {
034          int num = getChild(i).findFirstSourceLineNumber();
035          if(num != -1)
036            return num;
037        }
038        return -1;
039      }
040    
041    
042      inh int VariableDeclaration.variableScopeEndLabel(CodeGeneration gen);
043      syn lazy int Block.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel();
044      eq Block.getStmt(int i).variableScopeEndLabel(CodeGeneration gen) = variableScopeEndLabel(gen);
045      syn lazy int ForStmt.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel();
046      eq ForStmt.getInitStmt(int i).variableScopeEndLabel(CodeGeneration gen) = variableScopeEndLabel(gen);
047      eq Program.getChild(int i).variableScopeEndLabel(CodeGeneration gen) {
048        throw new Error("variableScopeEndLabel not valid from here");
049      }
050      
051      class CodeGeneration {
052        private ByteArray bytes = new ByteArray();
053        private ConstantPool constantPool;
054    
055        public void clearCodeGeneration() {
056          bytes = null;
057          constantPool = null;
058          variableScopeLabelAddress = null;
059          variableScopeLabelUses = null;
060          localVariableTable = null;
061          lineNumberTable = null;
062          exceptions = null;
063          address = null;
064          uses = null;
065        }
066        
067        private boolean wideGoto = false;
068    
069        private boolean numberFormatError = false;
070        public boolean numberFormatError() { return numberFormatError; }
071    
072        public CodeGeneration(ConstantPool constantPool) {
073          this.constantPool = constantPool;
074        }
075    
076        public CodeGeneration(ConstantPool constantPool, boolean wideGoto) {
077          this.constantPool = constantPool;
078          this.wideGoto = wideGoto;
079        }
080    
081        public ConstantPool constantPool() {
082          return constantPool;
083        }
084        
085        private int variableScopeLabel = 1;
086        public int variableScopeLabel() {
087          return variableScopeLabel++;
088        }
089        public void addVariableScopeLabel(int label) {
090          Integer label_object = new Integer(label);
091          variableScopeLabelAddress.put(label_object, new Integer(pos()));
092          // Update all reference to this label
093          if(variableScopeLabelUses.containsKey(label_object)) {
094            ArrayList array = (ArrayList)variableScopeLabelUses.get(label_object);
095            for(Iterator iter = array.iterator(); iter.hasNext(); ) {
096              LocalVariableEntry e = (LocalVariableEntry)iter.next();
097              e.length = pos() - e.start_pc;
098            }
099          }
100        } 
101        private HashMap variableScopeLabelAddress = new HashMap();
102        private HashMap variableScopeLabelUses = new HashMap();
103    
104        class LocalVariableEntry {
105          int start_pc;
106          int length;
107          int name_index;
108          int descriptor_index;
109          int index;
110        }
111        public Collection localVariableTable = new ArrayList();
112        public void addLocalVariableEntryAtCurrentPC(String name, String typeDescriptor, int localNum, int variableScopeEndLabel) {
113          LocalVariableEntry e = new LocalVariableEntry();
114          e.start_pc = pos();
115          e.length = 0;
116          e.name_index = constantPool().addUtf8(name);
117          e.descriptor_index = constantPool().addUtf8(typeDescriptor);
118          e.index = localNum;
119          localVariableTable.add(e);
120          Integer label_object = new Integer(variableScopeEndLabel);
121          if(!variableScopeLabelUses.containsKey(label_object))
122            variableScopeLabelUses.put(label_object, new ArrayList());
123          Collection c = (Collection)variableScopeLabelUses.get(label_object);
124          c.add(e);
125        }
126    
127        // at each variable declaration and parameter declaration
128        // inh int VariableDeclaration.variableScopeEndLabel(CodeGeneration gen); 
129        // addLocalVariableEntryAtCurrentPC(this, variableScopeEndLabel());
130        // syn lazy int Block.variableScopeEndLabel(CodeGeneration gen) = gen.variableScopeLabel();
131        //  Block.createBCode() { ... gen.addLabel(variableScopeLabel());
132        
133        class LineNumberEntry {
134          int start_pc;
135          int line_number;
136        }
137        public Collection lineNumberTable = new ArrayList();
138        public void addLineNumberEntryAtCurrentPC(ASTNode node) {
139          LineNumberEntry e = new LineNumberEntry();
140          e.start_pc = pos();
141          e.line_number = node.sourceLineNumber();
142          if(e.line_number != -1 && e.line_number != 65535)
143            lineNumberTable.add(e);
144        }
145        
146        public Collection exceptions = new ArrayList();
147        public void addException(int start_pc, int end_pc, int handler_pc, int catch_type) {
148          ExceptionEntry e = new ExceptionEntry();
149          e.start_pc = start_pc;
150          e.end_pc = end_pc;
151          e.handler_pc = handler_pc;
152          e.catch_type = catch_type;
153          if(e.start_pc != e.end_pc)
154            exceptions.add(e);
155        }
156        class ExceptionEntry {
157          int start_pc;
158          int end_pc;
159          int handler_pc;
160          int catch_type;
161        }
162        public void createExceptionTable(TryStmt tryStmt) {  
163          for(int i = 0; i < tryStmt.getNumCatchClause(); i++) {
164            tryStmt.getCatchClause(i).exceptionTableEntries(this, tryStmt);
165          }
166          if(tryStmt.hasFinally()) {
167            addException(
168                addressOf(tryStmt.label_begin()),
169                addressOf(tryStmt.label_finally()),
170                addressOf(tryStmt.label_exception_handler()),
171                0
172                );
173          }
174        }
175        public void createExceptionTable(SynchronizedStmt stmt) {  
176          addException(
177              addressOf(stmt.label_begin()),
178              addressOf(stmt.label_finally()),
179              addressOf(stmt.label_exception_handler()),
180              0
181              );
182        }
183    
184        public int maxLocals() {
185          return maxLocals+1;
186        }
187        int maxLocals = 0;
188    
189        /*
190        public int label() {
191          return labelCounter++;
192        }
193        private static int labelCounter = 1;
194        */
195        private HashMap address = new HashMap();
196        private HashMap uses = new HashMap();
197        public void addLabel(int label) {
198          Integer label_object = new Integer(label);
199          /*
200          if(pos() - 3 == bytes.lastGotoPos() && bytes.get(pos() - 3) == Bytecode.GOTO) {
201            if(uses.containsKey(label_object)) {
202              ArrayList array = (ArrayList)uses.get(label_object);
203              for(int i = 0; i < array.size(); i++) {
204                int p = ((Integer)array.get(i)).intValue();
205                if(pos() - 3 == p) {
206                  //System.out.println("Found direct branch");
207                  array.remove(i);
208                  i--;
209                }
210              }
211              bytes.setPos(pos() - 3);
212            }
213          }
214          */
215          address.put(label_object, new Integer(pos()));
216          // Update all reference to this label
217          if(uses.containsKey(label_object)) {
218            ArrayList array = (ArrayList)uses.get(label_object);
219            for(int i = 0; i < array.size(); i++) {
220              int p = ((Integer)array.get(i)).intValue();
221              if(bytes.get(p) == Bytecode.GOTO_W)
222                setAddress32(p + 1, pos() - p);
223              else
224                setAddress(p + 1, pos() -  p);
225            }
226          }
227        } 
228        public int addressOf(int label) {
229          Integer label_object = new Integer(label);
230          if(!address.containsKey(label_object))
231            throw new Error("Can not compute address of unplaced label");
232          return ((Integer)address.get(label_object)).intValue();
233        }
234        private int jump(int label) {
235          Integer label_object = new Integer(label);
236          if(!uses.containsKey(label_object))
237            uses.put(label_object, new ArrayList());
238          ArrayList a = (ArrayList)uses.get(label_object);
239          a.add(new Integer(pos())); // position of the 16-bits reference
240          Integer val = (Integer)address.get(label_object);
241          if(val != null)
242            return val.intValue() - pos();
243          return 0; // a position of 0 means not calculated yet
244        }
245        private void setAddress(int position, int address) {
246          if(address > Short.MAX_VALUE || address < Short.MIN_VALUE)
247            numberFormatError = true;
248          bytes.set(position + 0, (byte)((address&0xff00)>>8));
249          bytes.set(position + 1, (byte)(address&0xff));
250        }
251        private void setAddress32(int position, int address) {
252          bytes.set(position + 0, (byte)(address >> 24 & 0xff));
253          bytes.set(position + 1, (byte)(address >> 16 & 0xff));
254          bytes.set(position + 2, (byte)(address >> 8 & 0xff));
255          bytes.set(position + 3, (byte)(address & 0xff));
256        }
257    
258    
259        public void emitStoreReference(int pos) {
260          maxLocals = Math.max(maxLocals, pos+1);
261          if(pos == 0) emit(Bytecode.ASTORE_0);
262          else if(pos == 1) emit(Bytecode.ASTORE_1);
263          else if(pos == 2) emit(Bytecode.ASTORE_2);
264          else if(pos == 3) emit(Bytecode.ASTORE_3);
265          else if(pos < 256) emit(Bytecode.ASTORE).add(pos);
266          else emit(Bytecode.WIDE).emit(Bytecode.ASTORE).add2(pos);
267        }
268        public void emitLoadReference(int pos) {
269          maxLocals = Math.max(maxLocals, pos+1);
270          if(pos == 0) emit(Bytecode.ALOAD_0);
271          else if(pos == 1) emit(Bytecode.ALOAD_1);
272          else if(pos == 2) emit(Bytecode.ALOAD_2);
273          else if(pos == 3) emit(Bytecode.ALOAD_3);
274          else if(pos < 256) emit(Bytecode.ALOAD).add(pos);
275          else emit(Bytecode.WIDE).emit(Bytecode.ALOAD).add2(pos);
276        }
277    
278        public void emitReturn() {
279          bytes.emit(Bytecode.RETURN);
280        }      
281    
282        public void emitThrow() {
283          bytes.emit(Bytecode.ATHROW);
284        }
285    
286        public void emitInstanceof(TypeDecl type) {
287          int p = constantPool().addClass(type.isArrayDecl() ? type.typeDescriptor() : type.constantPoolName());
288          bytes.emit(Bytecode.INSTANCEOF).add2(p);
289        }
290        public void emitCheckCast(TypeDecl type) {
291          int p = constantPool().addClass(type.isArrayDecl() ? type.typeDescriptor() : type.constantPoolName());
292          bytes.emit(Bytecode.CHECKCAST).add2(p);
293        }
294    
295        public void emitDup() {
296          bytes.emit(Bytecode.DUP);
297        }
298        public void emitDup2() {
299          bytes.emit(Bytecode.DUP2);
300        }
301    
302        public void emitPop() {
303          bytes.emit(Bytecode.POP);
304        }
305        
306        public void emitSwap() {
307          bytes.emit(Bytecode.SWAP);
308        }
309    
310        public void emitBranchNonNull(int label) {
311          int p = jump(label);
312          bytes.emit(Bytecode.IFNONNULL).add2(p);
313        }
314    
315        public void emitGoto(int label) {
316          int p = jump(label);
317          if(wideGoto)
318            bytes.emitGoto(Bytecode.GOTO_W).add4(p);
319          else {
320            if(p > Short.MAX_VALUE || p < Short.MIN_VALUE)
321              numberFormatError = true;
322            bytes.emitGoto(Bytecode.GOTO).add2(p);
323          }
324        }
325    
326        public void emitJsr(int label) {
327          int p = jump(label);
328          bytes.emit(Bytecode.JSR).add2(p);
329        }
330    
331        public void emitCompare(byte bytecode, int label) {
332          int p = jump(label);
333          bytes.emit(bytecode).add2(p);
334        }
335    
336        public String toString() {
337          return bytes.toString();
338        }
339        public int size() {return bytes.size();}
340        public int pos() {return bytes.pos();}
341        public byte[] toArray() {return bytes.toArray();}
342        CodeGeneration add(int i) { return add((byte)i); }
343        CodeGeneration add(byte b) { bytes.add(b); return this; }
344        CodeGeneration add2(int index) {
345          bytes.add2(index);
346          return this; 
347        }
348        CodeGeneration add4(int index) {
349          bytes.add4(index);
350          return this;
351        }
352        CodeGeneration emit(byte b) {
353          bytes.emit(b);
354          return this;
355        }
356        CodeGeneration emit(byte b, int stackChange) {
357          bytes.emit(b, stackChange);
358          return this;
359        }
360        public int maxStackDepth() {
361          return bytes.maxStackDepth();
362        }
363        public int stackDepth() {
364          return bytes.stackDepth();
365        }
366        public void changeStackDepth(int i) {
367          bytes.changeStackDepth(i);
368        }
369      }
370      /*************************************************************
371       * Auxiliary class
372       *************************************************************/
373      class ByteArray {
374        private int stackDepth = 0;
375        private int maxStackDepth = 0;
376        private int size = 64;
377        private byte[] bytes = new byte[size];
378        private int pos = 0;
379        private int lastGotoPos = 0;
380        ByteArray add(int i) {return add((byte)i);}
381        ByteArray add(byte b) {
382          if(pos >= size) {
383            byte[] ba = new byte[size * 2];
384            System.arraycopy(bytes, 0, ba, 0, size);
385            size *= 2;
386            bytes = ba;
387          }
388          bytes[pos++] = b;
389          return this;
390        }
391        ByteArray add4(int i) { 
392          add(i >> 24 & 0xff);
393          add(i >> 16 & 0xff);
394          add(i >> 8 & 0xff);
395          add(i & 0xff);
396          return this;
397        }
398        ByteArray add2(int index) {
399          add(index >> 8 & 0xff);
400          add(index & 0xff);
401          return this;
402        }
403        ByteArray emit(byte b) {
404          changeStackDepth(BytecodeDebug.stackChange(b));
405          add(b);
406          return this;
407        }
408        ByteArray emitGoto(byte b) {
409          changeStackDepth(BytecodeDebug.stackChange(b));
410          lastGotoPos = pos;
411          add(b);
412          return this;
413        }
414        ByteArray emit(byte b, int stackChange) {
415          changeStackDepth(stackChange);
416          add(b);
417          return this;
418        }
419        
420        public int maxStackDepth() {
421          return maxStackDepth;
422        }
423        public int stackDepth() {
424          return stackDepth;
425        }
426        public void changeStackDepth(int i) {
427          stackDepth += i;
428          if(stackDepth > maxStackDepth)
429            maxStackDepth = stackDepth;
430        }
431        
432        public int pos() {return pos;}
433        public int lastGotoPos() {return lastGotoPos;}
434        public void setPos(int index) { pos = index; }
435        public int size() {return pos;}
436        public byte get(int index) {return bytes[index];}
437        public void set(int index, byte value) {bytes[index] = value;}
438        public String toString() {
439          StringBuffer b = new StringBuffer();
440          for(int i = 0; i < pos; i++) b.append(" " + bytes[i]);
441          return b.toString();
442        }
443        public byte[] toArray() {
444          byte[] b = new byte[pos];
445          System.arraycopy(bytes, 0, b, 0, pos);
446          return b;
447        }
448      }
449    
450      /*************************************************************
451       * Emit methods
452       *************************************************************/
453    
454      // push constants
455    
456      public static void IntegerLiteral.push(CodeGeneration gen, int value) {
457        switch(value) {
458          case -1:
459            gen.emit(Bytecode.ICONST_M1);
460            break;
461          case 0:
462            gen.emit(Bytecode.ICONST_0);
463            break;
464          case 1:
465            gen.emit(Bytecode.ICONST_1);
466            break;
467          case 2:
468            gen.emit(Bytecode.ICONST_2);
469            break;
470          case 3:
471            gen.emit(Bytecode.ICONST_3);
472            break;
473          case 4:
474            gen.emit(Bytecode.ICONST_4);
475            break;
476          case 5:
477            gen.emit(Bytecode.ICONST_5);
478            break;
479          default:
480            if(value >= -128 && value <= 127) {
481              gen.emit(Bytecode.BIPUSH).add(value);
482            }
483            else if(value >= -32768 && value <= 32767) {
484              gen.emit(Bytecode.SIPUSH).add2(value);
485            }
486            else {
487              int index = gen.constantPool().addConstant(value);
488              if(index < 256)
489                gen.emit(Bytecode.LDC).add(index);
490              else 
491                gen.emit(Bytecode.LDC_W).add2(index);
492            }
493        }
494      }
495      public static void LongLiteral.push(CodeGeneration gen, long value) {
496        if(value == 0)
497          gen.emit(Bytecode.LCONST_0);
498        else if(value == 1)
499          gen.emit(Bytecode.LCONST_1);
500        else {
501          int index = gen.constantPool().addConstant(value);
502          gen.emit(Bytecode.LDC2_W).add2(index);
503        }
504      }
505      public static void DoubleLiteral.push(CodeGeneration gen, double value) {
506        if(value == 0)
507          gen.emit(Bytecode.DCONST_0);
508        else if(value == 1)
509          gen.emit(Bytecode.DCONST_1);
510        else {
511          int index = gen.constantPool().addConstant(value);
512          gen.emit(Bytecode.LDC2_W).add2(index);
513        }
514      }
515      public static void FloatingPointLiteral.push(CodeGeneration gen, float value) {
516        if(value == 0)
517          gen.emit(Bytecode.FCONST_0);
518        else if(value == 1)
519          gen.emit(Bytecode.FCONST_1);
520        else if(value == 2)
521          gen.emit(Bytecode.FCONST_2);
522        else {
523          int index = gen.constantPool().addConstant(value);
524          if(index < 256)
525            gen.emit(Bytecode.LDC).add(index);
526          else
527            gen.emit(Bytecode.LDC_W).add2(index);
528        }
529      }
530      public static void StringLiteral.push(CodeGeneration gen, String value) {
531        int index = gen.constantPool().addConstant(value);
532        if(index < 256)
533          gen.emit(Bytecode.LDC).add(index);
534        else 
535          gen.emit(Bytecode.LDC_W).add2(index);
536      }
537    
538      public static void BooleanLiteral.push(CodeGeneration gen, boolean value) {
539        gen.emit(value ? Bytecode.ICONST_1 : Bytecode.ICONST_0);
540      }
541    
542      public void TypeDecl.emitPushConstant(CodeGeneration gen, int value) { }
543      public void IntegralType.emitPushConstant(CodeGeneration gen, int value) { IntegerLiteral.push(gen, value); }
544      public void LongType.emitPushConstant(CodeGeneration gen, int value) { LongLiteral.push(gen, value); }
545      public void DoubleType.emitPushConstant(CodeGeneration gen, int value) { DoubleLiteral.push(gen, value); }
546      public void FloatType.emitPushConstant(CodeGeneration gen, int value) { FloatingPointLiteral.push(gen, value); }
547    
548      // push literals
549    
550      public void Literal.emitPushConstant(CodeGeneration gen) {
551        System.out.println("ERROR: Tried to generate bytecode for: " + getClass().getName());  
552      }
553    
554      public void IntegerLiteral.emitPushConstant(CodeGeneration gen) {
555        type().emitPushConstant(gen, constant().intValue());
556      }
557    
558      public void CharacterLiteral.emitPushConstant(CodeGeneration gen) {
559        type().emitPushConstant(gen, constant().intValue());
560      }
561    
562      public void FloatingPointLiteral.emitPushConstant(CodeGeneration gen) {
563        FloatingPointLiteral.push(gen, constant().floatValue());
564      }
565    
566      public void LongLiteral.emitPushConstant(CodeGeneration gen) {
567        LongLiteral.push(gen, constant().longValue());
568      }
569    
570      public void DoubleLiteral.emitPushConstant(CodeGeneration gen) {
571        DoubleLiteral.push(gen, constant().doubleValue());
572      }
573    
574      public void StringLiteral.emitPushConstant(CodeGeneration gen) {
575        StringLiteral.push(gen, getLITERAL());
576      }
577    
578      public void NullLiteral.emitPushConstant(CodeGeneration gen) {
579        gen.emit(Bytecode.ACONST_NULL);
580      }
581    
582      public void BooleanLiteral.emitPushConstant(CodeGeneration gen) {
583        BooleanLiteral.push(gen, constant().booleanValue());
584      }
585    
586      public void ASTNode.error() {
587        Throwable t = new Throwable();
588        StackTraceElement[] ste = new Throwable().getStackTrace();
589        String s = ste[1].toString();
590        throw new Error(s+" Cannot create bytecode for:"+getClass().getName());
591      }
592    
593      public void Constant.createBCode(CodeGeneration gen) {
594        if(this instanceof ConstantInt)
595          IntegerLiteral.push(gen, intValue());
596        else if(this instanceof ConstantLong)
597          LongLiteral.push(gen, longValue());
598        else if(this instanceof ConstantFloat)
599          FloatingPointLiteral.push(gen, floatValue());
600        else if(this instanceof ConstantDouble)
601          DoubleLiteral.push(gen, doubleValue());
602        else if(this instanceof ConstantChar)
603          IntegerLiteral.push(gen, intValue());
604        else if(this instanceof ConstantBoolean)
605          BooleanLiteral.push(gen, booleanValue());
606        else if(this instanceof ConstantString)
607          StringLiteral.push(gen, stringValue());
608      }
609    
610      // return
611    
612      public void TypeDecl.emitReturn(CodeGeneration gen) { error(); }
613      public void VoidType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.RETURN);}
614      public void PrimitiveType.emitReturn(CodeGeneration gen) { gen.emit(Bytecode.IRETURN);}
615      public void LongType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.LRETURN);}
616      public void FloatType.emitReturn(CodeGeneration gen)     { gen.emit(Bytecode.FRETURN);}
617      public void DoubleType.emitReturn(CodeGeneration gen)    { gen.emit(Bytecode.DRETURN);}
618      public void ReferenceType.emitReturn(CodeGeneration gen) { gen.emit(Bytecode.ARETURN);}
619      public void NullType.emitReturn(CodeGeneration gen)      { gen.emit(Bytecode.ARETURN);}
620    
621      syn byte TypeDecl.arrayLoad() { 
622        throw new Error("Cannot create array load for TypeDecl");
623      }
624      eq ReferenceType.arrayLoad() = Bytecode.AALOAD;
625      eq IntType.arrayLoad() = Bytecode.IALOAD;
626      eq LongType.arrayLoad() = Bytecode.LALOAD;
627      eq FloatType.arrayLoad() = Bytecode.FALOAD;
628      eq DoubleType.arrayLoad() = Bytecode.DALOAD;
629      eq ByteType.arrayLoad() = Bytecode.BALOAD;
630      eq CharType.arrayLoad() = Bytecode.CALOAD;
631      eq ShortType.arrayLoad() = Bytecode.SALOAD;
632      eq BooleanType.arrayLoad() = Bytecode.BALOAD;
633    
634      public void TypeDecl.emitLoadLocal(CodeGeneration gen, int pos) {error();}
635      public void PrimitiveType.emitLoadLocal(CodeGeneration gen, int pos) {
636        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
637        if(pos == 0) gen.emit(Bytecode.ILOAD_0);
638        else if(pos == 1) gen.emit(Bytecode.ILOAD_1);
639        else if(pos == 2) gen.emit(Bytecode.ILOAD_2);
640        else if(pos == 3) gen.emit(Bytecode.ILOAD_3);
641        else if(pos < 256) gen.emit(Bytecode.ILOAD).add(pos);
642        else gen.emit(Bytecode.WIDE).emit(Bytecode.ILOAD).add2(pos);
643      }
644      public void LongType.emitLoadLocal(CodeGeneration gen, int pos) {
645        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
646        if(pos == 0) gen.emit(Bytecode.LLOAD_0);
647        else if(pos == 1) gen.emit(Bytecode.LLOAD_1);
648        else if(pos == 2) gen.emit(Bytecode.LLOAD_2);
649        else if(pos == 3) gen.emit(Bytecode.LLOAD_3);
650        else if(pos < 256) gen.emit(Bytecode.LLOAD).add(pos);
651        else gen.emit(Bytecode.WIDE).emit(Bytecode.LLOAD).add2(pos);
652      }
653      public void FloatType.emitLoadLocal(CodeGeneration gen, int pos) {
654        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
655        if(pos == 0) gen.emit(Bytecode.FLOAD_0);
656        else if(pos == 1) gen.emit(Bytecode.FLOAD_1);
657        else if(pos == 2) gen.emit(Bytecode.FLOAD_2);
658        else if(pos == 3) gen.emit(Bytecode.FLOAD_3);
659        else if(pos < 256) gen.emit(Bytecode.FLOAD).add(pos);
660        else gen.emit(Bytecode.WIDE).emit(Bytecode.FLOAD).add2(pos);
661      }
662      public void DoubleType.emitLoadLocal(CodeGeneration gen, int pos) {
663        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
664        if(pos == 0) gen.emit(Bytecode.DLOAD_0);
665        else if(pos == 1) gen.emit(Bytecode.DLOAD_1);
666        else if(pos == 2) gen.emit(Bytecode.DLOAD_2);
667        else if(pos == 3) gen.emit(Bytecode.DLOAD_3);
668        else if(pos < 256) gen.emit(Bytecode.DLOAD).add(pos);
669        else gen.emit(Bytecode.WIDE).emit(Bytecode.DLOAD).add2(pos);
670      }
671      public void ReferenceType.emitLoadLocal(CodeGeneration gen, int pos) {
672        gen.emitLoadReference(pos);
673      }
674      public void NullType.emitLoadLocal(CodeGeneration gen, int pos) {
675        gen.emitLoadReference(pos);
676      }
677    
678      public void FieldDeclaration.emitLoadField(CodeGeneration gen, TypeDecl typeDecl) {
679        if(hostType().isArrayDecl() && name().equals("length")) {
680          gen.emit(Bytecode.ARRAYLENGTH);
681          return;
682        }
683        String classname = typeDecl.constantPoolName();
684        String      desc = type().typeDescriptor();
685        String      name = name();
686        int index = gen.constantPool().addFieldref(classname, name, desc);
687        if(isStatic())
688          gen.emit(Bytecode.GETSTATIC, type().variableSize()).add2(index);
689        else
690          gen.emit(Bytecode.GETFIELD, type().variableSize() - 1).add2(index);
691      }
692      
693    
694      // emit store
695    
696      public void Expr.emitStore(CodeGeneration gen) { error("emitStore called with " + getClass().getName()); }
697      public void AbstractDot.emitStore(CodeGeneration gen) { lastAccess().emitStore(gen); }
698    
699      public void VarAccess.emitStore(CodeGeneration gen) {
700        Variable v = decl();
701        if(v instanceof VariableDeclaration) {
702          VariableDeclaration decl = (VariableDeclaration)v;
703          if(isDUbefore(v))
704             gen.addLocalVariableEntryAtCurrentPC(decl.name(), decl.type().typeDescriptor(), decl.localNum(), decl.variableScopeEndLabel(gen));
705          decl.type().emitStoreLocal(gen, decl.localNum());
706        }
707        else if(v instanceof ParameterDeclaration) {
708          ParameterDeclaration decl = (ParameterDeclaration)v;
709          decl.type().emitStoreLocal(gen, decl.localNum());
710        }
711        else if(v instanceof FieldDeclaration) {
712          FieldDeclaration f = (FieldDeclaration)v;
713          if(f.isPrivate() && !hostType().hasField(v.name()))
714            f.createAccessorWrite(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType());
715          else
716            f.emitStoreField(gen, fieldQualifierType());
717        }
718      }
719      
720      public void ArrayAccess.emitStore(CodeGeneration gen) {
721        gen.emit(type().arrayStore());
722      }
723      syn byte TypeDecl.arrayStore() { 
724        throw new Error("Cannot create array load for TypeDecl");
725      }
726      eq ReferenceType.arrayStore() = Bytecode.AASTORE;
727      eq IntType.arrayStore() = Bytecode.IASTORE;
728      eq LongType.arrayStore() = Bytecode.LASTORE;
729      eq FloatType.arrayStore() = Bytecode.FASTORE;
730      eq DoubleType.arrayStore() = Bytecode.DASTORE;
731      eq ByteType.arrayStore() = Bytecode.BASTORE;
732      eq CharType.arrayStore() = Bytecode.CASTORE;
733      eq ShortType.arrayStore() = Bytecode.SASTORE;
734      eq BooleanType.arrayStore() = Bytecode.BASTORE;
735      
736      public void FieldDeclaration.emitStoreField(CodeGeneration gen, TypeDecl typeDecl) {
737        String classname = typeDecl.constantPoolName();
738        String      desc = type().typeDescriptor();
739        String      name = name();
740        int index = gen.constantPool().addFieldref(classname, name, desc);
741        if(isStatic())
742          gen.emit(Bytecode.PUTSTATIC, -type().variableSize()).add2(index);
743        else
744          gen.emit(Bytecode.PUTFIELD, -type().variableSize() - 1).add2(index);
745      }
746      
747      public void TypeDecl.emitStoreLocal(CodeGeneration gen, int pos) {error();}
748      public void PrimitiveType.emitStoreLocal(CodeGeneration gen, int pos) {
749        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
750        if(pos == 0) gen.emit(Bytecode.ISTORE_0);
751        else if(pos == 1) gen.emit(Bytecode.ISTORE_1);
752        else if(pos == 2) gen.emit(Bytecode.ISTORE_2);
753        else if(pos == 3) gen.emit(Bytecode.ISTORE_3);
754        else if(pos < 256) gen.emit(Bytecode.ISTORE).add(pos);
755        else gen.emit(Bytecode.WIDE).emit(Bytecode.ISTORE).add2(pos);
756      }
757      public void LongType.emitStoreLocal(CodeGeneration gen, int pos) {
758        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
759        if(pos == 0) gen.emit(Bytecode.LSTORE_0);
760        else if(pos == 1) gen.emit(Bytecode.LSTORE_1);
761        else if(pos == 2) gen.emit(Bytecode.LSTORE_2);
762        else if(pos == 3) gen.emit(Bytecode.LSTORE_3);
763        else if(pos < 256) gen.emit(Bytecode.LSTORE).add(pos);
764        else gen.emit(Bytecode.WIDE).emit(Bytecode.LSTORE).add2(pos);
765      }
766      public void FloatType.emitStoreLocal(CodeGeneration gen, int pos) {
767        gen.maxLocals = Math.max(gen.maxLocals, pos+1);
768        if(pos == 0) gen.emit(Bytecode.FSTORE_0);
769        else if(pos == 1) gen.emit(Bytecode.FSTORE_1);
770        else if(pos == 2) gen.emit(Bytecode.FSTORE_2);
771        else if(pos == 3) gen.emit(Bytecode.FSTORE_3);
772        else if(pos < 256) gen.emit(Bytecode.FSTORE).add(pos);
773        else gen.emit(Bytecode.WIDE).emit(Bytecode.FSTORE).add2(pos);
774      }
775      public void DoubleType.emitStoreLocal(CodeGeneration gen, int pos) {
776        gen.maxLocals = Math.max(gen.maxLocals, pos+2);
777        if(pos == 0) gen.emit(Bytecode.DSTORE_0);
778        else if(pos == 1) gen.emit(Bytecode.DSTORE_1);
779        else if(pos == 2) gen.emit(Bytecode.DSTORE_2);
780        else if(pos == 3) gen.emit(Bytecode.DSTORE_3);
781        else if(pos < 256) gen.emit(Bytecode.DSTORE).add(pos);
782        else gen.emit(Bytecode.WIDE).emit(Bytecode.DSTORE).add2(pos);
783      }
784      public void ReferenceType.emitStoreLocal(CodeGeneration gen, int pos) {
785        gen.emitStoreReference(pos);
786      }
787      public void NullType.emitStoreLocal(CodeGeneration gen, int pos) {
788        gen.emitStoreReference(pos);
789      }
790    
791      // exceptions
792    
793      inh TypeDecl TryStmt.typeThrowable();
794    
795      public void TryStmt.emitExceptionHandler(CodeGeneration gen) {
796        // add 1 to stack depth
797        gen.changeStackDepth(1);
798        int num = localNum();
799        gen.emitStoreReference(num);
800        gen.emitJsr(label_finally_block());
801        gen.emitLoadReference(num);
802        gen.emit(Bytecode.ATHROW);
803      }
804    
805      public void TryStmt.emitFinallyBlock(CodeGeneration gen) {
806        // add 1 to stack depth
807        gen.changeStackDepth(1);
808        int num = localNum()+1;
809        gen.emitStoreReference(num);
810        getFinally().createBCode(gen);
811        if(num < 256)
812          gen.emit(Bytecode.RET).add(num);
813        else
814          gen.emit(Bytecode.WIDE).emit(Bytecode.RET).add2(num);
815      }
816    
817      public void SynchronizedStmt.emitMonitorEnter(CodeGeneration gen) {
818        gen.emitDup();
819        int num = localNum();
820        gen.emitStoreReference(num);
821        gen.emit(Bytecode.MONITORENTER);
822      }
823      public void SynchronizedStmt.emitExceptionHandler(CodeGeneration gen) {
824        // add 1 to stack depth
825        gen.changeStackDepth(1);
826        int num = localNum() + 1;
827        gen.emitStoreReference(num);
828        gen.emitJsr(label_finally_block());
829        gen.emitLoadReference(num);
830        gen.emit(Bytecode.ATHROW);
831      }
832      public void SynchronizedStmt.emitFinallyBlock(CodeGeneration gen) {
833        // add 1 to stack depth
834        gen.changeStackDepth(1);
835        int num = localNum() + 2;
836        gen.emitStoreReference(num);
837        gen.emitLoadReference(localNum()); // monitor
838        gen.emit(Bytecode.MONITOREXIT);
839        gen.emit(Bytecode.RET).add(num);
840      }
841    
842      // dup
843    
844      public void TypeDecl.emitDup(CodeGeneration gen)      { gen.emit(Bytecode.DUP); }
845      public void VoidType.emitDup(CodeGeneration gen)      { }
846      public void DoubleType.emitDup(CodeGeneration gen)    { gen.emit(Bytecode.DUP2); }
847      public void LongType.emitDup(CodeGeneration gen)      { gen.emit(Bytecode.DUP2); }
848      
849      public void TypeDecl.emitDup_x1(CodeGeneration gen)   { gen.emit(Bytecode.DUP_X1); }
850      public void VoidType.emitDup_x1(CodeGeneration gen)   { }
851      public void DoubleType.emitDup_x1(CodeGeneration gen) { gen.emit(Bytecode.DUP2_X1); }
852      public void LongType.emitDup_x1(CodeGeneration gen)   { gen.emit(Bytecode.DUP2_X1); }
853    
854      public void TypeDecl.emitDup_x2(CodeGeneration gen)   { gen.emit(Bytecode.DUP_X2); }
855      public void VoidType.emitDup_x2(CodeGeneration gen)   { }
856      public void DoubleType.emitDup_x2(CodeGeneration gen) { gen.emit(Bytecode.DUP2_X2); }
857      public void LongType.emitDup_x2(CodeGeneration gen)   { gen.emit(Bytecode.DUP2_X2); }
858      
859      public void TypeDecl.emitPop(CodeGeneration gen)      { gen.emit(Bytecode.POP); }
860      public void VoidType.emitPop(CodeGeneration gen)      { }
861      public void DoubleType.emitPop(CodeGeneration gen)    { gen.emit(Bytecode.POP2); }
862      public void LongType.emitPop(CodeGeneration gen)      { gen.emit(Bytecode.POP2); }
863    
864    
865      // emitInvoke
866    
867      public void MethodDecl.emitInvokeMethod(CodeGeneration gen, TypeDecl hostType) {
868        if(hostType.isInterfaceDecl()) {
869          int size = type().variableSize() - 1;
870          for(int i = 0; i < getNumParameter(); i++)
871            size -= getParameter(i).type().variableSize();
872          String classname = hostType.constantPoolName();
873          String      desc = descName();
874          String      name = name();
875          int index = gen.constantPool().addInterfaceMethodref(classname, name, desc);
876          int numArg = 1; // instance
877          for(int i = 0; i < getNumParameter(); i++)
878            numArg += getParameter(i).type().variableSize();
879          gen.emit(Bytecode.INVOKEINTERFACE, size).add2(index).add(numArg).add(0);
880        }
881        else {
882          String classname = hostType.constantPoolName();
883          String      desc = descName();
884          String      name = name();
885          int index = gen.constantPool().addMethodref(classname, name, desc);
886          if(isStatic()) {
887            int size = type().variableSize();
888            for(int i = 0; i < getNumParameter(); i++)
889              size -= getParameter(i).type().variableSize();
890            gen.emit(Bytecode.INVOKESTATIC, size).add2(index);
891          }
892          else {
893            int size = type().variableSize() - 1;
894            for(int i = 0; i < getNumParameter(); i++)
895              size -= getParameter(i).type().variableSize();
896            gen.emit(Bytecode.INVOKEVIRTUAL, size).add2(index);
897          }
898        }
899      }
900      
901      public void MethodDecl.emitInvokeSpecialMethod(CodeGeneration gen, TypeDecl hostType) {
902        String classname = hostType.constantPoolName();
903        String      desc = descName();
904        String      name = name();
905        int index = gen.constantPool().addMethodref(classname, name, desc);
906        int size = type().variableSize() - 1;
907        for(int i = 0; i < getNumParameter(); i++)
908          size -= getParameter(i).type().variableSize();
909        gen.emit(Bytecode.INVOKESPECIAL, size).add2(index);
910      }
911    
912      public void ConstructorDecl.emitInvokeConstructor(CodeGeneration gen) {
913        int size = -1;
914        for(int i = 0; i < getNumParameter(); i++)
915          size -= getParameter(i).type().variableSize();
916        if(hostType().needsEnclosing())
917          size--;
918        if(hostType().needsSuperEnclosing()) {
919          size--;
920        }
921        String classname = hostType().constantPoolName();
922        String      desc = descName();
923        String      name = "<init>";
924        int index = gen.constantPool().addMethodref(classname, name, desc);
925        gen.emit(Bytecode.INVOKESPECIAL, size).add2(index);
926      }
927    
928      // emitNew
929    
930      public void TypeDecl.emitNew(CodeGeneration gen) {
931        int index = gen.constantPool().addClass(constantPoolName());
932        gen.emit(Bytecode.NEW).add2(index);
933      }
934    }
935    aspect CodeGenerationConversions {
936      void TypeDecl.emitAssignConvTo(CodeGeneration gen, TypeDecl type) {
937        if(!type.isIntegralType() || !isIntegralType() || type.isLong())
938          emitCastTo(gen, type);
939      }
940      
941      void TypeDecl.emitCastTo(CodeGeneration gen, TypeDecl type) { throw new Error("CastTo not implemented for " + getClass().getName()); }
942      void ReferenceType.emitCastTo(CodeGeneration gen, TypeDecl type) { if(!instanceOf(type) && !type.isNull()) gen.emitCheckCast(type); }
943      void IntType.emitCastTo(CodeGeneration gen, TypeDecl type)      { type.intToThis(gen); }
944      void FloatType.emitCastTo(CodeGeneration gen, TypeDecl type)    { type.floatToThis(gen); }
945      void DoubleType.emitCastTo(CodeGeneration gen, TypeDecl type)   { type.doubleToThis(gen); }
946      void LongType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.longToThis(gen); }
947      void ByteType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.byteToThis(gen); }
948      void ShortType.emitCastTo(CodeGeneration gen, TypeDecl type)    { type.shortToThis(gen); }
949      void CharType.emitCastTo(CodeGeneration gen, TypeDecl type)     { type.charToThis(gen); }
950      void BooleanType.emitCastTo(CodeGeneration gen, TypeDecl type)  { }
951      void NullType.emitCastTo(CodeGeneration gen, TypeDecl type)     { }
952    
953      void TypeDecl.intToThis(CodeGeneration gen) { throw new Error("intToThis not implemented for " + getClass().getName()); }
954      void IntType.intToThis(CodeGeneration gen)    { }
955      void LongType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2L); }
956      void FloatType.intToThis(CodeGeneration gen)  { gen.emit(Bytecode.I2F); }
957      void DoubleType.intToThis(CodeGeneration gen) { gen.emit(Bytecode.I2D); }
958      void ByteType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2B); }
959      void CharType.intToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2C); }
960      void ShortType.intToThis(CodeGeneration gen)  { gen.emit(Bytecode.I2S); }
961    
962      void TypeDecl.floatToThis(CodeGeneration gen) { throw new Error("floatToThis not implemented for " + getClass().getName()); }
963      void IntType.floatToThis(CodeGeneration gen)    { gen.emit(Bytecode.F2I); }
964      void ByteType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2I).emit(Bytecode.I2B); }
965      void ShortType.floatToThis(CodeGeneration gen)  { gen.emit(Bytecode.F2I).emit(Bytecode.I2S); }
966      void CharType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2I).emit(Bytecode.I2C); }
967      void FloatType.floatToThis(CodeGeneration gen)  { }
968      void LongType.floatToThis(CodeGeneration gen)   { gen.emit(Bytecode.F2L); }
969      void DoubleType.floatToThis(CodeGeneration gen) { gen.emit(Bytecode.F2D); }
970    
971      void TypeDecl.doubleToThis(CodeGeneration gen) { throw new Error("doubleToThis not implemented for " + getClass().getName()); }
972      void IntType.doubleToThis(CodeGeneration gen)    { gen.emit(Bytecode.D2I); }
973      void ByteType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2I).emit(Bytecode.I2B); }
974      void ShortType.doubleToThis(CodeGeneration gen)  { gen.emit(Bytecode.D2I).emit(Bytecode.I2S); }
975      void CharType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2I).emit(Bytecode.I2C); }
976      void FloatType.doubleToThis(CodeGeneration gen)  { gen.emit(Bytecode.D2F); }
977      void LongType.doubleToThis(CodeGeneration gen)   { gen.emit(Bytecode.D2L); }
978      void DoubleType.doubleToThis(CodeGeneration gen) { }
979    
980      void TypeDecl.longToThis(CodeGeneration gen) { throw new Error("longToThis not implemented for " + getClass().getName()); }
981      void IntType.longToThis(CodeGeneration gen)    { gen.emit(Bytecode.L2I); }
982      void ByteType.longToThis(CodeGeneration gen)   { gen.emit(Bytecode.L2I).emit(Bytecode.I2B); }
983      void ShortType.longToThis(CodeGeneration gen)  { gen.emit(Bytecode.L2I).emit(Bytecode.I2S); }
984      void CharType.longToThis(CodeGeneration gen)   { gen.emit(Bytecode.L2I).emit(Bytecode.I2C); }
985      void FloatType.longToThis(CodeGeneration gen)  { gen.emit(Bytecode.L2F); }
986      void LongType.longToThis(CodeGeneration gen)   { }
987      void DoubleType.longToThis(CodeGeneration gen) { gen.emit(Bytecode.L2D); }
988    
989      void TypeDecl.byteToThis(CodeGeneration gen) { throw new Error("byteToThis not implemented for " + getClass().getName()); }
990      void IntegralType.byteToThis(CodeGeneration gen) { }
991      void CharType.byteToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2C); }
992      void FloatType.byteToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
993      void LongType.byteToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
994      void DoubleType.byteToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D);}
995      
996      void TypeDecl.charToThis(CodeGeneration gen) { throw new Error("charToThis not implemented for " + getClass().getName()); }
997      void IntegralType.charToThis(CodeGeneration gen) { }
998      void ByteType.charToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2B); }
999      void ShortType.charToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2S); }
1000      void FloatType.charToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
1001      void LongType.charToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
1002      void DoubleType.charToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D);}
1003      
1004      void TypeDecl.shortToThis(CodeGeneration gen) { throw new Error("shortToThis not implemented for " + getClass().getName()); }
1005      void IntegralType.shortToThis(CodeGeneration gen) { }
1006      void ByteType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2B); }
1007      void CharType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2C); }
1008      void FloatType.shortToThis(CodeGeneration gen)    { gen.emit(Bytecode.I2F); }
1009      void LongType.shortToThis(CodeGeneration gen)     { gen.emit(Bytecode.I2L); }
1010      void DoubleType.shortToThis(CodeGeneration gen)   { gen.emit(Bytecode.I2D); }
1011    
1012    }
1013    
1014    aspect CodeGenerationBinaryOperations {
1015      // emit the desired operation on the operand(s) on the stack
1016      void Expr.emitOperation(CodeGeneration gen) {error();}
1017      // unary
1018      void MinusExpr.emitOperation(CodeGeneration gen)  { type().neg(gen); }
1019      void PlusExpr.emitOperation(CodeGeneration gen)   { }
1020      void BitNotExpr.emitOperation(CodeGeneration gen) { type().bitNot(gen); }
1021      void LogNotExpr.emitOperation(CodeGeneration gen) { type().logNot(gen); }
1022    
1023      // binary
1024      void AddExpr.emitOperation(CodeGeneration gen) { type().add(gen); }
1025      void SubExpr.emitOperation(CodeGeneration gen) { type().sub(gen); }
1026      void MulExpr.emitOperation(CodeGeneration gen) { type().mul(gen); }
1027      void DivExpr.emitOperation(CodeGeneration gen) { type().div(gen); }
1028      void ModExpr.emitOperation(CodeGeneration gen) { type().rem(gen); }
1029    
1030      void LShiftExpr.emitOperation(CodeGeneration gen)     { type().shl(gen); }
1031      void RShiftExpr.emitOperation(CodeGeneration gen)     { type().shr(gen); }
1032      void URShiftExpr.emitOperation(CodeGeneration gen)    { type().ushr(gen); }
1033      void OrBitwiseExpr.emitOperation(CodeGeneration gen)  { type().bitor(gen); }
1034      void AndBitwiseExpr.emitOperation(CodeGeneration gen) { type().bitand(gen); }
1035      void XorBitwiseExpr.emitOperation(CodeGeneration gen) { type().bitxor(gen); }
1036      
1037      void TypeDecl.neg(CodeGeneration gen) { error(); }
1038      void IntegralType.neg(CodeGeneration gen) { gen.emit(Bytecode.INEG); }
1039      void LongType.neg(CodeGeneration gen)     { gen.emit(Bytecode.LNEG); }
1040      void FloatType.neg(CodeGeneration gen)    { gen.emit(Bytecode.FNEG); }
1041      void DoubleType.neg(CodeGeneration gen)   { gen.emit(Bytecode.DNEG); }
1042    
1043      void TypeDecl.bitNot(CodeGeneration gen) { error(); }
1044      void IntegralType.bitNot(CodeGeneration gen) { gen.emit(Bytecode.ICONST_M1).emit(Bytecode.IXOR); }
1045      void LongType.bitNot(CodeGeneration gen)     { emitPushConstant(gen, -1); gen.emit(Bytecode.LXOR); }
1046    
1047      void TypeDecl.logNot(CodeGeneration gen) { error();}
1048      void BooleanType.logNot(CodeGeneration gen) { gen.emit(Bytecode.ICONST_1).emit(Bytecode.IXOR); }
1049    
1050      void TypeDecl.add(CodeGeneration gen) {error();}
1051      void LongType.add(CodeGeneration gen) {gen.emit(Bytecode.LADD);}
1052      void FloatType.add(CodeGeneration gen) {gen.emit(Bytecode.FADD);}
1053      void DoubleType.add(CodeGeneration gen) {gen.emit(Bytecode.DADD);}
1054      void IntegralType.add(CodeGeneration gen) {gen.emit(Bytecode.IADD);}
1055    
1056      void TypeDecl.sub(CodeGeneration gen) {error();}
1057      void LongType.sub(CodeGeneration gen) {gen.emit(Bytecode.LSUB);}
1058      void FloatType.sub(CodeGeneration gen) {gen.emit(Bytecode.FSUB);}
1059      void DoubleType.sub(CodeGeneration gen) {gen.emit(Bytecode.DSUB);}
1060      void IntegralType.sub(CodeGeneration gen) {gen.emit(Bytecode.ISUB);}
1061    
1062      void TypeDecl.mul(CodeGeneration gen) {error();}
1063      void LongType.mul(CodeGeneration gen) {gen.emit(Bytecode.LMUL);}
1064      void FloatType.mul(CodeGeneration gen) {gen.emit(Bytecode.FMUL);}
1065      void DoubleType.mul(CodeGeneration gen) {gen.emit(Bytecode.DMUL);}
1066      void IntegralType.mul(CodeGeneration gen) {gen.emit(Bytecode.IMUL);}
1067    
1068      void TypeDecl.div(CodeGeneration gen) {error();}
1069      void LongType.div(CodeGeneration gen) {gen.emit(Bytecode.LDIV);}
1070      void FloatType.div(CodeGeneration gen) {gen.emit(Bytecode.FDIV);}
1071      void DoubleType.div(CodeGeneration gen) {gen.emit(Bytecode.DDIV);}
1072      void IntegralType.div(CodeGeneration gen) {gen.emit(Bytecode.IDIV);}
1073    
1074      void TypeDecl.rem(CodeGeneration gen) {error();}
1075      void LongType.rem(CodeGeneration gen) {gen.emit(Bytecode.LREM);}
1076      void FloatType.rem(CodeGeneration gen) {gen.emit(Bytecode.FREM);}
1077      void DoubleType.rem(CodeGeneration gen) {gen.emit(Bytecode.DREM);}
1078      void IntegralType.rem(CodeGeneration gen) {gen.emit(Bytecode.IREM);}
1079    
1080      void TypeDecl.shl(CodeGeneration gen) {error();}
1081      void LongType.shl(CodeGeneration gen) {gen.emit(Bytecode.LSHL);}
1082      void IntegralType.shl(CodeGeneration gen) {gen.emit(Bytecode.ISHL);}
1083    
1084      void TypeDecl.shr(CodeGeneration gen) {error();}
1085      void LongType.shr(CodeGeneration gen) {gen.emit(Bytecode.LSHR);}
1086      void IntegralType.shr(CodeGeneration gen) {gen.emit(Bytecode.ISHR);}
1087    
1088      void TypeDecl.ushr(CodeGeneration gen) {error();}
1089      void LongType.ushr(CodeGeneration gen) {gen.emit(Bytecode.LUSHR);}
1090      void IntegralType.ushr(CodeGeneration gen) {gen.emit(Bytecode.IUSHR);}
1091    
1092      void TypeDecl.bitand(CodeGeneration gen) {error();}
1093      void LongType.bitand(CodeGeneration gen) {gen.emit(Bytecode.LAND);}
1094      void IntegralType.bitand(CodeGeneration gen) {gen.emit(Bytecode.IAND);}
1095      void BooleanType.bitand(CodeGeneration gen) {gen.emit(Bytecode.IAND);}
1096    
1097      void TypeDecl.bitor(CodeGeneration gen) {error();}
1098      void LongType.bitor(CodeGeneration gen) {gen.emit(Bytecode.LOR);}
1099      void IntegralType.bitor(CodeGeneration gen) {gen.emit(Bytecode.IOR);}
1100      void BooleanType.bitor(CodeGeneration gen) {gen.emit(Bytecode.IOR);}
1101    
1102      void TypeDecl.bitxor(CodeGeneration gen) {error();}
1103      void LongType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.LXOR);}
1104      void IntegralType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.IXOR);}
1105      void BooleanType.bitxor(CodeGeneration gen) {gen.emit(Bytecode.IXOR);}
1106    }
1107    
1108    aspect CodeGenerationBranch {
1109      public void TypeDecl.branchLT(CodeGeneration gen, int label) { throw new Error("branchLT not supported for " + getClass().getName()); }
1110      public void DoubleType.branchLT(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFLT, label); }
1111      public void FloatType.branchLT(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFLT, label); }
1112      public void LongType.branchLT(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFLT, label); }
1113      public void IntegralType.branchLT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLT, label); }
1114        
1115      public void TypeDecl.branchLE(CodeGeneration gen, int label) { throw new Error("branchLE not supported for " + getClass().getName()); }
1116      public void DoubleType.branchLE(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPG).emitCompare(Bytecode.IFLE, label); }
1117      public void FloatType.branchLE(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPG).emitCompare(Bytecode.IFLE, label); }
1118      public void LongType.branchLE(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFLE, label); }
1119      public void IntegralType.branchLE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPLE, label); }
1120      
1121      public void TypeDecl.branchGE(CodeGeneration gen, int label) { throw new Error("branchGE not supported for " + getClass().getName()); }
1122      public void DoubleType.branchGE(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFGE, label); }
1123      public void FloatType.branchGE(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFGE, label); }
1124      public void LongType.branchGE(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFGE, label); }
1125      public void IntegralType.branchGE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGE, label); }
1126      
1127      public void TypeDecl.branchGT(CodeGeneration gen, int label) { throw new Error("branchGT not supported for " + getClass().getName()); }
1128      public void DoubleType.branchGT(CodeGeneration gen, int label)   { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFGT, label); }
1129      public void FloatType.branchGT(CodeGeneration gen, int label)    { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFGT, label); }
1130      public void LongType.branchGT(CodeGeneration gen, int label)     { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFGT, label); }
1131      public void IntegralType.branchGT(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ICMPGT, label); }
1132    
1133      public void TypeDecl.branchEQ(CodeGeneration gen, int label) { throw new Error("branchEQ not supported for " + getClass().getName()); }
1134      public void DoubleType.branchEQ(CodeGeneration gen, int label)    { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFEQ, label); }
1135      public void FloatType.branchEQ(CodeGeneration gen, int label)     { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFEQ, label); }
1136      public void LongType.branchEQ(CodeGeneration gen, int label)      { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFEQ, label); }
1137      public void IntegralType.branchEQ(CodeGeneration gen, int label)  { gen.emitCompare(Bytecode.IF_ICMPEQ, label); }
1138      public void BooleanType.branchEQ(CodeGeneration gen, int label)   { gen.emitCompare(Bytecode.IF_ICMPEQ, label); }
1139      public void ReferenceType.branchEQ(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPEQ, label); }
1140      public void NullType.branchEQ(CodeGeneration gen, int label)      { gen.emitCompare(Bytecode.IF_ACMPEQ, label); }
1141      
1142      public void TypeDecl.branchNE(CodeGeneration gen, int label) { throw new Error("branchNE not supported for " + getClass().getName()); }
1143      public void DoubleType.branchNE(CodeGeneration gen, int label)    { gen.emit(Bytecode.DCMPL).emitCompare(Bytecode.IFNE, label); }
1144      public void FloatType.branchNE(CodeGeneration gen, int label)     { gen.emit(Bytecode.FCMPL).emitCompare(Bytecode.IFNE, label); }
1145      public void LongType.branchNE(CodeGeneration gen, int label)      { gen.emit(Bytecode.LCMP).emitCompare(Bytecode.IFNE, label); }
1146      public void IntegralType.branchNE(CodeGeneration gen, int label)  { gen.emitCompare(Bytecode.IF_ICMPNE, label); }
1147      public void BooleanType.branchNE(CodeGeneration gen, int label)   { gen.emitCompare(Bytecode.IF_ICMPNE, label); }
1148      public void ReferenceType.branchNE(CodeGeneration gen, int label) { gen.emitCompare(Bytecode.IF_ACMPNE, label); }
1149      public void NullType.branchNE(CodeGeneration gen, int label)      { gen.emitCompare(Bytecode.IF_ACMPNE, label); }
1150    }