/*
Генератор кода для языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.generator;
import avt.io.*;
import avt.io.charset.*;
import avt.util.*;
import platform.independent.filesystem.*;
import ru.malik.elaborarer.avtoo.compiler.StringArray;
import ru.malik.elaborarer.avtoo.lang.*;
import ru.malik.elaborarer.compression.zlib.*;
public class BinarySourceGenerator(CodeGenerator, AVTOOConstants, AVTOORecompilable, AVTOOService)
{
/*<fold уровни создания файлов двоичного исходного кода>*/
public static final int CLASS = 0;
public static final int PACKAGE = 1;
public static final int LIBRARY = 2;
/*</fold>*/
private static void appendClassType(ClassType type, BinarySourceGeneratorConstants constants, Vector container) throws IOException {
for(container + constants.serializeClassType(type), boolean isStruct = type.isStruct(), int length = type.length, int index = 0; index < length; index++)
{
Code code = null;
label0:
{
Member member = type[index];
if(member instanceof Method)
{
Method method = (Method) member;
code = method.code;
container + constants.serializeMethod(method);
break label0;
}
if(member instanceof Callable)
{
Callable callable = (Callable) member;
code = callable.code;
container + constants.serializeCallable(callable);
break label0;
}
if(member instanceof Property)
{
container + constants.serializeProperty((Property) member);
continue;
}
if(member instanceof Field)
{
container + (isStruct ? constants.serializeStructField((Field) member) : constants.serializeClassField((Field) member));
}
continue;
}
if(code != null) container + constants.serializeCode(code);
}
}
private static void createRecompilable(Vector container, FileSystem fileSystem, String recompilablePath) throws IOException {
byte[][] chunks = new byte[container.length][];
container.copyInto(chunks, 0);
ByteWriter stream = fileSystem.createFile(recompilablePath + BINARY_SOURCE_EXTENSION);
try
{
with((new DataOutputStream(stream)).bigEndianDataOutput, (Checksum32) new CRC32())
{
writeLong(AVTOORecompilable.SIGNATURE_AVTR);
for(int clength = chunks.length, int cindex = 0; cindex < clength; cindex++)
{
byte[] dbytes = chunks[cindex];
int dlength = dbytes.length;
update(dbytes, 0, dlength);
writeInt(dlength - 4 >> 1);
write(dbytes);
writeInt(value);
reset();
}
}
stream.flush();
} finally
{
stream.close();
}
}
private static Hashtable createSourcesTable(SourceArray sources) {
Hashtable result = new Hashtable();
for(int index = sources.length; index-- > 0; )
{
TextSource source = (TextSource) sources[index];
Package owner = source.owner;
if(owner == null) continue;
String name = owner.specialCanonicalName;
(Vector) (result.containsKey(name) ? result[name] : result[name] = new Vector()) + source;
}
return result;
}
private int fldLevel;
private String fldOverwritten;
public (int pointerSize): super(pointerSize, true) { fldLevel = CLASS; }
public void compile() throws IOException, CompilerException {
/* -- предыдущие стадии -- */
super.compile();
/* 8. Стадия выгрузки данных */
Charset utf16 = Charset.get("UTF-16 BE");
Library project = project;
FileSystem fileSystem = project.fileSystem;
String destinationPath = fldOverwritten = prepareDestinationPath(fileSystem, project.directoryPath + BINARY_SOURCE_PATH);
Vector container = new Vector();
BinarySourceGeneratorConstants constants = new BinarySourceGeneratorConstants();
byte[] version = BinarySourceGeneratorConstants.serializeVersion();
byte[] end = BinarySourceGeneratorConstants.serializeEnd();
switch(fldLevel)
{
case LIBRARY:
{
container + version;
for(Hashtable sourcesTable = createSourcesTable(project.sources), int plength = project.length, int pindex = 0; pindex < plength; pindex++)
{
Package pack = project[pindex];
String packageName = pack.specialCanonicalName;
if(packageName.isEmpty()) continue;
Vector sourcesList = (Vector) sourcesTable[packageName];
TextSource[] sourcesArray = null;
if(sourcesList != null) sourcesList.copyInto(sourcesArray = new TextSource[sourcesList.length], 0);
container + constants.serializePackage(pack);
if(sourcesArray != null) for(int slength = sourcesArray.length, int sindex = 0; sindex < slength; sindex++)
{
TextSource source = sourcesArray[sindex];
container + BinarySourceGeneratorConstants.serializeTextSource(source, utf16);
for(ClassTypeArray declared = source.declared, int dlength = declared.length, int dindex = 0; dindex < dlength; dindex++)
{
appendClassType(declared[dindex], constants, container);
}
}
}
container.insert(1, constants.serializeConstants(utf16));
createRecompilable(container + end, fileSystem, destinationPath + "!library");
container.clear();
constants.clear();
}
break;
case PACKAGE:
for(Hashtable sourcesTable = createSourcesTable(project.sources), int plength = project.length, int pindex = 0; pindex < plength; pindex++)
{
Package pack = project[pindex];
String packageName = pack.specialCanonicalName;
if(packageName.isEmpty()) continue;
Vector sourcesList = (Vector) sourcesTable[packageName];
TextSource[] sourcesArray = null;
if(sourcesList != null) sourcesList.copyInto(sourcesArray = new TextSource[sourcesList.length], 0);
container + version + constants.serializePackage(pack);
if(sourcesArray != null) for(int slength = sourcesArray.length, int sindex = 0; sindex < slength; sindex++)
{
TextSource source = sourcesArray[sindex];
container + BinarySourceGeneratorConstants.serializeTextSource(source, utf16);
for(ClassTypeArray declared = source.declared, int dlength = declared.length, int dindex = 0; dindex < dlength; dindex++)
{
appendClassType(declared[dindex], constants, container);
}
}
container.insert(1, constants.serializeConstants(utf16));
createRecompilable(container + end, fileSystem, destinationPath + packageName);
container.clear();
constants.clear();
}
break;
default:
for(int plength = project.length, int pindex = 0; pindex < plength; pindex++)
{
Package pack = project[pindex];
String packageName = pack.specialCanonicalName;
if(packageName.isEmpty()) continue;
String directoryPath = destinationPath + packageName;
fileSystem.createDirectory(directoryPath);
directoryPath = directoryPath + '/';
{
container + version + constants.serializePackage(pack);
container.insert(1, constants.serializeConstants(utf16));
createRecompilable(container + end, fileSystem, directoryPath + "!package");
container.clear();
constants.clear();
}
for(int dlength = pack.length, int dindex = 0; dindex < dlength; dindex++)
{
ClassType type = (ClassType) pack[dindex];
if(type instanceof ArrayType) continue;
appendClassType(type, constants, container + version + BinarySourceGeneratorConstants.serializeTextSource((TextSource) type.source, utf16));
container.insert(1, constants.serializeConstants(utf16));
createRecompilable(container + end, fileSystem, directoryPath + type.specialSimpleName);
container.clear();
constants.clear();
}
}
}
/* -- конец процесса компиляции -- */
}
public final String overwritten { read = fldOverwritten }
public final int level { read = fldLevel, write = fldLevel = value < CLASS ? CLASS : value > LIBRARY ? LIBRARY : value }
}
service BinarySourceGeneratorConstants(Vector, AVTOOConstants, AVTOORecompilable)
{
public static byte[] serializeVersion() throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_VERS);
writeInt(VERSION_AVTR);
}
return stream.toByteArray();
}
public static byte[] serializeTextSource(TextSource source, Charset charset) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_SURC);
write(source.outputPath.toByteArray(charset));
}
return stream.toByteArray();
}
public static byte[] serializeEnd() throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_IEND);
}
return stream.toByteArray();
}
public void clear() {
super.clear();
operator +(null);
}
public byte[] serializeConstants(Charset charset) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_CONS);
for(Object[] elements = fldElements, int elength = fldLength, int eindex = 1; eindex < elength; eindex++)
{
Object element = elements[eindex];
if(element == null)
{
throw new UnencodableDataException(package.getResourceString("not-encodable.null-pointer"));
}
Class type = element.getClass();
if(Boolean.class == type)
{
writeShort(CONST_Z);
writeShort(((Boolean) element).booleanValue ? -1 : 0);
continue;
}
if(Char.class == type)
{
writeShort(CONST_C);
writeShort(((Char) element).charValue);
continue;
}
if(Real.class == type)
{
writeShort(CONST_R);
writeReal(((Real) element).realValue);
continue;
}
if(Double.class == type)
{
writeShort(CONST_D);
writeDouble(((Double) element).doubleValue);
continue;
}
if(Double2.class == type)
{
writeShort(CONST_D2);
writeDouble2(((Double2) element).double2Value);
continue;
}
if(Double4.class == type)
{
writeShort(CONST_D4);
writeDouble4(((Double4) element).double4Value);
continue;
}
if(Double8.class == type)
{
writeShort(CONST_D8);
writeDouble8(((Double8) element).double8Value);
continue;
}
if(Float.class == type)
{
writeShort(CONST_F);
writeFloat(((Float) element).floatValue);
continue;
}
if(Float2.class == type)
{
writeShort(CONST_F2);
writeFloat2(((Float2) element).float2Value);
continue;
}
if(Float4.class == type)
{
writeShort(CONST_F4);
writeFloat4(((Float4) element).float4Value);
continue;
}
if(Float8.class == type)
{
writeShort(CONST_F8);
writeFloat8(((Float8) element).float8Value);
continue;
}
if(Byte.class == type)
{
writeShort(CONST_B);
writeShort(((Byte) element).byteValue);
continue;
}
if(Byte2.class == type)
{
writeShort(CONST_B2);
writeByte2(((Byte2) element).byte2Value);
continue;
}
if(Byte4.class == type)
{
writeShort(CONST_B4);
writeByte4(((Byte4) element).byte4Value);
continue;
}
if(Byte8.class == type)
{
writeShort(CONST_B8);
writeByte8(((Byte8) element).byte8Value);
continue;
}
if(Short.class == type)
{
writeShort(CONST_S);
writeShort(((Short) element).shortValue);
continue;
}
if(Short2.class == type)
{
writeShort(CONST_S2);
writeShort2(((Short2) element).short2Value);
continue;
}
if(Short4.class == type)
{
writeShort(CONST_S4);
writeShort4(((Short4) element).short4Value);
continue;
}
if(Short8.class == type)
{
writeShort(CONST_S8);
writeShort8(((Short8) element).short8Value);
continue;
}
if(Int.class == type)
{
writeShort(CONST_I);
writeInt(((Int) element).intValue);
continue;
}
if(Int2.class == type)
{
writeShort(CONST_I2);
writeInt2(((Int2) element).int2Value);
continue;
}
if(Int4.class == type)
{
writeShort(CONST_I4);
writeInt4(((Int4) element).int4Value);
continue;
}
if(Int8.class == type)
{
writeShort(CONST_I8);
writeInt8(((Int8) element).int8Value);
continue;
}
if(Long.class == type)
{
writeShort(CONST_J);
writeLong(((Long) element).longValue);
continue;
}
if(Long2.class == type)
{
writeShort(CONST_J2);
writeLong2(((Long2) element).long2Value);
continue;
}
if(Long4.class == type)
{
writeShort(CONST_J4);
writeLong4(((Long4) element).long4Value);
continue;
}
if(Long8.class == type)
{
writeShort(CONST_J8);
writeLong8(((Long8) element).long8Value);
continue;
}
if(String.class == type) with((String) element)
{
writeShort(CONST_ST);
writeShort(length);
write(toByteArray(charset));
continue;
}
if(Package.class.isAssignableFrom(type)) with((TableItem) element)
{
writeShort(CONST_PK);
writeInt(indexOf(recompilableName));
continue;
}
if(Type.class.isAssignableFrom(type)) with((TableItem) element)
{
writeShort(CONST_TP);
writeInt(indexOf(recompilableName));
continue;
}
if(Field.class.isAssignableFrom(type)) with((Member) element)
{
writeShort(CONST_FL);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
continue;
}
if(Property.class.isAssignableFrom(type)) with((Member) element)
{
writeShort(CONST_PR);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
continue;
}
if(Callable.class.isAssignableFrom(type)) with((Callable) element, arguments)
{
writeShort(CONST_CL);
writeInt(indexOf(parentType));
writeInt(indexOf(recompilableName));
int alength = length;
writeShort(alength);
for(int aindex = 0; aindex < alength; aindex++) writeInt(indexOf(operator [](aindex).type));
continue;
}
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.constant-type"), new Object[] { type.simpleName }));
}
}
return stream.toByteArray();
}
public byte[] serializePackage(Package pack) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_PACK);
writeShort(pack.attributes);
writeInt(indexAcquire(pack.specialCanonicalName));
}
return stream.toByteArray();
}
public byte[] serializeClassType(ClassType type) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_TYPE);
writeShort(type.attributes);
writeInt(indexAcquire(type.parentPackage));
writeInt(indexAcquire(type.specialSimpleName));
if(type.isHelper())
{
writeInt(indexAcquire(type.getHelperForType().specialCanonicalName));
} else
{
ClassType supertype = type.getSuperclassType();
writeInt(supertype == null ? 0 : indexAcquire(supertype.specialCanonicalName));
for(int length = type.getSuperservicesLength(), int index = 0; index < length; index++)
{
writeInt(indexAcquire(type.getSuperserviceTypeAt(index).specialCanonicalName));
}
}
}
return stream.toByteArray();
}
public byte[] serializeClassField(Field field) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_CFLD);
writeShort(field.attributes);
writeInt(indexAcquire(field.type));
writeInt(indexAcquire(field.specialSimpleName));
Constant constant = field.value;
if(constant != null) writeInt(indexAcquire(constant));
}
return stream.toByteArray();
}
public byte[] serializeStructField(Field field) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_SFLD);
writeShort(field.attributes);
writeInt(indexAcquire(field.type));
writeInt(indexAcquire(field.specialSimpleName));
writeInt(field.capacity);
writeInt(field.structOffset);
}
return stream.toByteArray();
}
public byte[] serializeProperty(Property property) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_PROP);
writeShort(property.attributes);
writeInt(indexAcquire(property.type));
writeInt(indexAcquire(property.specialSimpleName));
writeInt(indexAcquire(property.indexMember));
writeInt(indexAcquire(property.storedMember));
writeInt(indexAcquire(property.readMember));
writeInt(indexAcquire(property.writeMember));
}
return stream.toByteArray();
}
public byte[] serializeCallable(Callable callable) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_OPER);
writeShort(callable.attributes);
writeInt(indexAcquire(callable.type));
writeInt(indexAcquire(callable.specialSimpleName));
with(callable.arguments)
{
int length = length;
writeShort(length);
for(int index = 0; index < length; index++) with(operator [](index))
{
writeInt(indexAcquire(type));
writeInt(indexAcquire(specialSimpleName));
}
}
}
return stream.toByteArray();
}
public byte[] serializeMethod(Method method) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_METH);
writeShort(method.attributes);
writeInt(indexAcquire(method.type));
writeInt(indexAcquire(method.specialSimpleName));
with(method.arguments)
{
int length = length;
writeShort(length);
for(int index = 0; index < length; index++) with(operator [](index))
{
writeInt(indexAcquire(type));
writeInt(indexAcquire(specialSimpleName));
}
}
for(int length = method.getThrowablesLength(), int index = 0; index < length; index++) writeInt(indexAcquire(method.getThrowableTypeAt(index).specialCanonicalName));
}
return stream.toByteArray();
}
public byte[] serializeCode(Code code) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
with((new DataOutputStream(stream)).bigEndianDataOutput)
{
writeInt(CHUNK_CODE);
{
Hashtable primTable = new Hashtable();
Hashtable refsTable = new Hashtable();
StringArray primArray = new StringArray();
StringArray refsArray = new StringArray();
with(code.locals) for(int length = length, int index = 0; index < length; index++) with(operator [](index)) if(!isConstant())
{
Type type = type;
String name = specialSimpleName;
if(type.isPrimitive())
{
if(!primTable.containsKey(name))
{
primArray.append(name);
primTable[name] = type;
}
else if(((Type) primTable[name]).fieldWidth < type.fieldWidth)
{
primTable[name] = type;
}
} else
{
if(!refsTable.containsKey(name))
{
refsArray.append(name);
refsTable[name] = type;
}
}
}
int primLength = primArray.length;
int refsLength = refsArray.length;
int length = primLength + refsLength;
if(length + Int.MIN_VALUE > 0xffff + Int.MIN_VALUE)
{
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.too-namy-locals"), new Object[] { code.parentCallable }));
}
writeShort(length);
for(int index = 0; index < primLength; index++)
{
String name = primArray[index];
Type type = (Type) primTable[name];
writeInt(indexAcquire(type));
writeInt(indexAcquire(name));
}
for(int index = 0; index < refsLength; index++)
{
String name = refsArray[index];
Type type = (Type) refsTable[name];
writeInt(indexAcquire(type));
writeInt(indexAcquire(name));
}
}
for(Local thisArgument = code.parentCallable.arguments.thisArgument, int lastIndex = -1, int clength = code.length, int cindex = 0; cindex < clength; cindex++)
{
Node node = code[cindex];
{
int lineIndex = (int) node.location;
if(lineIndex >= 0 && lineIndex != lastIndex)
{
int encoded = encodeDeclare(false, lastIndex = lineIndex);
if(isLongEncoded(encoded))
{
writeInt(encoded);
} else
{
writeShort(encoded);
}
}
if((lineIndex = node.debugIndex) >= 0)
{
int encoded = encodeDeclare(true, ~lineIndex);
if(isLongEncoded(encoded))
{
writeInt(encoded);
} else
{
writeShort(encoded);
}
}
if((lineIndex = node.labelIndex) >= 0)
{
int encoded = encodeDeclare(true, lineIndex);
if(isLongEncoded(encoded))
{
writeInt(encoded);
} else
{
writeShort(encoded);
}
}
}
int jlength = node.getJumpCasesLength();
int nodeInstruction = node.instruction;
int formInstruction = jlength > 0 ? FLAG_BOOLEAN_JUMP : 0;
switch(nodeInstruction)
{
case METHOD_ENTER:
writeShort(INST_METHOD_ENTER);
writeIndex(((Int) node.reference1).intValue);
continue;
case SWAP:
Type type = (Type) node.operand1;
writeShort(INST_SWAP | encodeType(type));
continue;
case BOUND:
case BEGIN:
case END:
writeShort(INST_BOUND);
continue;
case THROW:
Object type = node.reference1;
writeShort(INST_THROW);
writeIndex(indexAcquire(type));
continue;
case LOAD_STATIC:
TableItem global = node.operand1;
if(node.weak)
{
writeShort(INST_LOAD_STATICW);
writeIndex(indexAcquire(global));
continue;
}
writeShort(formInstruction |= INST_LOAD_STATIC);
writeIndex(indexAcquire(global));
break;
case LOAD_LOCAL:
TypedItem local = (TypedItem) node.operand1;
if(node.weak)
{
writeShort(INST_LOAD_LOCALW | encodeType(REF));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
continue;
}
writeShort(formInstruction |= INST_LOAD_LOCAL | encodeType(local.type));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
break;
case LOAD_CONST:
Constant constant = (Constant) node.operand1;
if(constant.isReference())
{
Object reference = constant.asObject();
if(reference == null)
{
writeShort(INST_LOAD_CONST_NULL);
continue;
}
if(reference instanceof RequiredReflectItem)
{
writeShort(node.weak ? INST_LOAD_CONSTW : INST_LOAD_CONST);
writeIndex(indexAcquire(reference));
continue;
}
if(reference instanceof String)
{
writeShort(INST_LOAD_CONST);
writeIndex(indexAcquire(reference));
continue;
}
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.constant-value"), new Object[] { reference.getClass().canonicalName }));
}
Type type = constant.type;
if(type.isBoolean())
{
writeShort(INST_LOAD_CONST_BYTE | (constant.asBoolean() ? 0xff : 0x00));
continue;
}
if(type.isInt())
{
int value = constant.asInt();
if(value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
{
writeShort(INST_LOAD_CONST_BYTE | constant.asByte() & 0xff);
continue;
}
if(value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
{
writeShort(INST_LOAD_CONST_SHORT);
writeShort(value);
continue;
}
writeShort(INST_LOAD_CONST_INT);
writeInt(value);
continue;
}
writeShort(INST_LOAD_CONST);
writeIndex(indexAcquire(constant));
continue;
case READ_ELEMENT:
Type type = (Type) node.operand1;
Constant index = (Constant) node.operand2;
if(index != null)
{
writeShort(INST_READ_ELEMENTI | encodeVectorIndex(index.asInt()) | encodeType(type));
continue;
}
writeShort(INST_READ_ELEMENT | encodeType(type));
continue;
case READ_COMPONENT:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_READ_COMPONENT | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case READ_FIELD:
TableItem fieldoid = node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_READ_FIELD | encodeOperand(operand));
writeIndex(indexAcquire(fieldoid));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case READ_SPECIAL:
TableItem fieldoid = node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_READ_SPECIAL | encodeOperand(operand));
writeIndex(indexAcquire(fieldoid));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case READ_PROPERTY:
TableItem fieldoid = node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_READ_PROPERTY | encodeOperand(operand));
writeIndex(indexAcquire(fieldoid));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case STORE_STATIC:
TableItem global = node.operand1;
Constant constant = (Constant) node.operand2;
if(constant != null)
{
if(constant.isNull())
{
writeShort(INST_STORE_STATIC_NULL);
writeIndex(indexAcquire(global));
continue;
}
Type type = constant.type;
if(type.isBoolean())
{
writeShort(formInstruction |= INST_STORE_STATIC_SHORT);
writeIndex(indexAcquire(global));
writeShort(constant.asBoolean() ? -1 : 0);
break;
}
if(type.isInt())
{
int value = constant.asInt();
if(value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
{
writeShort(INST_STORE_STATIC_SHORT);
writeIndex(indexAcquire(global));
writeShort(value);
continue;
}
writeShort(INST_STORE_STATIC_INT);
writeIndex(indexAcquire(global));
writeInt(value);
continue;
}
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.assignable.global"), new Object[] { type }));
}
writeShort(formInstruction |= INST_STORE_STATIC);
writeIndex(indexAcquire(global));
break;
case STORE_LOCAL:
case DECLARE_WITH:
case DECLARE_LOCAL:
int store = nodeInstruction - (STORE_LOCAL - STORE_NORMAL);
TypedItem local = (TypedItem) node.operand1;
Constant constant = (Constant) node.operand2;
if(constant != null)
{
if(constant.isNull())
{
writeShort(INST_STORE_LOCAL_NULL | encodeStore(store) | encodeType(REF));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
continue;
}
Type type = constant.type;
if(type.isBoolean())
{
writeShort(formInstruction |= INST_STORE_LOCAL_SHORT | encodeStore(store) | encodeType(BOOLEAN));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
writeShort(constant.asBoolean() ? -1 : 0);
break;
}
if(type.isInt())
{
int value = constant.asInt();
if(value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
{
writeShort(INST_STORE_LOCAL_SHORT | encodeStore(store) | encodeType(type));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
writeShort(value);
continue;
}
writeShort(INST_STORE_LOCAL_INT | encodeStore(store) | encodeType(type));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
writeInt(value);
continue;
}
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.assignable.local"), new Object[] { type }));
}
writeShort(formInstruction |= INST_STORE_LOCAL | encodeStore(store) | encodeType(local.type));
writeIndex(local == thisArgument ? 0 : indexOf(local.specialSimpleName));
break;
case INC_PRED_LOAD_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_INC_PRED_LOAD_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case DEC_PRED_LOAD_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_DEC_PRED_LOAD_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case INC_POST_LOAD_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_INC_POST_LOAD_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case DEC_POST_LOAD_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_DEC_POST_LOAD_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case WRITE_COMPONENT:
Type type = (Type) node.operand1;
writeShort(formInstruction |= INST_WRITE_COMPONENT | encodeType(type));
break;
case WRITE_FIELD:
TableItem fieldoid = node.operand1;
writeShort(formInstruction |= INST_WRITE_FIELD);
writeIndex(indexAcquire(fieldoid));
break;
case WRITE_SPECIAL:
TableItem fieldoid = node.operand1;
writeShort(formInstruction |= INST_WRITE_SPECIAL);
writeIndex(indexAcquire(fieldoid));
break;
case WRITE_PROPERTY:
TableItem fieldoid = node.operand1;
writeShort(formInstruction |= INST_WRITE_PROPERTY);
writeIndex(indexAcquire(fieldoid));
break;
case BRANCH:
if(jlength > 0)
{
int min = node.getJumpCaseValueAt(0);
int max = min;
for(int jindex = 1; jindex < jlength; jindex++)
{
int cur = node.getJumpCaseValueAt(jindex);
if(min > cur) min = cur;
if(max < cur) max = cur;
}
Node jumpDefault = node.jumpDefault;
if(((long) max - min + 2) <= ((long) jlength << 1))
{
writeShort(INST_SWITCH_TABLE);
writeInt(min);
writeIndex(jlength = max - min + 1);
for(int jvalue = min, int jindex = 0; jindex < jlength; jvalue++, jindex++)
{
Node target = node.getJumpCase(jvalue);
if(target == null) target = jumpDefault;
writeLabel(target);
}
} else
{
writeShort(INST_SWITCH_LOOKUP);
writeIndex(jlength);
for(int jindex = 0; jindex < jlength; jindex++)
{
int jvalue = node.getJumpCaseValueAt(jindex);
Node target = node.getJumpCaseNodeAt(jindex);
writeInt(jvalue);
writeLabel(target);
}
}
writeLabel(jumpDefault);
continue;
}
/* падение через */
case JUMP:
case RETURN:
writeShort(INST_JUMP);
writeLabel(node.jumpDefault);
continue;
case LOAD_INTERRUPT:
TableItem callable = node.operand1;
writeShort(INST_LOAD_INTERRUPT);
writeIndex(indexAcquire(callable));
continue;
case REF_EQ:
TableItem operand = node.operand1;
writeShort(formInstruction |= (node.weak ? INST_REF_EQW : INST_REF_EQ) | encodeOperand(operand) | encodeType(REF));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case REF_NE:
TableItem operand = node.operand1;
writeShort(formInstruction |= (node.weak ? INST_REF_NEW : INST_REF_NE) | encodeOperand(operand) | encodeType(REF));
if(operand != null) writeIndex(operand == thisArgument ? 0 : !(operand instanceof Local) ? indexAcquire(operand) : indexOf(operand.specialSimpleName));
break;
case REF_IS_NULL:
writeShort(formInstruction |= (node.weak ? INST_REF_IS_NULLW : INST_REF_IS_NULL) | encodeType(REF));
break;
case REF_IS_OBJECT:
writeShort(formInstruction |= (node.weak ? INST_REF_IS_OBJECTW : INST_REF_IS_OBJECT) | encodeType(REF));
break;
case CLINIT_TRY_LOCK:
TableItem operand = node.operand1;
writeShort(formInstruction |= INST_CLINIT_TRY_LOCK);
writeIndex(indexAcquire(operand));
break;
case CLINIT_UNLOCK:
TableItem operand = node.operand1;
writeShort(INST_CLINIT_UNLOCK);
writeIndex(indexAcquire(operand));
continue;
case MONITOR_ENTER:
writeShort(INST_MONITOR_ENTER | encodeType(REF));
continue;
case MONITOR_LEAVE:
writeShort(INST_MONITOR_LEAVE | encodeType(REF));
continue;
case FINALLY_ENTER:
writeShort(INST_FINALLY_ENTER);
continue;
case FINALLY_LEAVE:
writeShort(INST_FINALLY_LEAVE);
continue;
case NEW_ARRAY:
TableItem type = node.operand1;
Constant length = (Constant) node.operand2;
writeShort(INST_NEW_ARRAY);
writeIndex(indexAcquire(type));
writeInt(length.asInt());
continue;
case INVOKE_FINALLY:
Node target = (Node) node.reference1;
writeShort(INST_INVOKE_FINALLY);
writeLabel(target);
continue;
case INVOKE_STATIC:
TableItem callable = node.operand1;
writeShort(formInstruction |= node.weak ? INST_INVOKE_STATICD : INST_INVOKE_STATIC);
writeIndex(indexAcquire(callable));
break;
case INVOKE_SPECIAL:
TableItem callable = node.operand1;
writeShort(formInstruction |= node.weak ? INST_INVOKE_SPECIALD : INST_INVOKE_SPECIAL);
writeIndex(indexAcquire(callable));
break;
case INVOKE_VIRTUAL:
TableItem callable = node.operand1;
writeShort(formInstruction |= node.weak ? INST_INVOKE_VIRTUALD : INST_INVOKE_VIRTUAL);
writeIndex(indexAcquire(callable));
break;
case INVOKE_SERVICE:
TableItem callable = node.operand1;
writeShort(formInstruction |= node.weak ? INST_INVOKE_SERVICED : INST_INVOKE_SERVICE);
writeIndex(indexAcquire(callable));
break;
case O_VECT_DIV:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_DIV | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_PCK:
Type type = (Type) node.operand1;
writeShort(INST_VECT_PCK | encodeType(type));
continue;
case O_VECT_LUP:
Type type = (Type) node.operand1;
writeShort(INST_VECT_LUP | encodeType(type));
continue;
case O_VECT_UUP:
Type type = (Type) node.operand1;
writeShort(INST_VECT_UUP | encodeType(type));
continue;
case O_VECT_MUL:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_MUL | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SHL:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SHL | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SHR:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SHR | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SHRU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SHRU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_ADD:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_ADD | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SUB:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SUB | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_EQ:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_EQ | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_NE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_NE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_GT:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_GT | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_GE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_GE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_LT:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_LT | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_LE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_LE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_DIV:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_DIV | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_DIVU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_DIVU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_REM:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_REM | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_REMU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_REMU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_MUL:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_MUL | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_SHL:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_SHL | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_SHR:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_SHR | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_SHRU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_SHRU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_ADD:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_ADD | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_SUB:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_SCAL_SUB | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_EQ:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_EQ | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_SCAL_NE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_NE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_SCAL_GT:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_GT | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_SCAL_GE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_GE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_SCAL_LT:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_LT | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_SCAL_LE:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_SCAL_LE | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_VECT_NEG:
Type type = (Type) node.operand1;
writeShort(INST_VECT_NEG | encodeType(type));
continue;
case CAST_TO:
TableItem newType = node.operand1;
Type oldType = (Type) node.operand2;
writeShort(INST_CAST_TO | encodeType(oldType));
writeIndex(indexAcquire(newType));
continue;
case INC_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_INC_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case DEC_LOCAL:
TypedItem local = (TypedItem) node.operand1;
writeShort(INST_DEC_LOCAL | encodeType(local.type));
writeIndex(indexOf(local.specialSimpleName));
continue;
case O_BIT_NOT:
Type type = (Type) node.operand1;
writeShort(formInstruction |= INST_BIT_NOT | encodeType(type));
break;
case O_BIT_AND:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_BIT_AND | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_BIT_OR:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_BIT_OR | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case O_BIT_XOR:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_BIT_XOR | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case DUP1:
Type type = (Type) node.operand1;
writeShort(INST_DUP1 | encodeType(type));
continue;
case DUP2:
Type type = (Type) node.operand1;
writeShort(INST_DUP2 | encodeType(type));
continue;
case O_VECT_HMUL:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_HMUL | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_HMULU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_HMULU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SADD:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SADD | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SADDU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SADDU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SSUB:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SSUB | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_VECT_SSUBU:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(INST_VECT_SSUBU | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
continue;
case O_SCAL_NEG:
Type type = (Type) node.operand1;
writeShort(INST_SCAL_NEG | encodeType(type));
continue;
case INSTANCEOF:
TableItem type = node.operand1;
writeShort(formInstruction |= INST_INSTANCE_OF | encodeType(REF));
writeIndex(indexAcquire(type));
break;
case TEST_EQZ:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_TEST_EQZ | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case TEST_NEZ:
Type type = (Type) node.operand1;
TableItem operand = node.operand2;
writeShort(formInstruction |= INST_TEST_NEZ | encodeOperand(operand) | encodeType(type));
if(operand != null) writeIndex(operand instanceof Local ? indexOf(operand.specialSimpleName) : indexAcquire(operand));
break;
case NEW_VECTOR:
Type type = (Type) node.operand1;
writeShort(INST_NEW_VECTOR | encodeType(type));
continue;
case NEW_INSTANCE:
TableItem type = node.operand1;
writeShort(INST_NEW_INSTANCE);
writeIndex(indexAcquire(type));
continue;
case NEW_ARRAY_MONO:
TableItem type = node.operand1;
writeShort(INST_NEW_ARRAY_MONO);
writeIndex(indexAcquire(type));
continue;
case NEW_ARRAY_MULTI:
TableItem type = node.operand1;
writeShort(INST_NEW_ARRAY_MULTI);
writeIndex(indexAcquire(type));
continue;
case DUP1X1:
Type type = (Type) node.operand1;
writeShort(INST_DUP1X1 | encodeType(type));
continue;
case DUP1X2:
Type type = (Type) node.operand1;
writeShort(INST_DUP1X2 | encodeType(type));
continue;
case METHOD_LEAVE:
writeShort(INST_METHOD_LEAVE);
continue;
case EXCEPT_ENTER:
writeShort(INST_EXCEPT_ENTER);
continue;
case EXCEPT_TRY:
Node begin = (Node) node.reference1;
Node end = (Node) node.reference2;
writeShort(INST_EXCEPT_TRY);
writeLabel(begin);
writeLabel(end);
continue;
case EXCEPT_CATCH:
Node block = (Node) node.reference1;
Object type = node.reference2;
writeShort(INST_EXCEPT_CATCH);
writeLabel(block);
writeIndex(indexAcquire(type));
continue;
case EXCEPT_FINALLY:
Node block = (Node) node.reference1;
writeShort(INST_EXCEPT_FINALLY);
writeLabel(block);
continue;
case EXCEPT_LEAVE:
writeShort(INST_EXCEPT_LEAVE);
continue;
default:
throw new UnencodableDataException(String.format(package.getResourceString("not-encodable.instruction"), new Object[] { Int.toHexString(nodeInstruction) }));
}
if((formInstruction & FLAG_BOOLEAN_JUMP) != 0)
{
writeLabel(node.jumpIsTrue);
writeLabel(node.jumpIsFalse);
}
}
}
return stream.toByteArray();
}
protected void afterConstruction() { operator +(null); }
private int indexAcquire(Object element) throws IOException {
if(element instanceof Constant)
{
Constant constant = (Constant) element;
if(constant.isReference())
{
element = constant.asObject();
}
else if(constant.isBoolean())
{
element = constant.asBoolean() ? Boolean.TRUE : Boolean.FALSE;
}
else switch(constant.type.kind)
{
case CHAR:
element = new Char(constant.asChar());
break;
case REAL:
element = new Real(constant.asReal());
break;
case DOUBLE:
element = new Double(constant.asDouble());
break;
case DOUBLE2:
element = new Double2(constant.asDouble2());
break;
case DOUBLE4:
element = new Double4(constant.asDouble4());
break;
case DOUBLE8:
element = new Double8(constant.asDouble8());
break;
case FLOAT:
element = new Float(constant.asFloat());
break;
case FLOAT2:
element = new Float2(constant.asFloat2());
break;
case FLOAT4:
element = new Float4(constant.asFloat4());
break;
case FLOAT8:
element = new Float8(constant.asFloat8());
break;
case BYTE:
element = new Byte(constant.asByte());
break;
case BYTE2:
element = new Byte2(constant.asByte2());
break;
case BYTE4:
element = new Byte4(constant.asByte4());
break;
case BYTE8:
element = new Byte8(constant.asByte8());
break;
case SHORT:
element = new Short(constant.asShort());
break;
case SHORT2:
element = new Short2(constant.asShort2());
break;
case SHORT4:
element = new Short4(constant.asShort4());
break;
case SHORT8:
element = new Short8(constant.asShort8());
break;
case INT:
element = new Int(constant.asInt());
break;
case INT2:
element = new Int2(constant.asInt2());
break;
case INT4:
element = new Int4(constant.asInt4());
break;
case INT8:
element = new Int8(constant.asInt8());
break;
case LONG:
element = new Long(constant.asLong());
break;
case LONG2:
element = new Long2(constant.asLong2());
break;
case LONG4:
element = new Long4(constant.asLong4());
break;
case LONG8:
element = new Long8(constant.asLong8());
}
}
int result = indexOf(element);
if(result < 0)
{
if(element instanceof String && ((String) element).length > 0xffff)
{
throw new UnencodableDataException(package.getResourceString("not-encodable.too-long-string"));
}
label0:
{
if(element instanceof RequiredReflectItem) with((TableItem) element)
{
indexAcquire(recompilableName);
break label0;
}
if(element instanceof Fieldoid) with((Member) element)
{
indexAcquire(parentType);
indexAcquire(recompilableName);
break label0;
}
if(element instanceof Callable) with((Callable) element, arguments)
{
indexAcquire(parentType);
indexAcquire(recompilableName);
for(int length = length, int index = 0; index < length; index++) indexAcquire(operator [](index).type);
}
}
result = operator +(element).length - 1;
}
return result;
}
}
helper BinarySourceGeneratorCodeDataOutput: DataOutput
{
public void writeIndex(int index) throws IOException {
if(index <= Short.MAX_VALUE)
{
writeShort(index);
} else
{
writeInt(Int.MIN_VALUE | index);
}
}
public void writeLabel(Node target) throws IOException {
int index;
int encoded = AVTOORecompilable.encodeNext();
if((index = target.debugIndex) >= 0)
{
encoded = AVTOORecompilable.encodeUsing(~index);
}
else if((index = target.labelIndex) >= 0)
{
encoded = AVTOORecompilable.encodeUsing(index);
}
if(AVTOORecompilable.isLongEncoded(encoded))
{
writeInt(encoded);
} else
{
writeShort(encoded);
}
}
}