/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */ module org.jastadd.java14backend; import java.io.*; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.ArrayList; class Attribute { int attribute_name_index; ByteArrayOutputStream buf = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(buf); public Attribute(ConstantPool cp, String name) { attribute_name_index = cp.addUtf8(name); } public void emit(DataOutputStream out) throws IOException { out.writeChar(attribute_name_index); out.writeInt(buf.size()); buf.writeTo(out); output.close(); buf.close(); } public int size() { return buf.size(); } public void u1(int v) { try { output.writeByte(v); } catch(IOException e) {} } public void u2(int v) { try { output.writeChar(v); } catch(IOException e) {} } public void u4(int v) { try { output.writeInt(v); } catch(IOException e) {} } public void append(byte[] data) { try { output.write(data, 0, data.length); } catch(IOException e) {} } public void append(Attribute attribute) { try { attribute.emit(output); } catch(IOException e) {} } } class SourceFileAttribute extends Attribute { public SourceFileAttribute(ConstantPool p, String sourcefile) { super(p, "SourceFile"); u2(p.addUtf8(sourcefile)); } } class SyntheticAttribute extends Attribute { public SyntheticAttribute(ConstantPool p) { super(p, "Synthetic"); } } class ConstantValueAttribute extends Attribute { public ConstantValueAttribute(ConstantPool p, FieldDeclaration f) { super(p, "ConstantValue"); int constantvalue_index = constantvalue_index = f.type().addConstant(p, f.getInit().constant()); u2(constantvalue_index); } } public aspect AttributesCodegen { public int TypeDecl.addConstant(ConstantPool p, Constant c) { if(isString()) return p.addConstant(c.stringValue()); throw new Error("Not supported"); } public int BooleanType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.booleanValue() ? 1 : 0); } public int IntegralType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.intValue()); } public int LongType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.longValue()); } public int FloatType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.floatValue()); } public int DoubleType.addConstant(ConstantPool p, Constant c) { return p.addConstant(c.doubleValue()); } syn lazy Collection TypeDecl.innerClassesAttributeEntries() { HashSet list = new HashSet(); if(isNestedType()) list.add(this); for(Iterator iter = nestedTypes().iterator(); iter.hasNext(); ) list.add(iter.next()); for(Iterator iter = usedNestedTypes().iterator(); iter.hasNext(); ) list.add(iter.next()); return list; } MethodDecl implements ExceptionHolder; ConstructorDecl implements ExceptionHolder; syn lazy Collection TypeDecl.attributes() { Collection c = new ArrayList(); if(!innerClassesAttributeEntries().isEmpty()) c.add(new InnerClassesAttribute(this)); if(isSynthetic()) c.add(new SyntheticAttribute(constantPool())); if(compilationUnit().fromSource()) { String relativeName = compilationUnit().relativeName(); if(relativeName != null) { String splitToken = java.io.File.separator; if(splitToken.equals("\\")) splitToken = "\\\\"; String[] strings = relativeName.split(splitToken); c.add(new SourceFileAttribute(constantPool(), strings[strings.length-1])); } } return c; } syn lazy Collection BodyDecl.attributes() = new ArrayList(); eq FieldDeclaration.attributes() { ArrayList l = new ArrayList(); if(isStatic() && isFinal() && isConstant() && (type().isPrimitive() || type().isString())) l.add(new ConstantValueAttribute(hostType().constantPool(), this)); return l; } eq MethodDecl.attributes() { ArrayList l = new ArrayList(); l.add(new ExceptionsAttribute(bytecodes(hostType().constantPool()), this)); if(isAbstract() || isNative()) return l; l.add(new CodeAttribute(bytecodes(hostType().constantPool()), this)); if(getModifiers().isSynthetic()) l.add(new SyntheticAttribute(hostType().constantPool())); return l; } eq ConstructorDecl.attributes() { ArrayList l = new ArrayList(); l.add(new CodeAttribute(bytecodes(hostType().constantPool()), null)); l.add(new ExceptionsAttribute(bytecodes(hostType().constantPool()), this)); if(getModifiers().isSynthetic()) l.add(new SyntheticAttribute(hostType().constantPool())); return l; } syn lazy Collection TypeDecl.clinit_attributes() { ArrayList l = new ArrayList(); l.add(new CodeAttribute(bytecodes(constantPool()), null)); return l; } } class InnerClassesAttribute extends Attribute { public InnerClassesAttribute(TypeDecl typeDecl) { super(typeDecl.constantPool(), "InnerClasses"); ConstantPool c = typeDecl.constantPool(); Collection list = typeDecl.innerClassesAttributeEntries(); u2(list.size()); for(Iterator iter = list.iterator(); iter.hasNext(); ) { TypeDecl type = (TypeDecl)iter.next(); u2(c.addClass(type.constantPoolName())); // inner_class_info_index u2(type.isMemberType() ? c.addClass(type.enclosingType().constantPoolName()) : 0); // outer_class_info_index u2(type.isAnonymous() ? 0 : c.addUtf8(type.name())); // inner_name_index u2(type.isInterfaceDecl() ? (type.flags() | Modifiers.ACC_INTERFACE) : type.flags()); // inner_class_access_flags } } } class LocalVariableTableAttribute extends Attribute { public LocalVariableTableAttribute(CodeGeneration gen) { super(gen.constantPool(), "LocalVariableTable"); u2(gen.localVariableTable.size()); for(Iterator iter = gen.localVariableTable.iterator(); iter.hasNext(); ) { CodeGeneration.LocalVariableEntry e = (CodeGeneration.LocalVariableEntry)iter.next(); u2(e.start_pc); u2(e.length); u2(e.name_index); u2(e.descriptor_index); u2(e.index); } } } class LineNumberTableAttribute extends Attribute { public LineNumberTableAttribute(CodeGeneration gen) { super(gen.constantPool(), "LineNumberTable"); u2(gen.lineNumberTable.size()); for(Iterator iter = gen.lineNumberTable.iterator(); iter.hasNext(); ) { CodeGeneration.LineNumberEntry e = (CodeGeneration.LineNumberEntry)iter.next(); u2(e.start_pc); u2(e.line_number); } } } class CodeAttribute extends Attribute { public CodeAttribute(CodeGeneration codeGen, MethodDecl m) { super(codeGen.constantPool(), "Code"); u2(codeGen.maxStackDepth()); u2(codeGen.maxLocals()); u4(codeGen.pos()); // code_length append(codeGen.toArray()); u2(codeGen.exceptions.size()); for(Iterator iter = codeGen.exceptions.iterator(); iter.hasNext(); ) { CodeGeneration.ExceptionEntry e = (CodeGeneration.ExceptionEntry)iter.next(); u2(e.start_pc); u2(e.end_pc); u2(e.handler_pc); u2(e.catch_type); } if(m == null || !m.getModifiers().isSynthetic()) { u2(2); // Attribute count append(new LineNumberTableAttribute(codeGen)); append(new LocalVariableTableAttribute(codeGen)); } else { u2(0); // Attribute count } } } interface ExceptionHolder { public int getNumException(); public Access getException(int i); } class ExceptionsAttribute extends Attribute { public ExceptionsAttribute(CodeGeneration gen, ExceptionHolder m) { super(gen.constantPool(), "Exceptions"); u2(m.getNumException()); for(int i = 0; i < m.getNumException(); i++) u2(gen.constantPool().addClass(m.getException(i).type().constantPoolName())); } }