/Libraries/JManaVaLib/Source/org/managarm/jmanavalib/utils/VaWriter.java
Java | 817 lines | 604 code | 118 blank | 95 comment | 151 complexity | 43da6b1c1d0a189a55c32012050b3154 MD5 | raw file
Possible License(s): GPL-3.0
- /* This file is part of the Managarm operating system.
- * Copyright (C) 2007, 2008, 2009 Alexander van der Grinten
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
- package org.managarm.jmanavalib.utils;
- // import java util classes
- import java.util.Iterator;
- import java.util.HashMap;
- import java.util.ArrayList;
- import java.io.OutputStream;
- import java.io.IOException;
- // import managarm virtual architecture
- import org.managarm.jmanavalib.core.VaClass;
- import org.managarm.jmanavalib.core.VaDatatype;
- import org.managarm.jmanavalib.core.VaClsInfo;
- import org.managarm.jmanavalib.core.VaMthInfo;
- import org.managarm.jmanavalib.core.VaFldInfo;
- import org.managarm.jmanavalib.core.VaProcedure;
- import org.managarm.jmanavalib.core.VaFrame;
- import org.managarm.jmanavalib.core.VaInst;
- import org.managarm.jmanavalib.core.VaLiteral;
- public class VaWriter {
- private static final int CNST_NULL = 0;
-
- private static final int VAIMG_VERSION = 1;
- private static final int VAIMG_MODEL = 2;
-
- // constant type ids
- private static final short CNST_CLSINFO = 1;
- private static final short CNST_MTHINFO = 2;
- private static final short CNST_FLDINFO = 3;
- private static final short CNST_PRIMTYPE = 4;
- private static final short CNST_CLSTYPE = 5;
- private static final short CNST_ARRTYPE = 6;
- private static final short CNST_DLGTYPE = 10;
- private static final short CNST_CARR_LITERAL = 7;
- private static final short CNST_INT_LITERAL = 8;
- private static final short CNST_UINT_LITERAL = 9;
- private static final short CNST_CHAR_LITERAL = 20;
- private static final short CNST_LIT_BOOLEAN = 21;
- private static final short CNST_LIT_NULL = 22;
-
- // operation code constants
- private static final short OPCODE_RETURN = 1;
- private static final short OPCODE_LOAD = 2;
- private static final short OPCODE_INVOKE_VIRT_RES = 3;
- private static final short OPCODE_INVOKE_VIRT_VOID = 4;
- private static final short OPCODE_INVOKE_STAT_RES = 5;
- private static final short OPCODE_INVOKE_STAT_VOID = 6;
- private static final short OPCODE_BINOP_ARITH_ADD = 7;
- private static final short OPCODE_BINOP_ARITH_SUB = 8;
- private static final short OPCODE_BINOP_ARITH_MUL = 9;
- private static final short OPCODE_BINOP_ARITH_DIV = 10;
- private static final short OPCODE_BINOP_ARITH_MOD = 11;
- private static final short OPCODE_BINOP_ARITH_OR = 12;
- private static final short OPCODE_BINOP_ARITH_AND = 13;
- private static final short OPCODE_BINOP_ARITH_XOR = 14;
- private static final short OPCODE_BINOP_ARITH_SHL = 15;
- private static final short OPCODE_BINOP_ARITH_SHR = 16;
- private static final short OPCODE_BINOP_SETIF_EQUALS = 17;
- private static final short OPCODE_BINOP_SETIF_ABOVE = 18;
- private static final short OPCODE_BINOP_SETIF_BELOW = 19;
- private static final short OPCODE_UNOP_ARITH_NOT = 20;
- private static final short OPCODE_UNOP_ARITH_NEG = 21;
- private static final short OPCODE_UNOP_ARR_SIZE = 22;
- private static final short OPCODE_JUMP = 23;
- private static final short OPCODE_CREATE_OBJECT = 24;
- private static final short OPCODE_CREATE_ARRAY = 25;
- private static final short OPCODE_ARRACC_LOAD = 26;
- private static final short OPCODE_ARRACC_STORE = 27;
- private static final short OPCODE_FLDACC_LOAD = 28;
- private static final short OPCODE_FLDACC_STORE = 29;
- private static final short OPCODE_CAST = 30;
- private static final short OPCODE_INSTANCEOF = 31;
- private static final short OPCODE_DLG_CONSTRUCT = 32;
- private static final short OPCODE_CATCH = 33;
- private static final short OPCODE_THROW = 34;
- private static final short OPCODE_PASS = 35;
- private static final short OPCODE_LEAVE = 36;
-
- // instruction set extension constants
- private static final short OPCODE_EXT0 = 255;
-
- // first opcode extension
- private static final long EXT0_XNAT_METHOD_ADDRESS = 1;
- private static final long EXT0_XNAT_SIZEOF_OBJECT = 2;
- private static final long EXT0_XNAT_SIZEOF_ARRAY = 3;
- private static final long EXT0_XNAT_ADDRESS_CAST = 4;
- private static final long EXT0_XNAT_ADDRESS_OF = 5;
- private static final long EXT0_XNAT_MAKE_OBJECT = 6;
- private static final long EXT0_XNAT_MAKE_ARRAY = 7;
- private static final long EXT0_XNAT_MAKE_DELEGATE = 8;
- private static final long EXT0_XNAT_REF_INCREMENT = 9;
- private static final long EXT0_XNAT_REF_DECREMENT = 10;
- private static final long EXT0_XATOM_CAS_RESULT = 100;
- private static final long EXT0_XATOM_CAS_VOID = 101;
- private static final long EXT0_XPERF_ARRAY_COPY = 200;
-
- // constant maps
- private final HashMap<Object, Integer> cnstMap = new HashMap<Object, Integer>();
- private final HashMap<String, Integer> stringMap = new HashMap<String, Integer>();
-
- // constant arrays
- private final ArrayList<Object> cnstList = new ArrayList<Object>();
- private final ArrayList<String> stringList = new ArrayList<String>();
-
- private final VaImage image;
- private int classCnt = 0;
- private int methodCnt = 0;
-
- public VaWriter(VaImage image) throws ValibException {
- // save the image
- this.image = image;
-
- // analyze the classes
- final Iterator<VaClsInfo> clsiter = image.classIterator();
- while(clsiter.hasNext()) {
- final VaClsInfo clsinfo = clsiter.next();
- mergeConst(clsinfo);
- analyzeClass(image.getClass(clsinfo));
- classCnt++;
- }
-
- // analyze the methods
- final Iterator<VaMthInfo> seciter = image.methodIterator();
- while(seciter.hasNext()) {
- final VaMthInfo mthinfo = seciter.next();
- mergeConst(mthinfo);
- analyzeSection(image.getMethod(mthinfo));
- methodCnt++;
- }
- }
-
- // write the image to the stream
- public void write(OutputStream stream) throws ValibException {
- // write the header
- writeUInt(VAIMG_VERSION, stream);
- writeUInt(VAIMG_MODEL, stream);
-
- // write the string count
- writeUInt(stringList.size(), stream);
-
- // write the strings
- for(int i = 0; i < stringList.size(); i++) {
- final String string = stringList.get(i);
-
- // write the string length
- writeUInt(string.length(), stream);
-
- // write the chars
- for(int j = 0; j < string.length(); j++) {
- if(string.charAt(j) >= 0xFF) {
- writeUByte((short)0xFF, stream);
- writeUInt((long)string.charAt(j), stream);
- }else{
- writeUByte((short)string.charAt(j), stream);
- }
- }
- }
-
- // write the constant count
- writeUInt(cnstList.size(), stream);
-
- // write the constants
- for(int i = 0; i < cnstList.size(); i++) {
- final Object cnst = cnstList.get(i);
-
- if(cnst instanceof VaClsInfo) {
- final VaClsInfo info = (VaClsInfo)cnst;
-
- // write the constant's type
- writeUByte(CNST_CLSINFO, stream);
-
- // write the class' identifier and version
- writeUInt(stringMap.get(info.ident), stream);
- writeUInt(info.major, stream);
- writeUInt(info.minor, stream);
- writeUInt(info.revision, stream);
-
- // write the flags
- writeUInt(info.flags0, stream);
- }else if(cnst instanceof VaMthInfo) {
- final VaMthInfo info = (VaMthInfo)cnst;
-
- // write the constant's type
- writeUByte(CNST_MTHINFO, stream);
-
- // write the identifier
- writeUInt(stringMap.get(info.ident), stream);
-
- // write the flags
- writeUInt(info.flags0, stream);
-
- // write the class
- writeUInt(cnstMap.get(info.clsInfo), stream);
-
- // write the return type
- writeUInt(cnstMap.get(info.returnType), stream);
-
- // write the argument count
- writeUInt(info.getArgumentCnt(), stream);
-
- // write the arguments
- for(int j = 0; j < info.getArgumentCnt(); j++) {
- writeUInt(cnstMap.get(info.getArgument(j)), stream);
- }
- }else if(cnst instanceof VaFldInfo) {
- final VaFldInfo info = (VaFldInfo)cnst;
-
- // write the constant's type
- writeUByte(CNST_FLDINFO, stream);
-
- // write the identifier
- writeUInt(stringMap.get(info.ident), stream);
-
- // write the flags
- writeUInt(info.flags0, stream);
-
- // write the class
- writeUInt(cnstMap.get(info.clsInfo), stream);
-
- // write the type
- writeUInt(cnstMap.get(info.datatype), stream);
- }else if(cnst instanceof VaDatatype.DtPrimitive) {
- final VaDatatype.DtPrimitive type
- = (VaDatatype.DtPrimitive)cnst;
-
- // write the constant's type
- writeUByte(CNST_PRIMTYPE, stream);
-
- // write the primitive id
- writeUByte(type.identity, stream);
- }else if(cnst instanceof VaDatatype.DtArray) {
- final VaDatatype.DtArray type = (VaDatatype.DtArray)cnst;
-
- // write the constant's type
- writeUByte(CNST_ARRTYPE, stream);
-
- // write the base type and flag fields
- writeUInt(cnstMap.get(type.basetype), stream);
- writeUInt(type.flags0, stream);
- }else if(cnst instanceof VaDatatype.DtClass) {
- final VaDatatype.DtClass type = (VaDatatype.DtClass)cnst;
-
- // write the constant's type
- writeUByte(CNST_CLSTYPE, stream);
-
- // write the class info
- writeUInt(cnstMap.get(type.clsInfo), stream);
- }else if(cnst instanceof VaDatatype.DtDelegate) {
- final VaDatatype.DtDelegate type = (VaDatatype.DtDelegate)cnst;
-
- // write the constant's type
- writeUByte(CNST_DLGTYPE, stream);
-
- // write the return type
- writeUInt(cnstMap.get(type.returnType), stream);
-
- writeUInt(type.getArgumentCnt(), stream);
-
- // write the argument types
- for(int j = 0; j < type.getArgumentCnt(); j++)
- writeUInt(cnstMap.get(type.getArgument(j)), stream);
- }else if(cnst instanceof VaLiteral.LitNull) {
- // write the constant's type
- writeUByte(CNST_LIT_NULL, stream);
- }else if(cnst instanceof VaLiteral.LitUInt) {
- final VaLiteral.LitUInt literal = (VaLiteral.LitUInt)cnst;
-
- // write the constant's type
- writeUByte(CNST_UINT_LITERAL, stream);
-
- // write the value
- writeUInt(literal.value, stream);
- }else if(cnst instanceof VaLiteral.LitChar) {
- final VaLiteral.LitChar literal = (VaLiteral.LitChar)cnst;
-
- // write the constant's type
- writeUByte(CNST_CHAR_LITERAL, stream);
-
- // write the value
- writeUInt((int)literal.value, stream);
- }else if(cnst instanceof VaLiteral.LitBoolean) {
- final VaLiteral.LitBoolean literal = (VaLiteral.LitBoolean)cnst;
-
- // write the constant's type
- writeUByte(CNST_LIT_BOOLEAN, stream);
-
- // write the value
- writeUByte((byte)(literal.value ? 1 : 0), stream);
- }else if(cnst instanceof VaLiteral.LitCharArray) {
- final VaLiteral.LitCharArray literal = (VaLiteral.LitCharArray)cnst;
-
- // write the constant's type
- writeUByte(CNST_CARR_LITERAL, stream);
-
- // write the char count
- writeUInt(literal.size(), stream);
-
- // write the chars
- for(int j = 0; j < literal.size(); j++)
- writeUInt(literal.get(j), stream);
- }else{
- throw new ValibException("Unknown constant " + cnst.getClass().getSimpleName());
- }
- }
-
- // write the classes count
- writeUInt(classCnt, stream);
-
- // write the classes
- final Iterator<VaClsInfo> clsiter = image.classIterator();
- while(clsiter.hasNext()) {
- final VaClsInfo clsinfo = clsiter.next();
- final VaClass cls = image.getClass(clsinfo);
-
- // write the class info
- writeUInt(cnstMap.get(clsinfo), stream);
-
- // write the parent info
- if(cls.parentInfo != null) {
- writeUInt(cnstMap.get(cls.parentInfo), stream);
- }else{
- writeUInt(CNST_NULL, stream);
- }
-
- // write the method count
- writeUInt(cls.getMethodCnt(), stream);
-
- // write the methods
- for(int i = 0; i < cls.getMethodCnt(); i++) {
- writeUInt(cnstMap.get(cls.getMethod(i)), stream);
- }
-
- // write the field count
- writeUInt(cls.getFieldCnt(), stream);
-
- // write the fields
- for(int i = 0; i < cls.getFieldCnt(); i++) {
- writeUInt(cnstMap.get(cls.getField(i)), stream);
- }
- }
-
- // write the section count
- writeUInt(methodCnt, stream);
-
- final Iterator<VaMthInfo> mthiter = image.methodIterator();
- while(mthiter.hasNext()) {
- final VaMthInfo mthinfo = mthiter.next();
- final VaProcedure procedure = image.getMethod(mthinfo);
-
- // write the method description
- writeUInt(cnstMap.get(mthinfo), stream);
- // write the procedure
- writeProcedure(procedure, stream);
- }
- }
-
- private void writeProcedure(final VaProcedure procedure,
- final OutputStream stream) throws ValibException {
- // write the frame count
- writeUInt(procedure.getFrameCnt(), stream);
-
- for(int j = 0; j < procedure.getFrameCnt(); j++) {
- final VaFrame frame = procedure.getFrame(j);
-
- // write the argument count
- writeUInt(frame.argumentCnt, stream);
-
- // write the register count
- writeUInt(frame.getRegisterCnt(), stream);
-
- // write the register types
- for(int k = 0; k < frame.getRegisterCnt(); k++)
- writeUInt(cnstMap.get(frame.getRegister(k)), stream);
- // write the instruction count
- writeUInt(frame.getInstCnt(), stream);
-
- // write the instructions
- for(int k = 0; k < frame.getInstCnt(); k++) {
- final VaInst opcode = frame.getInst(k);
-
- if(opcode instanceof VaInst.InstReturn) {
- final VaInst.InstReturn inst = (VaInst.InstReturn)opcode;
- writeUByte(OPCODE_RETURN, stream);
- writeUInt(inst.register, stream);
- }else if(opcode instanceof VaInst.InstLoad) {
- final VaInst.InstLoad inst = (VaInst.InstLoad)opcode;
- writeUByte(OPCODE_LOAD, stream);
- writeUInt(cnstMap.get(inst.literal), stream);
- }else if(opcode instanceof VaInst.InstInvoke) {
- final VaInst.InstInvoke inst = (VaInst.InstInvoke)opcode;
- if(inst.virtual && inst.result) {
- writeUByte(OPCODE_INVOKE_VIRT_RES, stream);
- }else if(inst.virtual && !inst.result) {
- writeUByte(OPCODE_INVOKE_VIRT_VOID, stream);
- }else if(!inst.virtual && inst.result) {
- writeUByte(OPCODE_INVOKE_STAT_RES, stream);
- }else if(!inst.virtual && !inst.result){
- writeUByte(OPCODE_INVOKE_STAT_VOID, stream);
- }
- if(inst.mthInfo == null) {
- writeUInt(0, stream);
- }else{
- writeUInt(cnstMap.get(inst.mthInfo), stream);
- }
- writeRegister(inst.object, stream);
- writeUInt(inst.getArgumentCnt(), stream);
- for(int i = 0; i < inst.getArgumentCnt(); i++)
- writeRegister(inst.getArgument(i), stream);
- }else if(opcode instanceof VaInst.InstBinOperation) {
- final VaInst.InstBinOperation inst = (VaInst.InstBinOperation)opcode;
-
- if(inst.operator == VaInst.InstBinOperation.OP_ARITH_ADD) {
- writeUByte(OPCODE_BINOP_ARITH_ADD, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SUB) {
- writeUByte(OPCODE_BINOP_ARITH_SUB, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_MUL) {
- writeUByte(OPCODE_BINOP_ARITH_MUL, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_DIV) {
- writeUByte(OPCODE_BINOP_ARITH_DIV, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_MOD) {
- writeUByte(OPCODE_BINOP_ARITH_MOD, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_OR) {
- writeUByte(OPCODE_BINOP_ARITH_OR, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_AND) {
- writeUByte(OPCODE_BINOP_ARITH_AND, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_XOR) {
- writeUByte(OPCODE_BINOP_ARITH_XOR, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SHL) {
- writeUByte(OPCODE_BINOP_ARITH_SHL, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_ARITH_SHR) {
- writeUByte(OPCODE_BINOP_ARITH_SHR, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_EQUALS) {
- writeUByte(OPCODE_BINOP_SETIF_EQUALS, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_ABOVE) {
- writeUByte(OPCODE_BINOP_SETIF_ABOVE, stream);
- }else if(inst.operator == VaInst.InstBinOperation.OP_SETIF_BELOW) {
- writeUByte(OPCODE_BINOP_SETIF_BELOW, stream);
- }else{
- throw new UnsupportedOperationException("Invalid operator for InstBinOperation");
- }
-
- writeUInt(inst.left, stream);
- writeUInt(inst.right, stream);
- }else if(opcode instanceof VaInst.InstUnOperation) {
- final VaInst.InstUnOperation inst = (VaInst.InstUnOperation)opcode;
-
- if(inst.operator == VaInst.InstUnOperation.OP_ARITH_NOT) {
- writeUByte(OPCODE_UNOP_ARITH_NOT, stream);
- }else if(inst.operator == VaInst.InstUnOperation.OP_ARITH_NEG) {
- writeUByte(OPCODE_UNOP_ARITH_NEG, stream);
- }else if(inst.operator == VaInst.InstUnOperation.OP_ARR_SIZE) {
- writeUByte(OPCODE_UNOP_ARR_SIZE, stream);
- }
-
- writeUInt(inst.operand, stream);
- }else if(opcode instanceof VaInst.InstJump) {
- final VaInst.InstJump inst = (VaInst.InstJump)opcode;
-
- writeUByte(OPCODE_JUMP, stream);
- writeUInt(inst.frameId, stream);
- writeRegister(inst.register, stream);
-
- writeUInt(inst.getArgumentCnt(), stream);
- for(int i = 0; i < inst.getArgumentCnt(); i++)
- writeRegister(inst.getArgument(i), stream);
- }else if(opcode instanceof VaInst.InstCreateObject) {
- final VaInst.InstCreateObject inst = (VaInst.InstCreateObject)opcode;
-
- writeUByte(OPCODE_CREATE_OBJECT, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- }else if(opcode instanceof VaInst.InstCreateArray) {
- final VaInst.InstCreateArray inst = (VaInst.InstCreateArray)opcode;
-
- writeUByte(OPCODE_CREATE_ARRAY, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- writeUInt(inst.size, stream);
- }else if(opcode instanceof VaInst.InstArrAccess) {
- final VaInst.InstArrAccess inst = (VaInst.InstArrAccess)opcode;
-
- if(inst.operator == VaInst.InstArrAccess.OP_LOAD) {
- writeUByte(OPCODE_ARRACC_LOAD, stream);
- }else if(inst.operator == VaInst.InstArrAccess.OP_STORE) {
- writeUByte(OPCODE_ARRACC_STORE, stream);
- }
-
- writeUInt(inst.array, stream);
- writeUInt(inst.index, stream);
- writeUInt(inst.operand, stream);
- }else if(opcode instanceof VaInst.InstFldAccess) {
- final VaInst.InstFldAccess inst = (VaInst.InstFldAccess)opcode;
-
- if(inst.operator == VaInst.InstFldAccess.OP_LOAD) {
- writeUByte(OPCODE_FLDACC_LOAD, stream);
- }else if(inst.operator == VaInst.InstFldAccess.OP_STORE) {
- writeUByte(OPCODE_FLDACC_STORE, stream);
- }
-
- writeUInt(cnstMap.get(inst.fldInfo), stream);
- writeUInt(inst.object, stream);
- writeUInt(inst.operand, stream);
- }else if(opcode instanceof VaInst.InstCast) {
- final VaInst.InstCast inst = (VaInst.InstCast)opcode;
-
- writeUByte(OPCODE_CAST, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- writeUInt(inst.source, stream);
- }else if(opcode instanceof VaInst.InstInstanceof) {
- final VaInst.InstInstanceof inst = (VaInst.InstInstanceof)opcode;
-
- writeUByte(OPCODE_INSTANCEOF, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- writeUInt(inst.object, stream);
- }else if(opcode instanceof VaInst.InstDlgConstruct) {
- final VaInst.InstDlgConstruct inst
- = (VaInst.InstDlgConstruct)opcode;
-
- writeUByte(OPCODE_DLG_CONSTRUCT, stream);
- writeUInt(cnstMap.get(inst.method), stream);
- writeUInt(inst.object, stream);
- }else if(opcode instanceof VaInst.InstCatch) {
- final VaInst.InstCatch inst = (VaInst.InstCatch)opcode;
- writeUByte(OPCODE_CATCH, stream);
- writeUInt(inst.frame, stream);
- writeUInt(inst.getArgumentCnt(), stream);
- for(int i = 0; i < inst.getArgumentCnt(); i++)
- writeUInt(inst.getArgument(i), stream);
- writeProcedure(inst.procedure, stream);
- }else if(opcode instanceof VaInst.InstThrow) {
- final VaInst.InstThrow inst = (VaInst.InstThrow)opcode;
- writeUByte(OPCODE_THROW, stream);
- writeUInt(inst.exception, stream);
- }else if(opcode instanceof VaInst.InstPass) {
- final VaInst.InstPass inst = (VaInst.InstPass)opcode;
- writeUByte(OPCODE_PASS, stream);
- writeUInt(inst.argument, stream);
- writeUInt(inst.register, stream);
- }else if(opcode instanceof VaInst.InstLeave) {
- writeUByte(OPCODE_LEAVE, stream);
- }else if(opcode instanceof VaInst.InstXNatSizeofObject) {
- final VaInst.InstXNatSizeofObject inst = (VaInst.InstXNatSizeofObject)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XNAT_SIZEOF_OBJECT, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- }else if(opcode instanceof VaInst.InstXNatMthAddress) {
- final VaInst.InstXNatMthAddress inst = (VaInst.InstXNatMthAddress)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XNAT_METHOD_ADDRESS, stream);
- writeUInt(cnstMap.get(inst.method), stream);
- }else if(opcode instanceof VaInst.InstXNatAddressCast) {
- final VaInst.InstXNatAddressCast inst = (VaInst.InstXNatAddressCast)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XNAT_ADDRESS_CAST, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- writeUInt(inst.address, stream);
- }else if(opcode instanceof VaInst.InstXNatAddressOf) {
- final VaInst.InstXNatAddressOf inst = (VaInst.InstXNatAddressOf)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XNAT_ADDRESS_OF, stream);
- writeUInt(inst.address, stream);
- writeUInt(inst.object, stream);
- }else if(opcode instanceof VaInst.InstXNatMakeDelegate) {
- final VaInst.InstXNatMakeDelegate inst = (VaInst.InstXNatMakeDelegate)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XNAT_MAKE_DELEGATE, stream);
- writeUInt(cnstMap.get(inst.datatype), stream);
- writeUInt(inst.method, stream);
- writeUInt(inst.object, stream);
- }else if(opcode instanceof VaInst.InstXNatRefOperation) {
- final VaInst.InstXNatRefOperation inst
- = (VaInst.InstXNatRefOperation)opcode;
- writeUByte(OPCODE_EXT0, stream);
- if(inst.operation == VaInst.InstXNatRefOperation.REF_INCREMENT) {
- writeUInt(EXT0_XNAT_REF_INCREMENT, stream);
- }else{
- writeUInt(EXT0_XNAT_REF_DECREMENT, stream);
- }
- writeUInt(inst.register, stream);
- }else if(opcode instanceof VaInst.InstXAtomCas) {
- final VaInst.InstXAtomCas inst = (VaInst.InstXAtomCas)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- if(inst.result) {
- writeUInt(EXT0_XATOM_CAS_RESULT, stream);
- }else{
- writeUInt(EXT0_XATOM_CAS_VOID, stream);
- }
- writeUInt(cnstMap.get(inst.field), stream);
- writeUInt(inst.object, stream);
- writeUInt(inst.source, stream);
- writeUInt(inst.value, stream);
- }else if(opcode instanceof VaInst.InstXPerfArrayCopy) {
- final VaInst.InstXPerfArrayCopy inst = (VaInst.InstXPerfArrayCopy)opcode;
-
- writeUByte(OPCODE_EXT0, stream);
- writeUInt(EXT0_XPERF_ARRAY_COPY, stream);
- writeUInt(inst.dest, stream);
- writeUInt(inst.source, stream);
- writeUInt(inst.destOffset, stream);
- writeUInt(inst.sourceOffset, stream);
- writeUInt(inst.size, stream);
- }else{
- throw new UnsupportedOperationException("Invalid instruction");
- }
- }
- }
- }
-
- private void analyzeClass(VaClass cls) throws ValibException {
- if(cls.parentInfo != null)
- mergeConst(cls.parentInfo);
-
- // merge the method descs
- for(int i = 0; i < cls.getMethodCnt(); i++)
- mergeConst(cls.getMethod(i));
-
- // merge the field desc
- for(int i = 0; i < cls.getFieldCnt(); i++)
- mergeConst(cls.getField(i));
- }
-
- private void analyzeSection(VaProcedure procedure) throws ValibException {
- for(int i = 0; i < procedure.getFrameCnt(); i++) {
- final VaFrame frame = procedure.getFrame(i);
-
- for(int j = 0; j < frame.getRegisterCnt(); j++)
- mergeConst(frame.getRegister(j));
-
- for(int j = 0; j < frame.getInstCnt(); j++) {
- final VaInst opcode = frame.getInst(j);
-
- if(opcode instanceof VaInst.InstLoad) {
- final VaInst.InstLoad inst = (VaInst.InstLoad)opcode;
- mergeConst(inst.literal);
- }else if(opcode instanceof VaInst.InstInvoke) {
- final VaInst.InstInvoke inst = (VaInst.InstInvoke)opcode;
- if(inst.mthInfo != null)
- mergeConst(inst.mthInfo);
- }else if(opcode instanceof VaInst.InstFldAccess) {
- final VaInst.InstFldAccess inst = (VaInst.InstFldAccess)opcode;
- mergeConst(inst.fldInfo);
- }else if(opcode instanceof VaInst.InstCreateObject) {
- final VaInst.InstCreateObject inst = (VaInst.InstCreateObject)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstCreateArray) {
- final VaInst.InstCreateArray inst = (VaInst.InstCreateArray)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstInstanceof) {
- final VaInst.InstInstanceof inst = (VaInst.InstInstanceof)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstCast) {
- final VaInst.InstCast inst = (VaInst.InstCast)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstDlgConstruct) {
- final VaInst.InstDlgConstruct inst
- = (VaInst.InstDlgConstruct)opcode;
- mergeConst(inst.method);
- }else if(opcode instanceof VaInst.InstXNatMthAddress) {
- final VaInst.InstXNatMthAddress inst
- = (VaInst.InstXNatMthAddress)opcode;
- mergeConst(inst.method);
- }else if(opcode instanceof VaInst.InstXNatSizeofObject) {
- final VaInst.InstXNatSizeofObject inst
- = (VaInst.InstXNatSizeofObject)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstXNatAddressCast) {
- final VaInst.InstXNatAddressCast inst
- = (VaInst.InstXNatAddressCast)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstXNatMakeObject) {
- final VaInst.InstXNatMakeObject inst
- = (VaInst.InstXNatMakeObject)opcode;
- mergeConst(inst.clsInfo);
- }else if(opcode instanceof VaInst.InstXNatMakeArray) {
- final VaInst.InstXNatMakeArray inst
- = (VaInst.InstXNatMakeArray)opcode;
- mergeConst(inst.datatype);
- }else if(opcode instanceof VaInst.InstXAtomCas) {
- final VaInst.InstXAtomCas inst
- = (VaInst.InstXAtomCas)opcode;
- mergeConst(inst.field);
- }else if(opcode instanceof VaInst.InstXNatMakeDelegate) {
- final VaInst.InstXNatMakeDelegate inst
- = (VaInst.InstXNatMakeDelegate)opcode;
- mergeConst(inst.datatype);
- }
- }
- }
- }
-
- // adds "cnst" and all constants that depend on "cnst" to the constant map
- private void mergeConst(Object cnst) throws ValibException {
- if(cnstMap.containsKey(cnst))
- return;
-
- // merge dependancies
- if(cnst instanceof VaClsInfo) {
- final VaClsInfo info = (VaClsInfo)cnst;
- mergeString(info.ident);
- }else if(cnst instanceof VaMthInfo) {
- final VaMthInfo info = (VaMthInfo)cnst;
- mergeString(info.ident);
- mergeConst(info.returnType);
-
- // merge the arguments
- for(int i = 0; i < info.getArgumentCnt(); i++)
- mergeConst(info.getArgument(i));
- }else if(cnst instanceof VaFldInfo) {
- final VaFldInfo info = (VaFldInfo)cnst;
- mergeString(info.ident);
- mergeConst(info.datatype);
-
- // merge the literal
- if(info.literal != null)
- mergeConst(info.literal);
- }else if(cnst instanceof VaDatatype.DtClass) {
- final VaDatatype.DtClass type = (VaDatatype.DtClass)cnst;
- mergeConst(type.clsInfo);
- }else if(cnst instanceof VaDatatype.DtArray) {
- final VaDatatype.DtArray type = (VaDatatype.DtArray)cnst;
- mergeConst(type.basetype);
- }else if(cnst instanceof VaDatatype.DtDelegate) {
- final VaDatatype.DtDelegate type = (VaDatatype.DtDelegate)cnst;
- mergeConst(type.returnType);
- for(int i = 0; i < type.getArgumentCnt(); i++)
- mergeConst(type.getArgument(i));
- }else if(cnst instanceof VaDatatype.DtPrimitive) {
- }else if(cnst instanceof VaLiteral.LitNull) {
- }else if(cnst instanceof VaLiteral.LitUInt) {
- }else if(cnst instanceof VaLiteral.LitChar) {
- }else if(cnst instanceof VaLiteral.LitBoolean) {
- }else if(cnst instanceof VaLiteral.LitCharArray) {
- // do nothing
- }else{
- throw new ValibException("Unknown constant " + cnst.getClass().getSimpleName());
- }
- // add the constant to the map
- cnstList.add(cnst);
- cnstMap.put(cnst, cnstList.size());
- }
-
- private void mergeString(final String string) {
- if(stringMap.containsKey(string))
- return;
- stringList.add(string);
- stringMap.put(string, stringList.size());
- }
-
- private static void writeRegister(int register,
- OutputStream stream) throws ValibException {
- if(register < 0xFF) {
- writeUByte((short)register, stream);
- }else{
- writeUByte((short)0xFF, stream);
- writeUInt(register, stream);
- }
- }
-
- private static void writeBool(boolean value,
- OutputStream stream) throws ValibException {
- if(value) {
- writeUByte((short)1, stream);
- }else{
- writeUByte((short)0, stream);
- }
- }
-
- // writes an unsigned integer value to a stream
- private static void writeUInt(long value,
- OutputStream stream) throws ValibException {
- writeUByte((short)((value & 0xFF000000L) >> 24), stream);
- writeUByte((short)((value & 0xFF0000L) >> 16), stream);
- writeUByte((short)((value & 0xFF00L) >> 8), stream);
- writeUByte((short)(value & 0xFFL), stream);
- }
-
- // writes an unsigned short value to a stream
- private static void writeUShort(int value,
- OutputStream stream) throws ValibException {
- writeUByte((short)((value & 0xFF00) >> 8), stream);
- writeUByte((short)(value & 0xFF), stream);
- }
-
- private static void writeUByte(short value,
- OutputStream stream) throws ValibException {
- try {
- stream.write(value);
- } catch(IOException e) {
- throw new ValibException("Could not write output file");
- }
- }
- }