1783f80f37ad70eba7fd4b5e11a34854724227bf6cushon/* 2783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * Copyright 2016 Google Inc. All Rights Reserved. 3783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * 4783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * Licensed under the Apache License, Version 2.0 (the "License"); 5783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * you may not use this file except in compliance with the License. 6783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * You may obtain a copy of the License at 7783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * 8783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * http://www.apache.org/licenses/LICENSE-2.0 9783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * 10783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * Unless required by applicable law or agreed to in writing, software 11783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * distributed under the License is distributed on an "AS IS" BASIS, 12783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * See the License for the specific language governing permissions and 14783f80f37ad70eba7fd4b5e11a34854724227bf6cushon * limitations under the License. 15783f80f37ad70eba7fd4b5e11a34854724227bf6cushon */ 16783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 17783f80f37ad70eba7fd4b5e11a34854724227bf6cushonpackage com.google.turbine.bytecode; 18783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 19783f80f37ad70eba7fd4b5e11a34854724227bf6cushonimport com.google.common.io.ByteArrayDataOutput; 20783f80f37ad70eba7fd4b5e11a34854724227bf6cushonimport com.google.common.io.ByteStreams; 21bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const.DoubleValue; 22bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const.FloatValue; 23bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const.IntValue; 24bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const.LongValue; 25bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushonimport com.google.turbine.model.Const.StringValue; 26783f80f37ad70eba7fd4b5e11a34854724227bf6cushonimport com.google.turbine.model.Const.Value; 27783f80f37ad70eba7fd4b5e11a34854724227bf6cushonimport java.util.List; 28783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 29783f80f37ad70eba7fd4b5e11a34854724227bf6cushon/** Class file writing. */ 30783f80f37ad70eba7fd4b5e11a34854724227bf6cushonpublic class ClassWriter { 31783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 32783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static final int MAGIC = 0xcafebabe; 33783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static final int MINOR_VERSION = 0; 34783f80f37ad70eba7fd4b5e11a34854724227bf6cushon // TODO(cushon): configuration? 35783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static final int MAJOR_VERSION = 52; 36783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 37783f80f37ad70eba7fd4b5e11a34854724227bf6cushon /** Writes a {@link ClassFile} to bytecode. */ 38783f80f37ad70eba7fd4b5e11a34854724227bf6cushon public static byte[] writeClass(ClassFile classfile) { 39783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ConstantPool pool = new ConstantPool(); 40783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ByteArrayDataOutput output = ByteStreams.newDataOutput(); 41783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(classfile.access()); 42783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.classInfo(classfile.name())); 43d8ea288afe5a7df01f74a0c5b55e489b0dc62349cushon output.writeShort(classfile.superName() != null ? pool.classInfo(classfile.superName()) : 0); 44783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(classfile.interfaces().size()); 45783f80f37ad70eba7fd4b5e11a34854724227bf6cushon for (String i : classfile.interfaces()) { 46783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.classInfo(i)); 47783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 48783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(classfile.fields().size()); 49783f80f37ad70eba7fd4b5e11a34854724227bf6cushon for (ClassFile.FieldInfo f : classfile.fields()) { 50783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeField(pool, output, f); 51783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 52783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(classfile.methods().size()); 53783f80f37ad70eba7fd4b5e11a34854724227bf6cushon for (ClassFile.MethodInfo m : classfile.methods()) { 54783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeMethod(pool, output, m); 55783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 56783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeAttributes(pool, output, LowerAttributes.classAttributes(classfile)); 57783f80f37ad70eba7fd4b5e11a34854724227bf6cushon return finishClass(pool, output); 58783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 59783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 60783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static void writeMethod( 61783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ConstantPool pool, ByteArrayDataOutput output, ClassFile.MethodInfo method) { 62783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(method.access()); 63783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.utf8(method.name())); 64783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.utf8(method.descriptor())); 65783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeAttributes(pool, output, LowerAttributes.methodAttributes(method)); 66783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 67783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 68783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static void writeField( 69783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ConstantPool pool, ByteArrayDataOutput output, ClassFile.FieldInfo field) { 70783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(field.access()); 71783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.utf8(field.name())); 72783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(pool.utf8(field.descriptor())); 73783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeAttributes(pool, output, LowerAttributes.fieldAttributes(field)); 74783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 75783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 76783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static void writeAttributes( 77783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ConstantPool pool, ByteArrayDataOutput body, List<Attribute> attributes) { 78783f80f37ad70eba7fd4b5e11a34854724227bf6cushon body.writeShort(attributes.size()); 79783f80f37ad70eba7fd4b5e11a34854724227bf6cushon for (Attribute attribute : attributes) { 80783f80f37ad70eba7fd4b5e11a34854724227bf6cushon new AttributeWriter(pool, body).write(attribute); 81783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 82783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 83783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 84783f80f37ad70eba7fd4b5e11a34854724227bf6cushon static void writeConstantPool(ConstantPool constantPool, ByteArrayDataOutput output) { 85783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeShort(constantPool.nextEntry); 86783f80f37ad70eba7fd4b5e11a34854724227bf6cushon for (ConstantPool.Entry e : constantPool.constants()) { 87783f80f37ad70eba7fd4b5e11a34854724227bf6cushon output.writeByte(e.kind().tag()); 88783f80f37ad70eba7fd4b5e11a34854724227bf6cushon Value value = e.value(); 8933b30eb88e4724f61d7ea86b0a6564cb702e6615cushon switch (e.kind()) { 9033b30eb88e4724f61d7ea86b0a6564cb702e6615cushon case CLASS_INFO: 91783f80f37ad70eba7fd4b5e11a34854724227bf6cushon case STRING: 9233b30eb88e4724f61d7ea86b0a6564cb702e6615cushon output.writeShort(((IntValue) value).value()); 93783f80f37ad70eba7fd4b5e11a34854724227bf6cushon break; 9433b30eb88e4724f61d7ea86b0a6564cb702e6615cushon case INTEGER: 95bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon output.writeInt(((IntValue) value).value()); 96bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon break; 9733b30eb88e4724f61d7ea86b0a6564cb702e6615cushon case DOUBLE: 9833b30eb88e4724f61d7ea86b0a6564cb702e6615cushon output.writeDouble(((DoubleValue) value).value()); 99bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon break; 100bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon case FLOAT: 101bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon output.writeFloat(((FloatValue) value).value()); 102bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon break; 10333b30eb88e4724f61d7ea86b0a6564cb702e6615cushon case LONG: 10433b30eb88e4724f61d7ea86b0a6564cb702e6615cushon output.writeLong(((LongValue) value).value()); 10533b30eb88e4724f61d7ea86b0a6564cb702e6615cushon break; 10633b30eb88e4724f61d7ea86b0a6564cb702e6615cushon case UTF8: 10733b30eb88e4724f61d7ea86b0a6564cb702e6615cushon output.writeUTF(((StringValue) value).value()); 108bd2b29bb7fd05aed8481ef8342c09c4e88492c88cushon break; 109783f80f37ad70eba7fd4b5e11a34854724227bf6cushon default: 11033b30eb88e4724f61d7ea86b0a6564cb702e6615cushon throw new AssertionError(e.kind()); 111783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 112783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 113783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 114783f80f37ad70eba7fd4b5e11a34854724227bf6cushon 115783f80f37ad70eba7fd4b5e11a34854724227bf6cushon private static byte[] finishClass(ConstantPool pool, ByteArrayDataOutput body) { 116783f80f37ad70eba7fd4b5e11a34854724227bf6cushon ByteArrayDataOutput result = ByteStreams.newDataOutput(); 117783f80f37ad70eba7fd4b5e11a34854724227bf6cushon result.writeInt(MAGIC); 118783f80f37ad70eba7fd4b5e11a34854724227bf6cushon result.writeShort(MINOR_VERSION); 119783f80f37ad70eba7fd4b5e11a34854724227bf6cushon result.writeShort(MAJOR_VERSION); 120783f80f37ad70eba7fd4b5e11a34854724227bf6cushon writeConstantPool(pool, result); 121783f80f37ad70eba7fd4b5e11a34854724227bf6cushon result.write(body.toByteArray()); 122783f80f37ad70eba7fd4b5e11a34854724227bf6cushon return result.toByteArray(); 123783f80f37ad70eba7fd4b5e11a34854724227bf6cushon } 124783f80f37ad70eba7fd4b5e11a34854724227bf6cushon} 125