/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * @author Intel, George A. Timoshenko
 * @version $Revision: 1.34.8.4.4.4 $
 */

#include "Stl.h"
#include "JavaByteCodeTranslator.h"
#include "JavaTranslator.h"
#include "Log.h"
#include "ExceptionInfo.h"
#include "simplifier.h"
#include "methodtable.h"
#include "open/bytecodes.h"
#include "irmanager.h"
#include "Jitrino.h"
#include "EMInterface.h"
#include "inliner.h"
#include "VMMagic.h"

#include <assert.h>
#include <stdio.h>

namespace Jitrino {

static bool matchType(const char* candidate, const char* typeName) {
    if (candidate[0]=='L') {
        size_t typeLen = strlen(typeName);
        size_t candLen = strlen(candidate);
        bool res = typeLen+2 == candLen && !strncmp(typeName, candidate+1, typeLen);
        return res;
    }
    return !strcmp(typeName, candidate);
}

static Type* convertVMMagicType2HIR(TypeManager& tm, const char* name) {
    assert(VMMagicUtils::isVMMagicClass(name));

    if (matchType(name, "org/vmmagic/unboxed/Address")
        //TODO: ObjectReference must have a ManagedPointer/Object type
        || matchType(name, "org/vmmagic/unboxed/ObjectReference"))
    {
        return tm.getUnmanagedPtrType(tm.getInt8Type());
    } else if (matchType(name, "org/vmmagic/unboxed/Word")
        || matchType(name, "org/vmmagic/unboxed/Offset")
        || matchType(name, "org/vmmagic/unboxed/Extent"))
    {
        return tm.getUIntPtrType();
    } else if (matchType(name, "org/vmmagic/unboxed/WordArray")
        || matchType(name, "org/vmmagic/unboxed/OffsetArray")
        || matchType(name, "org/vmmagic/unboxed/ExtentArray") 
        || matchType(name, "org/vmmagic/unboxed/AddressArray") 
        || matchType(name, "org/vmmagic/unboxed/ObjectReferenceArray")) 
    {
#ifdef _EM64T_
        return tm.getArrayType(tm.getInt64Type(), false);
#else 
        return tm.getArrayType(tm.getInt32Type(), false);
#endif
    }
    assert(0);
    return NULL;
}

static Type* convertVMMagicType2HIR(TypeManager& tm, Type* type) {
    if (!type->isObject() || !type->isNamedType() || type->isSystemObject()) {
        return type;
    }
    const char* name = type->getName();    
    return convertVMMagicType2HIR(tm, name);
}

//vm helpers support

static bool isVMHelperClass(const char* name) {
#ifdef _IPF_
    return false;//natives are not tested on IPF.
#else
    bool res =  !strcmp(name, VMHELPER_TYPE_NAME);
    return res;
#endif
}


//-----------------------------------------------------------------------------
// JavaByteCodeTranslator constructors
//-----------------------------------------------------------------------------
// version for non-inlined methods

JavaByteCodeTranslator::JavaByteCodeTranslator(CompilationInterface& ci,
                                 MemoryManager& mm,
                                 IRBuilder& irb,
                                 ByteCodeParser& bcp,
                                 MethodDesc& methodDesc,
                                 TypeManager& typeManager,
                                 JavaFlowGraphBuilder& cfg)
    : 
      memManager(mm), 
      compilationInterface(ci), 
      methodToCompile(methodDesc), 
      parser(bcp), 
      typeManager(*irb.getTypeManager()), 
      irBuilder(irb),
      translationFlags(*irb.getTranslatorFlags()),
      cfgBuilder(cfg),
      // CHECK ? for static sync methods must ensure at least one slot on stack for monitor enter/exit code
      opndStack(mm,methodDesc.getMaxStack()+1),
      returnOpnd(NULL),
      returnNode(NULL),
      inliningExceptionInfo(NULL),
      prepass(memManager,
              typeManager,
              irBuilder.getInstFactory()->getMemManager(),
              methodDesc,
              ci,
              NULL),
      lockAddr(NULL), 
      oldLockValue(NULL),
      jsrEntryMap(NULL),
      retOffsets(mm),
      jsrEntryOffsets(mm)
{
    initJsrEntryMap();
    // create a prolog block 
    cfgBuilder.genBlock(irBuilder.genMethodEntryLabel(&methodDesc));
    initLocalVars();
    initArgs();
    CompilationContext* cc = CompilationContext::getCurrentContext();
    InliningContext* ic  = cc->getInliningContext();
    //
    // load actual parameters into formal parameters
    //
    for (U_32 i=0,j=0; i<numArgs; i++,j++) {
        //
        // for Java this is the same as a local var!
        //
        Opnd *arg;
        if (i == 0 && methodToCompile.isStatic() == false) {
            //
            // for non-inlined, non-static methods, 'this' pointer should have non-null property set
            //
            arg = irBuilder.genArgDef(NonNullThisArg,argTypes[i]);
        } else {
            Type* type = argTypes[i];
            if (ic!=NULL) {
                assert(ic->getNumArgs() == numArgs);
                Type* newType = ic->getArgTypes()[i];
                if (newType->isObject()) {
                    assert(newType->isObject() == type->isObject());
                    assert(newType->isNullObject() || newType->isUnresolvedType()  || type->isUnresolvedType()
                        || newType->asObjectType()->isSubClassOf(type->asObjectType()) || newType->isSystemObject());
                    type = newType;
                } else {
                    //TODO: numX->numY auto conversion not tested
                }
            } 
            if (VMMagicUtils::isVMMagicClass(type->getName())) {
                type = convertVMMagicType2HIR(typeManager, type);
            }
            arg = irBuilder.genArgDef(DefArgNoModifier,type);
        }
        JavaLabelPrepass::JavaVarType javaType = JavaLabelPrepass::getJavaType(argTypes[i]);
        VarOpnd *var = getVarOpndStVar(javaType,j,arg);
        //
        // longs & doubles take up 2 slots
        //
        if (javaType==JavaLabelPrepass::L || javaType==JavaLabelPrepass::D) 
            j++;
        if (var != NULL)
            irBuilder.genStVar(var,arg);
        stateInfo->stack[j].vars = new (memManager) SlotVar(prepass.getVarInc(0, j));
    }
    // check for synchronized methods
    if (methodToCompile.isSynchronized()) {
        if (methodToCompile.isStatic()) {
            //irBuilder.genTypeMonitorEnter(methodToCompile.getParentType());
            Opnd* classObjectOpnd = irBuilder.genGetClassObj((ObjectType*) methodToCompile.getParentType());
            pushOpnd(classObjectOpnd);
            genMethodMonitorEnter();
        } else {
            genLdVar(0,JavaLabelPrepass::A);
            genMethodMonitorEnter();
        }
    }

    if(!prepass.allExceptionTypesResolved()) {
        unsigned problemToken = prepass.getProblemTypeToken();
        assert(problemToken != MAX_UINT32);
        linkingException(problemToken,OPCODE_CHECKCAST); // CHECKCAST is suitable here
        noNeedToParse = true;
    }
}


//-----------------------------------------------------------------------------
// initialization helpers
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::initJsrEntryMap()
{
    MemoryManager& ir_mem_manager = irBuilder.getIRManager()->getMemoryManager();
    jsrEntryMap = new (ir_mem_manager) JsrEntryInstToRetInstMap(ir_mem_manager);
}

void 
JavaByteCodeTranslator::initLocalVars() {
    //
    // perform label prepass in this method
    //
    parser.parse(&prepass);
    prepass.parseDone();
    prepassVisited = prepass.bytecodevisited;
    moreThanOneReturn = false;
    jumpToTheEnd      = false;
    lastInstructionWasABranch = false;

    // compute number of labels
    numLabels = prepass.getNumLabels();
    labels = new (memManager) LabelInst*[numLabels+1];
    irBuilder.createLabels(numLabels,labels);

    nextLabel = 0;
    resultOpnd = NULL;

    numVars = methodToCompile.getNumVars();
    numStackVars = prepass.getStateTable()->getMaxStackOverflow()-numVars;
    stateInfo = &prepass.stateInfo;
    for (U_32 k=0; k < numVars+numStackVars; k++) {
        struct StateInfo::SlotInfo *slot = &stateInfo->stack[k];
        slot->type = NULL;
        slot->slotFlags = 0;
        slot->vars = NULL;
    }
    stateInfo->stackDepth = numVars;
    javaTypeMap[JavaLabelPrepass::I]   = typeManager.getInt32Type();
    javaTypeMap[JavaLabelPrepass::L]   = typeManager.getInt64Type();
    javaTypeMap[JavaLabelPrepass::F]   = typeManager.getSingleType();
    javaTypeMap[JavaLabelPrepass::D]   = typeManager.getDoubleType();
    javaTypeMap[JavaLabelPrepass::A]   = typeManager.getSystemObjectType();
    javaTypeMap[JavaLabelPrepass::RET] = typeManager.getIntPtrType();
    prepass.createMultipleDefVarOpnds(&irBuilder);

}

void 
JavaByteCodeTranslator::initArgs() {
    // incoming argument and return value information
    numArgs = methodToCompile.getNumParams();
    retType = methodToCompile.getReturnType();
    argTypes = new (memManager) Type*[numArgs];
    args = new (memManager) Opnd*[numArgs];
    for (uint16 i=0; i<numArgs; i++) {
        Type* argType = methodToCompile.getParamType(i);
        assert(!(typeManager.isLazyResolutionMode() && argType==NULL));
        // argType == NULL if it fails to be resolved. Respective exception
        // will be thrown at the point of usage
        argTypes[i] = argType != NULL ? argType : typeManager.getNullObjectType();
    }
}

//-----------------------------------------------------------------------------
// variable management helpers
//-----------------------------------------------------------------------------
// returns either VarOpnd or Opnd. If returning is operand, do not generate the LdVar, only
// push the operand
//
Opnd* 
JavaByteCodeTranslator::getVarOpndLdVar(JavaLabelPrepass::JavaVarType javaType,U_32 index) {
    if (index >= numVars+numStackVars)
        // error: invalid local variable id
        invalid();
    struct StateInfo::SlotInfo slot = stateInfo->stack[index];
    assert(slot.vars);
    Opnd* var = slot.vars->getVarIncarnation()->getOrCreateOpnd(&irBuilder);
    return var;
}

// returns either VarOpnd or null. If null, does not generate the StVar

VarOpnd* 
JavaByteCodeTranslator::getVarOpndStVar(JavaLabelPrepass::JavaVarType javaType,
                                        U_32 index, 
                                        Opnd* opnd) {
    if (index >= numVars+numStackVars)
        // error: invalid local variable id
        invalid();
    VariableIncarnation* varInc = prepass.getVarInc(currentOffset, index);
    Opnd* var = NULL;
    StateInfo::SlotInfo* slot = NULL;
    slot = &stateInfo->stack[index];
    if(varInc) {
        slot->vars = new (memManager) SlotVar(varInc);
        var = varInc->getOpnd();
    }

    if (var) {
        assert(var->isVarOpnd());
        return var->asVarOpnd();
    } else {
        slot->type = typeManager.toInternalType(opnd->getType());
        slot->slotFlags = 0;
        if (isNonNullOpnd(opnd))
            StateInfo::setNonNull(slot);
        if (isExactTypeOpnd(opnd))
            StateInfo::setExactType(slot);
        varInc->setTmpOpnd(opnd);
        return NULL;
    }
}

//-----------------------------------------------------------------------------
// operand stack manipulation helpers
//-----------------------------------------------------------------------------
void    
JavaByteCodeTranslator::pushOpnd(Opnd* opnd) {
    assert(opnd->getInst());
    opndStack.push(opnd);
}

Opnd*    
JavaByteCodeTranslator::topOpnd() {
    return opndStack.top();
}

Opnd*    
JavaByteCodeTranslator::popOpnd() {
    Opnd *top = opndStack.pop();
    setStackOpndAliveOpnd(top,true);
    return top;
}

Opnd*    
JavaByteCodeTranslator::popOpndStVar() {
    return opndStack.pop();
}

//
// Called at the end of each basic block to empty out the operand stack
//
void 
JavaByteCodeTranslator::checkStack() {
    int numElems = opndStack.getNumElems();
    for (int i = numElems-1; i >= 0; i--) {
        Opnd* opnd = popOpndStVar();
        JavaLabelPrepass::JavaVarType javaType = 
            JavaLabelPrepass::getJavaType(opnd->getType());

        VarOpnd* var = getVarOpndStVar(javaType,(uint16)(numVars+i),opnd);
        // simple optimization
        if(var != NULL) {
            Inst* srcInst = opnd->getInst();
            assert(srcInst);
            if ((srcInst->getOpcode() != Op_LdVar) || 
                (srcInst->getSrc(0)->getId() != var->getId())) {
                irBuilder.genStVar(var,opnd);
                setStackOpndAliveOpnd(opnd,true);
            } else {
            }
        }
    }
}
//-----------------------------------------------------------------------------
// constant pool resolution helpers
//-----------------------------------------------------------------------------

const char*
JavaByteCodeTranslator::methodSignatureString(U_32 cpIndex) {
    return compilationInterface.getSignatureString(&methodToCompile,cpIndex);
}

U_32 
JavaByteCodeTranslator::labelId(U_32 offset) {
    U_32 labelId = prepass.getLabelId(offset);
    if (labelId == (U_32) -1)
        jitrino_assert(0);
    return labelId;
}

//-----------------------------------------------------------------------------
// misc JavaByteCodeParserCallback methods
//-----------------------------------------------------------------------------

// called when invalid byte code is encountered
void 
JavaByteCodeTranslator::invalid() {
    jitrino_assert(0);
}

// called when an error occurs during the byte code parsing
void 
JavaByteCodeTranslator::parseError() {
    jitrino_assert(0);
}

void 
JavaByteCodeTranslator::offset(U_32 offset) {

    // set bc offset in ir builder
    irBuilder.setBcOffset(offset);
    if (prepass.isLabel(offset) == false)
        return;
    if (prepassVisited && prepassVisited->getBit(offset) == false) {
        getNextLabelId(); // skip this DEAD byte code
        return;
    }

    // finish the previous basic block, if any work was required
    if (!lastInstructionWasABranch) {
        checkStack();
    }
    lastInstructionWasABranch = false;

    // start with the current basic block
    StateInfo* state = prepass.stateTable->getStateInfo(offset);
    stateInfo->flags = state->flags;
    stateInfo->stackDepth = state->stackDepth;
    stateInfo->exceptionInfo = state->exceptionInfo;
    for(unsigned i=0; i<state->stackDepth; ++i)
        stateInfo->stack[i] = state->stack[i];
    assert(stateInfo != NULL);
    Type* handlerExceptionType = NULL;
    U_32 lblId = getNextLabelId();
    LabelInst* labelInst = getLabel(lblId);

    ::std::vector<LabelInst*> catchLabels;

    bool isCatchHandler = false;
    for (ExceptionInfo* exceptionInfo = stateInfo->getExceptionInfo();
         exceptionInfo != NULL;
         exceptionInfo = exceptionInfo->getNextExceptionInfoAtOffset()) {
        if (exceptionInfo->isCatchBlock()) {
            CatchBlock* catchBlock = (CatchBlock*)exceptionInfo;
            CatchHandler *first = ((CatchBlock*)exceptionInfo)->getHandlers();
            if (Log::isEnabled()) {
                Log::out() << "TRY REGION " << (int)exceptionInfo->getBeginOffset() 
                    << " " << (int)exceptionInfo->getEndOffset() << ::std::endl;
                for (; first != NULL; first = first->getNextHandler()) {
                    Log::out() << " handler " << (int)first->getBeginOffset() << ::std::endl;
                }
            }
            if (catchBlock->getLabelInst() == NULL) {
                Node *dispatchNode = cfgBuilder.createDispatchNode();
                catchBlock->setLabelInst((LabelInst*)dispatchNode->getFirstInst());
                ((LabelInst*)dispatchNode->getFirstInst())->setState(catchBlock);
            }
            if (labelInst->getState() == NULL) 
                labelInst->setState(catchBlock);
            if(Log::isEnabled()) {
                Log::out() << "LABEL "; labelInst->print(Log::out()); Log::out() << labelInst->getState();
                Log::out() << "CATCH ";catchBlock->getLabelInst()->print(Log::out()); Log::out() << ::std::endl;
            }
        } else if (exceptionInfo->isCatchHandler()) {
            // catch handler block
            isCatchHandler = true;
            CatchHandler* handler = (CatchHandler*)exceptionInfo;
            if (Log::isEnabled()) Log::out() << "CATCH REGION " << (int)exceptionInfo->getBeginOffset() 
                << " " << (int)exceptionInfo->getEndOffset() << ::std::endl;
            handlerExceptionType = (handlerExceptionType == NULL) ?
                handler->getExceptionType() :
                typeManager.getCommonObjectType((ObjectType*) handlerExceptionType, (ObjectType*) handler->getExceptionType());
            LabelInst *oldLabel = labelInst;
            labelInst = irBuilder.getInstFactory()->makeCatchLabel(
                                            handler->getExceptionOrder(),
                                            handler->getExceptionType());
            labelInst->setBCOffset((uint16)exceptionInfo->getBeginOffset());
            catchLabels.push_back(labelInst);
            labelInst->setState(oldLabel->getState());
            exceptionInfo->setLabelInst(labelInst);
            if(Log::isEnabled()) {
                Log::out() << "LABEL "; labelInst->print(Log::out()); Log::out() << labelInst->getState();
                Log::out() << "CATCH "; handler->getLabelInst()->print(Log::out()); Log::out() << ::std::endl;
            }
        } else {jitrino_assert(0);}    // only catch blocks should occur in Java
    }
    // generate the label instruction
    if(!catchLabels.empty()) {
        for(::std::vector<LabelInst*>::iterator iter = catchLabels.begin(); iter != catchLabels.end(); ++iter) {
            LabelInst* catchLabel = *iter;
            irBuilder.genLabel(catchLabel);
            cfgBuilder.genBlock(catchLabel);
        }
        LabelInst* handlerLabel= getLabel(lblId);
        assert(!handlerLabel->isCatchLabel());
        handlerLabel->setState(labelInst->getState());
        irBuilder.genLabel(handlerLabel);
        cfgBuilder.genBlock(handlerLabel);
    } else {
        if (stateInfo->isFallThroughLabel()) {
            irBuilder.genFallThroughLabel(labelInst);
        } else { 
            irBuilder.genLabel(labelInst);
            // empty out the stack operand
            opndStack.makeEmpty();
        }
        cfgBuilder.genBlock(labelInst);
    }

    if (isCatchHandler) {
        // for catch handler blocks, generate the catch instruction
        assert(stateInfo->isCatchLabel());
        assert(1 == stateInfo->stackDepth - numVars);
        assert(stateInfo->stack[numVars].type == handlerExceptionType);
        pushOpnd(irBuilder.genCatch(stateInfo->stack[numVars].type));
    } else {
        //
        // Load var operands where current basic block begins
        //
        for (U_32 k=numVars; k < (U_32)stateInfo->stackDepth; k++) {
            if(Log::isEnabled()) {
                Log::out() << "STACK ";StateInfo::print(stateInfo->stack[k], Log::out());Log::out() << ::std::endl;
            }
            genLdVar(k,prepass.getJavaType(stateInfo->stack[k].type));
        }
    }
    if (stateInfo->isSubroutineEntry()) {
        pushOpnd(irBuilder.genSaveRet());
    }
}

void 
JavaByteCodeTranslator::offset_done(U_32 offset) {
    if (prepass.isSubroutineEntry(offset) ) {
        jsrEntryOffsets[offset] = irBuilder.getLastGeneratedInst();
    }
}

//
// called when byte code parsing is done
//
void 
JavaByteCodeTranslator::parseDone() 
{
    OffsetToInstMap::const_iterator ret_i, ret_e;
    for (ret_i = retOffsets.begin(), ret_e = retOffsets.end(); ret_i != ret_e; ++ret_i) {
        U_32 ret_offset = ret_i->first;
        Inst* ret_inst = ret_i->second;
        JavaLabelPrepass::RetToSubEntryMap* ret_to_entry_map = prepass.getRetToSubEntryMapPtr();
        JavaLabelPrepass::RetToSubEntryMap::const_iterator sub_i = ret_to_entry_map->find(ret_offset);
        //
        // jsr target should be found for each ret inst
        //
        assert(sub_i != ret_to_entry_map->end());
        U_32 entry_offset = sub_i->second;
        OffsetToInstMap::const_iterator entry_inst_i = jsrEntryOffsets.find(entry_offset);
        assert(entry_inst_i != jsrEntryOffsets.end());
        Inst* entry_inst = entry_inst_i->second;
        jsrEntryMap->insert(std::make_pair(entry_inst, ret_inst));
    }
    irBuilder.getIRManager()->setJsrEntryMap(jsrEntryMap);
    if (Log::isEnabled()) Log::out() << ::std::endl << "================= TRANSLATOR IS FINISHED =================" << ::std::endl << ::std::endl;
}

//-----------------------------------------------------------------------------
// byte code callbacks
//-----------------------------------------------------------------------------

void JavaByteCodeTranslator::nop() {}

//-----------------------------------------------------------------------------
// load constant byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::aconst_null()     {
    pushOpnd(irBuilder.genLdNull());
}
void 
JavaByteCodeTranslator::iconst(I_32 val) {
    pushOpnd(irBuilder.genLdConstant(val));
}
void 
JavaByteCodeTranslator::lconst(int64 val) {
    pushOpnd(irBuilder.genLdConstant(val));
}
void 
JavaByteCodeTranslator::fconst(float val) {
    pushOpnd(irBuilder.genLdConstant(val));
}
void 
JavaByteCodeTranslator::dconst(double val){
    pushOpnd(irBuilder.genLdConstant(val));
}
void 
JavaByteCodeTranslator::bipush(I_8 val)  {
    pushOpnd(irBuilder.genLdConstant((I_32)val));
}
void 
JavaByteCodeTranslator::sipush(int16 val) {
    pushOpnd(irBuilder.genLdConstant((I_32)val));
}
void 
JavaByteCodeTranslator::ldc(U_32 constPoolIndex) {
    // load 32-bit quantity or string from constant pool
    Type* constantType = 
        compilationInterface.getConstantType(&methodToCompile,constPoolIndex);
    Opnd* opnd = NULL;
    if (constantType->isSystemString()) {
        opnd = irBuilder.genLdRef(&methodToCompile,constPoolIndex,constantType);
    } else if (constantType->isSystemClass()) {
        NamedType *literalType = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex);
        if (!typeManager.isLazyResolutionMode() && literalType->isUnresolvedType()) {
            linkingException(constPoolIndex, OPCODE_LDC);
        }
        opnd = irBuilder.genLdRef(&methodToCompile,constPoolIndex,constantType);
    } else {
        const void* constantAddress =
           compilationInterface.getConstantValue(&methodToCompile,constPoolIndex);
        if (constantType->isInt4()) {
            I_32 value = *(I_32*)constantAddress;
            opnd = irBuilder.genLdConstant(value);
        } else if (constantType->isSingle()) {
            float value = *(float*)constantAddress;
            opnd = irBuilder.genLdConstant((float)value);
        } else {
            // Invalid type!
            jitrino_assert(0);
        }
    }
    pushOpnd(opnd);
}

void 
JavaByteCodeTranslator::ldc2(U_32 constPoolIndex) {
    // load 64-bit quantity from constant pool
    Type* constantType = 
        compilationInterface.getConstantType(&methodToCompile,constPoolIndex);

    const void* constantAddress =
        compilationInterface.getConstantValue(&methodToCompile,constPoolIndex);
    Opnd *opnd = NULL; 
    if (constantType->isInt8()) {
        int64 value = *(int64*)constantAddress;
        opnd = irBuilder.genLdConstant((int64)value);
    } else if (constantType->isDouble()) {
        double value = *(double*)constantAddress;
        opnd = irBuilder.genLdConstant((double)value);
    } else {
        // Invalid type!
        jitrino_assert(0);
    }
    pushOpnd(opnd);
}

//-----------------------------------------------------------------------------
// variable access byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::iload(uint16 varIndex) {
    genLdVar(varIndex,JavaLabelPrepass::I);
}
void 
JavaByteCodeTranslator::lload(uint16 varIndex) {
    genLdVar(varIndex,JavaLabelPrepass::L);
}
void 
JavaByteCodeTranslator::fload(uint16 varIndex) {
    genLdVar(varIndex,JavaLabelPrepass::F);
}
void 
JavaByteCodeTranslator::dload(uint16 varIndex) {
    genLdVar(varIndex,JavaLabelPrepass::D);
}
void 
JavaByteCodeTranslator::aload(uint16 varIndex) {
    genLdVar(varIndex,JavaLabelPrepass::A);
}
void 
JavaByteCodeTranslator::istore(uint16 varIndex,U_32 off) {
    genStVar(varIndex,JavaLabelPrepass::I);
}
void 
JavaByteCodeTranslator::lstore(uint16 varIndex,U_32 off) {
    genStVar(varIndex,JavaLabelPrepass::L);
}
void 
JavaByteCodeTranslator::fstore(uint16 varIndex,U_32 off) {
    genStVar(varIndex,JavaLabelPrepass::F);
}
void 
JavaByteCodeTranslator::dstore(uint16 varIndex,U_32 off) {
    genStVar(varIndex,JavaLabelPrepass::D);
}
void 
JavaByteCodeTranslator::astore(uint16 varIndex,U_32 off) {
    genTypeStVar(varIndex);
}
//-----------------------------------------------------------------------------
// field access byte codes
//-----------------------------------------------------------------------------
Type* 
JavaByteCodeTranslator::getFieldType(FieldDesc* field, U_32 constPoolIndex) {
    Type* fieldType = field->getFieldType();
    if (!fieldType) {
        // some problem with fieldType class handle. Let's try the constant_pool.
        // (For example if the field type class is deleted, the field is beeing resolved successfully
        // but field->getFieldType() returns NULL in this case)
        fieldType = compilationInterface.getFieldType(methodToCompile.getParentHandle(),constPoolIndex);
    }
    return fieldType;
}


void 
JavaByteCodeTranslator::getstatic(U_32 constPoolIndex) {
    FieldDesc *field = compilationInterface.getStaticField(methodToCompile.getParentHandle(), constPoolIndex, false);
    if (field && field->isStatic()) {
        bool fieldValueInlined = false;
        Type* fieldType = field->getFieldType();
        assert(fieldType);
        bool fieldIsMagic = VMMagicUtils::isVMMagicClass(fieldType->getName());
        if (fieldIsMagic) {
            fieldType = convertVMMagicType2HIR(typeManager, fieldType);
        }
        if (field->isInitOnly() && !field->getParentType()->needsInitialization()) {
            //the final static field of the initialized class
            if (field->getFieldType()->isNumeric() || field->getFieldType()->isBoolean() || fieldIsMagic) {
                Opnd* constVal = NULL;
                void* fieldAddr = field->getAddress();
                switch(fieldType->tag) {
                    case Type::Int8 :   constVal=irBuilder.genLdConstant(*(I_8*)fieldAddr);break;
                    case Type::Int16:   constVal=irBuilder.genLdConstant(*(int16*)fieldAddr);break;
                    case Type::Char :   constVal=irBuilder.genLdConstant(*(uint16*)fieldAddr);break;
                    case Type::Int32:   constVal=irBuilder.genLdConstant(*(I_32*)fieldAddr);break;
                    case Type::Int64:   constVal=irBuilder.genLdConstant(*(int64*)fieldAddr);break;
                    case Type::Single:  constVal=irBuilder.genLdConstant(*(float*)fieldAddr);break;
                    case Type::Double:  constVal=irBuilder.genLdConstant(*(double*)fieldAddr);break;
                    case Type::Boolean: constVal=irBuilder.genLdConstant(*(bool*)fieldAddr);break;
                    case Type::UnmanagedPtr:  assert(fieldIsMagic); 
#ifdef _IA32_
                            constVal=irBuilder.genLdConstant(*(I_32*)fieldAddr);
#else
                            assert(sizeof(void*)==8);
                            constVal=irBuilder.genLdConstant(*(int64*)fieldAddr);
#endif
                            break;
                    default: assert(0); //??
                }
                if (constVal != NULL) {
                    pushOpnd(constVal);
                    fieldValueInlined = true;
                }
            }
        } 
        if (!fieldValueInlined){
            pushOpnd(irBuilder.genLdStatic(fieldType, field));
        }
    } else {
        //field is not resolved or not static
        if (!typeManager.isLazyResolutionMode()) {
            // generate helper call for throwing respective exception
            linkingException(constPoolIndex, OPCODE_GETSTATIC);
        }
        const char* fieldTypeName = CompilationInterface::getFieldSignature(methodToCompile.getParentHandle(), constPoolIndex);
        bool fieldIsMagic = VMMagicUtils::isVMMagicClass(fieldTypeName);
        Type* fieldType = fieldIsMagic ? convertVMMagicType2HIR(typeManager, fieldTypeName) 
                                       : compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex);
        Opnd* res = irBuilder.genLdStaticWithResolve(fieldType, methodToCompile.getParentType()->asObjectType(), constPoolIndex);
        pushOpnd(res);
    }
}

void 
JavaByteCodeTranslator::putstatic(U_32 constPoolIndex) {
    FieldDesc *field = compilationInterface.getStaticField(methodToCompile.getParentHandle(), constPoolIndex, true);
    if (field && field->isStatic()) {
        Type* fieldType = getFieldType(field,constPoolIndex);
        assert(fieldType);
        bool fieldIsMagic = VMMagicUtils::isVMMagicClass(fieldType->getName());
        if (fieldIsMagic) {
            fieldType = convertVMMagicType2HIR(typeManager, fieldType);
        }
        irBuilder.genStStatic(fieldType,field,popOpnd());
    } else {
        //field is not resolved or not static
        if (!typeManager.isLazyResolutionMode()) {
            // generate helper call for throwing respective exception
            linkingException(constPoolIndex, OPCODE_PUTSTATIC);
        }
        const char* fieldTypeName = CompilationInterface::getFieldSignature(methodToCompile.getParentHandle(), constPoolIndex);
        bool fieldIsMagic = VMMagicUtils::isVMMagicClass(fieldTypeName);
        Type* fieldType = fieldIsMagic ? convertVMMagicType2HIR(typeManager, fieldTypeName) 
                                       : compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex);
        Opnd* value = popOpnd();
        irBuilder.genStStaticWithResolve(fieldType, methodToCompile.getParentType()->asObjectType(), constPoolIndex, value);
    }
}

void 
JavaByteCodeTranslator::getfield(U_32 constPoolIndex) {
    FieldDesc *field = compilationInterface.getNonStaticField(methodToCompile.getParentHandle(), constPoolIndex, false);
    if (field && !field->isStatic()) {
        Type* fieldType = getFieldType(field, constPoolIndex);
        if (VMMagicUtils::isVMMagicClass(fieldType->getName())) {
            fieldType = convertVMMagicType2HIR(typeManager, fieldType);
        }
        pushOpnd(irBuilder.genLdField(fieldType,popOpnd(),field));
    } else {
        if (!typeManager.isLazyResolutionMode()) {
            // generate helper call for throwing respective exception
            linkingException(constPoolIndex, OPCODE_GETFIELD);
        }
        Type* fieldType = compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex);
        if (VMMagicUtils::isVMMagicClass(fieldType->getName())) {
            fieldType = convertVMMagicType2HIR(typeManager, fieldType);
        }
        Opnd* base = popOpnd();
        Opnd* res = irBuilder.genLdFieldWithResolve(fieldType, base, methodToCompile.getParentType()->asObjectType(), constPoolIndex);
        pushOpnd(res);
    }
}

void 
JavaByteCodeTranslator::putfield(U_32 constPoolIndex) {
    FieldDesc *field = compilationInterface.getNonStaticField(methodToCompile.getParentHandle(), constPoolIndex, true);
    if (field && !field->isStatic()) {
        Type* fieldType = getFieldType(field,constPoolIndex);
        assert(fieldType);
        if (VMMagicUtils::isVMMagicClass(fieldType->getName())) {
            fieldType = convertVMMagicType2HIR(typeManager, fieldType);
        }

        Opnd* value = popOpnd();
        Opnd* ref = popOpnd();
        irBuilder.genStField(fieldType,ref,field,value);
    } else {
        if (!typeManager.isLazyResolutionMode()) {
            // generate helper call for throwing respective exception
            linkingException(constPoolIndex, OPCODE_PUTFIELD);
        }
        Type* type = compilationInterface.getFieldType(methodToCompile.getParentHandle(), constPoolIndex);
        Opnd* value = popOpnd();
        Opnd* base = popOpnd();
        irBuilder.genStFieldWithResolve(type, base, methodToCompile.getParentType()->asObjectType(), constPoolIndex, value);
    }
}
//-----------------------------------------------------------------------------
// array access byte codes
//-----------------------------------------------------------------------------
void JavaByteCodeTranslator::iaload() {
    genArrayLoad(typeManager.getInt32Type());
}
void JavaByteCodeTranslator::laload() {
    genArrayLoad(typeManager.getInt64Type());
}
void JavaByteCodeTranslator::faload() {
    genArrayLoad(typeManager.getSingleType());
}
void JavaByteCodeTranslator::daload() {
    genArrayLoad(typeManager.getDoubleType());
}
void JavaByteCodeTranslator::aaload() {
    genTypeArrayLoad();
}
void JavaByteCodeTranslator::baload() {
    genArrayLoad(typeManager.getInt8Type());
}
void JavaByteCodeTranslator::caload() {
    genArrayLoad(typeManager.getCharType());
}
void JavaByteCodeTranslator::saload() {
    genArrayLoad(typeManager.getInt16Type());
}
void JavaByteCodeTranslator::iastore() {
    genArrayStore(typeManager.getInt32Type());
}
void JavaByteCodeTranslator::lastore() {
    genArrayStore(typeManager.getInt64Type());
}
void JavaByteCodeTranslator::fastore() {
    genArrayStore(typeManager.getSingleType());
}
void JavaByteCodeTranslator::dastore() {
    genArrayStore(typeManager.getDoubleType());
}
void JavaByteCodeTranslator::aastore() {
    genTypeArrayStore();
}
void JavaByteCodeTranslator::bastore() {
    genArrayStore(typeManager.getInt8Type());
}
void JavaByteCodeTranslator::castore() {
    genArrayStore(typeManager.getCharType());
}
void JavaByteCodeTranslator::sastore() {
    genArrayStore(typeManager.getInt16Type());
}
//-----------------------------------------------------------------------------
// stack manipulation byte codes (pops, dups & exchanges)
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::pop() {popOpnd();}

bool 
isCategory2(Opnd* opnd) {
    return (opnd->getType()->isInt8() || opnd->getType()->isDouble());
}

void 
JavaByteCodeTranslator::pop2() {
    Opnd* opnd = popOpnd();
    if (isCategory2(opnd))
        return;
    popOpnd();
}

void 
JavaByteCodeTranslator::dup() {
    pushOpnd(topOpnd());
}

void 
JavaByteCodeTranslator::dup_x1() {
    Opnd* opnd1 = popOpnd();
    Opnd* opnd2 = popOpnd();
    pushOpnd(opnd1);
    pushOpnd(opnd2);
    pushOpnd(opnd1);
}

void 
JavaByteCodeTranslator::dup_x2() {
    Opnd* opnd1 = popOpnd();
    Opnd* opnd2 = popOpnd();
    if (isCategory2(opnd2)) {
        pushOpnd(opnd1);
        pushOpnd(opnd2);
        pushOpnd(opnd1);
        return;
    }
    Opnd* opnd3 = popOpnd();
    pushOpnd(opnd1);
    pushOpnd(opnd3);
    pushOpnd(opnd2);
    pushOpnd(opnd1);
}

void 
JavaByteCodeTranslator::dup2() {
    Opnd* opnd1 = popOpnd();
    if (isCategory2(opnd1)) {
        pushOpnd(opnd1);
        pushOpnd(opnd1);
        return;
    }
    Opnd* opnd2 = popOpnd();
    pushOpnd(opnd2);
    pushOpnd(opnd1);
    pushOpnd(opnd2);
    pushOpnd(opnd1);
}

void 
JavaByteCodeTranslator::dup2_x1() {
    Opnd* opnd1 = popOpnd();
    Opnd* opnd2 = popOpnd();
    if (isCategory2(opnd1)) {
        // opnd1 is a category 2 instruction
        pushOpnd(opnd1);
        pushOpnd(opnd2);
        pushOpnd(opnd1);
    } else {
        // opnd1 is a category 1 instruction
        Opnd* opnd3 = popOpnd();
        pushOpnd(opnd2);
        pushOpnd(opnd1);
        pushOpnd(opnd3);
        pushOpnd(opnd2);
        pushOpnd(opnd1);
    }
}

void 
JavaByteCodeTranslator::dup2_x2() {
    Opnd* opnd1 = popOpnd();
    Opnd* opnd2 = popOpnd();
    if (isCategory2(opnd1)) {
        // opnd1 is category 2
        if (isCategory2(opnd2)) {
            pushOpnd(opnd1);
            pushOpnd(opnd2);
            pushOpnd(opnd1);
        } else {
            // opnd2 is category 1
            Opnd* opnd3 = popOpnd();
            assert(isCategory2(opnd3) == false);
            pushOpnd(opnd1);
            pushOpnd(opnd3);
            pushOpnd(opnd2);
            pushOpnd(opnd1);
        }
    } else {
        assert(isCategory2(opnd2) == false);
        // both opnd1 & opnd2 are category 1
        Opnd* opnd3 = popOpnd();
        if (isCategory2(opnd3)) {
            pushOpnd(opnd2);
            pushOpnd(opnd1);
            pushOpnd(opnd3);
            pushOpnd(opnd2);
            pushOpnd(opnd1);
        } else {
            // opnd1, opnd2, opnd3 all are category 1
            Opnd* opnd4 = popOpnd();
            assert(isCategory2(opnd4) == false);
            pushOpnd(opnd2);
            pushOpnd(opnd1);
            pushOpnd(opnd4);
            pushOpnd(opnd3);
            pushOpnd(opnd2);
            pushOpnd(opnd1);
        }
    }
}

void 
JavaByteCodeTranslator::swap() {
    Opnd* opnd1 = popOpnd();
    Opnd* opnd2 = popOpnd();
    pushOpnd(opnd1);
    pushOpnd(opnd2);
}
//-----------------------------------------------------------------------------
// Arithmetic and logical operation byte codes
//-----------------------------------------------------------------------------
void JavaByteCodeTranslator::iadd() {genAdd(typeManager.getInt32Type());}
void JavaByteCodeTranslator::ladd() {genAdd(typeManager.getInt64Type());}
void JavaByteCodeTranslator::fadd() {genFPAdd(typeManager.getSingleType());}
void JavaByteCodeTranslator::dadd() {genFPAdd(typeManager.getDoubleType());}
void JavaByteCodeTranslator::isub() {genSub(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lsub() {genSub(typeManager.getInt64Type());}
void JavaByteCodeTranslator::fsub() {genFPSub(typeManager.getSingleType());}
void JavaByteCodeTranslator::dsub() {genFPSub(typeManager.getDoubleType());}
void JavaByteCodeTranslator::imul() {genMul(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lmul() {genMul(typeManager.getInt64Type());}
void JavaByteCodeTranslator::fmul() {genFPMul(typeManager.getSingleType());}
void JavaByteCodeTranslator::dmul() {genFPMul(typeManager.getDoubleType());}
void JavaByteCodeTranslator::idiv() {genDiv(typeManager.getInt32Type());}
void JavaByteCodeTranslator::ldiv() {genDiv(typeManager.getInt64Type());}
void JavaByteCodeTranslator::fdiv() {genFPDiv(typeManager.getSingleType());}
void JavaByteCodeTranslator::ddiv() {genFPDiv(typeManager.getDoubleType());}
void JavaByteCodeTranslator::irem() {genRem(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lrem() {genRem(typeManager.getInt64Type());}
void JavaByteCodeTranslator::frem() {genFPRem(typeManager.getSingleType());}
void JavaByteCodeTranslator::drem() {genFPRem(typeManager.getDoubleType());}
void JavaByteCodeTranslator::ineg() {genNeg(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lneg() {genNeg(typeManager.getInt64Type());}
void JavaByteCodeTranslator::fneg() {genNeg(typeManager.getSingleType());}
void JavaByteCodeTranslator::dneg() {genNeg(typeManager.getDoubleType());}
void JavaByteCodeTranslator::iand() {genAnd(typeManager.getInt32Type());}
void JavaByteCodeTranslator::land() {genAnd(typeManager.getInt64Type());}
void JavaByteCodeTranslator::ior()  {genOr(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lor()  {genOr(typeManager.getInt64Type());}
void JavaByteCodeTranslator::ixor() {genXor(typeManager.getInt32Type());}
void JavaByteCodeTranslator::lxor() {genXor(typeManager.getInt64Type());}
void 
JavaByteCodeTranslator::ishl() {
    genShl(typeManager.getInt32Type(), ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::lshl() {
    genShl(typeManager.getInt64Type(), ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::ishr() {
    genShr(typeManager.getInt32Type(),SignedOp, ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::lshr() {
    genShr(typeManager.getInt64Type(),SignedOp, ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::iushr(){
    genShr(typeManager.getInt32Type(),UnsignedOp, ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::lushr(){
    genShr(typeManager.getInt64Type(),UnsignedOp, ShiftMask_Masked);
}
void 
JavaByteCodeTranslator::iinc(uint16 varIndex,I_32 amount) {
    VarOpnd* varOpnd = (VarOpnd*)getVarOpndLdVar(JavaLabelPrepass::I,varIndex);
    assert(varOpnd->isVarOpnd());
    Opnd* src1 = irBuilder.genLdVar(typeManager.getInt32Type(),varOpnd);
    Opnd* src2 = irBuilder.genLdConstant((I_32)amount);
    Opnd* result = irBuilder.genAdd(typeManager.getInt32Type(),Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
                                    src1,src2);
    irBuilder.genStVar(varOpnd,result);
}

//-----------------------------------------------------------------------------
// conversion byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::i2l() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt64Type(),Type::Int64,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::i2f() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getSingleType(),Type::Single,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::i2d() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getDoubleType(),Type::Double,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::l2i() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::Int32,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::l2f() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getSingleType(),Type::Single,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::l2d() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getDoubleType(),Type::Double,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::f2i() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::Int32,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::f2l() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt64Type(),Type::Int64,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::f2d() {
    Opnd*    src = popOpnd();
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never);
    if (methodToCompile.isStrict())
        mod = mod | Modifier(Strict_Yes);
    else 
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genConv(typeManager.getDoubleType(),Type::Double,mod,src));
}

void 
JavaByteCodeTranslator::d2i() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::Int32,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::d2l() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt64Type(),Type::Int64,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::d2f() {
    Opnd*    src = popOpnd();
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never);
    if (methodToCompile.isStrict())
        mod  = mod | Modifier(Strict_Yes);
    else
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genConv(typeManager.getSingleType(),Type::Single,mod,src));
}

void 
JavaByteCodeTranslator::i2b() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::Int8,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::i2c() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::UInt16,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}

void 
JavaByteCodeTranslator::i2s() {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genConv(typeManager.getInt32Type(),Type::Int16,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src));
}
//-----------------------------------------------------------------------------
// comparison byte codes
//-----------------------------------------------------------------------------
//
void JavaByteCodeTranslator::lcmp()  {genThreeWayCmp(Type::Int64,Cmp_GT);}
void JavaByteCodeTranslator::fcmpl() {genThreeWayCmp(Type::Single,Cmp_GT);}
void JavaByteCodeTranslator::fcmpg() {genThreeWayCmp(Type::Single,Cmp_GT_Un);}
void JavaByteCodeTranslator::dcmpl() {genThreeWayCmp(Type::Double,Cmp_GT);}
void JavaByteCodeTranslator::dcmpg() {genThreeWayCmp(Type::Double,Cmp_GT_Un);}

//-----------------------------------------------------------------------------
// control transfer byte codes
//-----------------------------------------------------------------------------
void JavaByteCodeTranslator::ifeq(U_32 targetOffset,U_32 nextOffset) {
    genIf1(Cmp_EQ,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifne(U_32 targetOffset,U_32 nextOffset) {
    genIf1(Cmp_NE_Un,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::iflt(U_32 targetOffset,U_32 nextOffset) {
    genIf1Commute(Cmp_GT,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifge(U_32 targetOffset,U_32 nextOffset) {
    genIf1(Cmp_GTE,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifgt(U_32 targetOffset,U_32 nextOffset) {
    genIf1(Cmp_GT,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifle(U_32 targetOffset,U_32 nextOffset) {
    genIf1Commute(Cmp_GTE,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifnull(U_32 targetOffset,U_32 nextOffset) {
    genIfNull(Cmp_Zero,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::ifnonnull(U_32 targetOffset,U_32 nextOffset) {
    genIfNull(Cmp_NonZero,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmpeq(U_32 targetOffset,U_32 nextOffset) {
    genIf2(Cmp_EQ,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmpne(U_32 targetOffset,U_32 nextOffset) {
    genIf2(Cmp_NE_Un,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmplt(U_32 targetOffset,U_32 nextOffset) {
    genIf2Commute(Cmp_GT,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmpge(U_32 targetOffset,U_32 nextOffset) {
    genIf2(Cmp_GTE,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmpgt(U_32 targetOffset,U_32 nextOffset) {
    genIf2(Cmp_GT,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_icmple(U_32 targetOffset,U_32 nextOffset) {
    genIf2Commute(Cmp_GTE,targetOffset,nextOffset);
}
void JavaByteCodeTranslator::if_acmpeq(U_32 targetOffset,U_32 nextOffset) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    irBuilder.genBranch(Type::Object,Cmp_EQ,target,src1,src2);
}

void 
JavaByteCodeTranslator::if_acmpne(U_32 targetOffset,U_32 nextOffset) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    irBuilder.genBranch(Type::Object,Cmp_NE_Un,target,src1,src2);
}

void 
JavaByteCodeTranslator::goto_(U_32 targetOffset,U_32 nextOffset) {
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    U_32 lid = labelId(targetOffset);
    LabelInst *target = getLabel(lid);
    irBuilder.genJump(target);
}
//-----------------------------------------------------------------------------
// jsr & ret byte codes for finally statements
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::jsr(U_32 targetOffset, U_32 nextOffset) {
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    irBuilder.genJSR(getLabel(labelId(targetOffset)));
}

void 
JavaByteCodeTranslator::ret(uint16 varIndex, const U_8* byteCodes) {
    lastInstructionWasABranch = true;
    checkStack();
    irBuilder.genRet(getVarOpndLdVar(JavaLabelPrepass::RET,varIndex));

    retOffsets[currentOffset] = irBuilder.getLastGeneratedInst();
}
//-----------------------------------------------------------------------------
// multy-way branch byte codes (switches)
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::tableswitch(JavaSwitchTargetsIter* iter) {
    Opnd* opnd = popOpnd();
    lastInstructionWasABranch = true;
    checkStack();
    // subtract the lower bound
    Opnd* bias = irBuilder.genLdConstant((I_32)iter->getLowValue());
    Opnd* dst  = irBuilder.genSub(bias->getType(),Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),opnd,bias);
    LabelInst**    labels = new (memManager) LabelInst*[iter->getNumTargets()];
    for (U_32 i=0; iter->hasNext(); i++) {
        labels[i] = getLabel(labelId(iter->getNextTarget()));
    }
    LabelInst * defaultLabel = getLabel(labelId(iter->getDefaultTarget()));
    irBuilder.genSwitch(iter->getNumTargets(),labels,defaultLabel,dst);
}

void 
JavaByteCodeTranslator::lookupswitch(JavaLookupSwitchTargetsIter* iter) {
    Opnd* opnd = popOpnd();
    lastInstructionWasABranch = true;
    checkStack();
    // generate a sequence of branches
    while (iter->hasNext()) {
        U_32 key;
        U_32 offset = iter->getNextTarget(&key);
        // load the key
        Opnd* value = irBuilder.genLdConstant((I_32)key);
        LabelInst *target = getLabel(labelId(offset));
        irBuilder.genBranch(Type::Int32,Cmp_EQ,target,opnd,value);
        // break the basic block
        LabelInst *label = irBuilder.createLabel();
        cfgBuilder.genBlockAfterCurrent(label);
    }
    // generate a jump to the default label
    LabelInst *defaultLabel = getLabel(labelId(iter->getDefaultTarget()));
    irBuilder.genJump(defaultLabel);
}
//-----------------------------------------------------------------------------
// method return byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::ireturn(U_32 off) {
    genReturn(JavaLabelPrepass::I,off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
void 
JavaByteCodeTranslator::lreturn(U_32 off) {
    genReturn(JavaLabelPrepass::L,off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
void 
JavaByteCodeTranslator::freturn(U_32 off) {
    genReturn(JavaLabelPrepass::F,off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
void 
JavaByteCodeTranslator::dreturn(U_32 off) {
    genReturn(JavaLabelPrepass::D,off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
void 
JavaByteCodeTranslator::areturn(U_32 off) {
    genReturn(JavaLabelPrepass::A,off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
void 
JavaByteCodeTranslator::return_(U_32 off) {
    genReturn(off);
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}
//-----------------------------------------------------------------------------
// LinkingException throw
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::linkingException(U_32 constPoolIndex, U_32 operation) {
    Class_Handle enclosingDrlVMClass = methodToCompile.getParentHandle();
    irBuilder.genThrowLinkingException(enclosingDrlVMClass, constPoolIndex, operation);
}
//-----------------------------------------------------------------------------
// for invoke emulation if resolution fails
//-----------------------------------------------------------------------------
void JavaByteCodeTranslator::pseudoInvoke(const char* methodSig) 
{
    U_32 numArgs = JavaLabelPrepass::getNumArgsBySignature(methodSig); 

    // pop numArgs items
    while (numArgs--) {
        popOpnd();
    }
    // recognize and push respective returnType
    Type* retType = JavaLabelPrepass::getRetTypeBySignature(compilationInterface, methodToCompile.getParentHandle(), methodSig);
    assert(retType);

    // push NULL as a returned object
    if (retType->tag != Type::Void) {
        pushOpnd(irBuilder.genLdNull());
    }
}

//-----------------------------------------------------------------------------
// method invocation byte codes
//-----------------------------------------------------------------------------
Opnd** 
JavaByteCodeTranslator::popArgs(U_32 numArgs) {
    // pop source operands
    Opnd** srcOpnds = new (memManager) Opnd*[numArgs];
    for (int i=numArgs-1; i>=0; i--) 
        srcOpnds[i] = popOpnd();
    return srcOpnds;
}

//Helper class used to initialize unresolved method ptrs
class JavaMethodSignature : public MethodSignature {
public:
    JavaMethodSignature(MemoryManager& mm, CompilationInterface ci, bool instanceMethod, Class_Handle cl, const char* sigStr){
        signatureStr = sigStr;
        nParams = JavaLabelPrepass::getNumArgsBySignature(sigStr) + (instanceMethod ? 1 : 0);
        const char* sigSuffix = sigStr;
        if (nParams > 0) {
            paramTypes = new (mm) Type*[nParams];
            U_32 i = 0;
            if (instanceMethod) {
                paramTypes[0] = ci.getTypeManager().getUnresolvedObjectType();
                i++;
            }
            sigSuffix++;
            for (; i < nParams; i++) {
                U_32 len = 0;
                Type* type = JavaLabelPrepass::getTypeByDescriptorString(ci, cl, sigSuffix, len);
                assert(type!=NULL);
                paramTypes[i] = type;
                sigSuffix+=len;
            }
        } else {
            paramTypes = NULL;
        }
        retType = JavaLabelPrepass::getRetTypeBySignature(ci, cl, sigSuffix);
    }
    
    virtual ~JavaMethodSignature(){};
    virtual U_32 getNumParams() const { return nParams;}
    virtual Type** getParamTypes() const { return paramTypes;}
    virtual Type* getRetType() const {return retType;}
    virtual const char* getSignatureString() const {return signatureStr;}
private:
    U_32 nParams;
    Type** paramTypes;
    Type* retType;
    const char* signatureStr;

};

void JavaByteCodeTranslator::genCallWithResolve(JavaByteCodes bc, unsigned cpIndex) {
    assert(bc == OPCODE_INVOKESPECIAL || bc == OPCODE_INVOKESTATIC || bc == OPCODE_INVOKEVIRTUAL || bc == OPCODE_INVOKEINTERFACE);
    bool isStatic = bc == OPCODE_INVOKESTATIC;
    

    ObjectType* enclosingClass = methodToCompile.getParentType()->asObjectType();
    assert(enclosingClass!=NULL);
    const char* methodSig = methodSignatureString(cpIndex);
    assert(methodSig);
    JavaMethodSignature* sig = new (memManager) JavaMethodSignature(irBuilder.getIRManager()->getMemoryManager(), 
        compilationInterface, !isStatic, (Class_Handle)enclosingClass->getVMTypeHandle(), methodSig);
    U_32 numArgs = sig->getNumParams();
    assert(numArgs > 0 || isStatic);

    Opnd** args = popArgs(numArgs);
    Type* returnType = sig->getRetType();
    

    if (bc != OPCODE_INVOKEINTERFACE) {
        const char* kname = CompilationInterface::getMethodClassName(methodToCompile.getParentHandle(), cpIndex);
        const char* mname = CompilationInterface::getMethodName(methodToCompile.getParentHandle(), cpIndex);
        if (VMMagicUtils::isVMMagicClass(kname)) {
            assert(bc == OPCODE_INVOKESTATIC || bc == OPCODE_INVOKEVIRTUAL);
            UNUSED bool res = genVMMagic(mname, numArgs, args, returnType);    
            assert(res);
            return;
        } else if (isVMHelperClass(kname)) {
            assert(bc == OPCODE_INVOKESTATIC);
            bool res = genVMHelper(mname, numArgs, args, returnType);
            if (res) { //method is not a registered vmhelper name
                return;
            }
        }
    }

    Opnd* tauNullCheckedFirstArg = bc == OPCODE_INVOKESTATIC ? irBuilder.genTauSafe() :irBuilder.genTauCheckNull(args[0]);
    Opnd* tauTypesChecked = NULL;// let IRBuilder handle types

    Opnd* dst = irBuilder.genIndirectCallWithResolve(returnType, tauNullCheckedFirstArg, tauTypesChecked, 
                                numArgs, args, enclosingClass, bc, cpIndex, sig);
    if (returnType->tag != Type::Void) {
        pushOpnd(dst);
    }
}

void 
JavaByteCodeTranslator::invokevirtual(U_32 constPoolIndex) {
    MethodDesc* methodDesc = compilationInterface.getVirtualMethod(methodToCompile.getParentHandle(), constPoolIndex);
    if (!methodDesc) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_INVOKEVIRTUAL);
        }
        genCallWithResolve(OPCODE_INVOKEVIRTUAL, constPoolIndex);
        return;
    }
    jitrino_assert(methodDesc);
    U_32 numArgs = methodDesc->getNumParams();
    Opnd** srcOpnds = popArgs(numArgs);
    Type* returnType = methodDesc->getReturnType();

    const char* className = methodDesc->getParentType()->getName();
    if (VMMagicUtils::isVMMagicClass(className)) {
        UNUSED bool res = genVMMagic(methodDesc->getName(), numArgs, srcOpnds, returnType);
        assert(res);
        return;
    }

    // callvirt can throw a null pointer exception
    Opnd *tauNullChecked = irBuilder.genTauCheckNull(srcOpnds[0]);
    Opnd* thisOpnd = srcOpnds[0];
    if (methodDesc->getParentType() != thisOpnd->getType()) {
        if(Log::isEnabled()) {
            Log::out()<<"CHECKVIRTUAL "; thisOpnd->printWithType(Log::out()); Log::out() << " : ";
            methodDesc->getParentType()->print(Log::out());
            Log::out() <<"."<<methodDesc->getName()<<" "<< (int)methodDesc->getByteCodeSize()<< ::std::endl;
        }

        Type* type = thisOpnd->getType();
        if (!type->isNullObject() && !type->isUnresolvedType() && !type->isInterface()) {
            // needs to refine the method descriptor before doing any optimization
            MethodDesc *overriding = compilationInterface.getOverridingMethod(
                                     (NamedType*)type,methodDesc);
            if (overriding && overriding != methodDesc) {
                methodDesc = overriding;
            }
        }
    }

    if (returnType==NULL) {
        // This means that it was not resolved successfully but it can be resolved later
        // inside the callee (with some "magic" custom class loader for example)
        // Or respective exception will be thrown there (in the callee) at the attempt to create (new)
        // an object of unresolved type
        const char* methodSig_string = methodSignatureString(constPoolIndex);
        returnType = JavaLabelPrepass::getRetTypeBySignature(compilationInterface, methodToCompile.getParentHandle(), methodSig_string);
    }

    Opnd* dst = irBuilder.genTauVirtualCall(methodDesc,returnType,
                                            tauNullChecked, 
                                            0, // let IRBuilder handle types
                                            numArgs,
                                            srcOpnds);
    // push the return type
    if (returnType->tag != Type::Void)
        pushOpnd(dst);
}

void 
JavaByteCodeTranslator::invokespecial(U_32 constPoolIndex) {
    MethodDesc* methodDesc = compilationInterface.getSpecialMethod(methodToCompile.getParentHandle(), constPoolIndex);
    if (!methodDesc) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_INVOKESPECIAL);
        }
        genCallWithResolve(OPCODE_INVOKESPECIAL, constPoolIndex);
        return;
    }
    jitrino_assert(methodDesc);
    U_32 numArgs = methodDesc->getNumParams();
    Opnd** srcOpnds = popArgs(numArgs);
    Type* returnType = methodDesc->getReturnType();
    // invokespecial can throw a null pointer exception
    Opnd *tauNullChecked = irBuilder.genTauCheckNull(srcOpnds[0]);
    Opnd* dst;
    
    if (returnType == NULL) {
        // This means that it was not resolved successfully but it can be resolved later
        // inside the callee (with some "magic" custom class loader for example)
        // Or respective exception will be thrown there (in the callee) at the attempt to create (new)
        // an object of unresolved type
        returnType = typeManager.getNullObjectType();
    }
    dst = irBuilder.genDirectCall(methodDesc,
        returnType,
        tauNullChecked, 
        0, // let IRBuilder check types
        numArgs,
        srcOpnds);

    // push the return type
    if (returnType->tag != Type::Void) {
        pushOpnd(dst);
    }

}

void 
JavaByteCodeTranslator::invokestatic(U_32 constPoolIndex) {
    MethodDesc* methodDesc = compilationInterface.getStaticMethod(methodToCompile.getParentHandle(), constPoolIndex);
    if (!methodDesc) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_INVOKESTATIC);
        }
        genCallWithResolve(OPCODE_INVOKESTATIC, constPoolIndex);
        return;
    }

    jitrino_assert(methodDesc);
    U_32 numArgs = methodDesc->getNumParams();
    Opnd** srcOpnds = popArgs(numArgs);
    Type *returnType = methodDesc->getReturnType();
    if (returnType == NULL) {
        // This means that it was not resolved successfully but it can be resolved later
        // inside the callee (with some "magic" custom class loader for example)
        // Or respective exception will be thrown there (in the callee) at the attempt to create (new)
        // an object of unresolved type
        returnType = typeManager.getNullObjectType();
    }
    //
    //  Try some optimizations for Min, Max, Abs...
    //
    if (translationFlags.genMinMaxAbs == true &&
        genMinMax(methodDesc,numArgs,srcOpnds,returnType)) {
        return;
    } else
        genInvokeStatic(methodDesc,numArgs,srcOpnds,returnType);
}

void 
JavaByteCodeTranslator::invokeinterface(U_32 constPoolIndex,U_32 count) {
    MethodDesc* methodDesc = compilationInterface.getInterfaceMethod(methodToCompile.getParentHandle(), constPoolIndex);
    if (!methodDesc) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_INVOKEINTERFACE);
        }
        genCallWithResolve(OPCODE_INVOKEINTERFACE, constPoolIndex);
        return;
    }
    jitrino_assert(methodDesc);
    U_32 numArgs = methodDesc->getNumParams();
    Opnd** srcOpnds = popArgs(numArgs);
    Type* returnType = methodDesc->getReturnType();
    // callintf can throw a null pointer exception
    Opnd *tauNullChecked = irBuilder.genTauCheckNull(srcOpnds[0]);
    Opnd* thisOpnd = srcOpnds[0];
    Opnd* dst;
    if (methodDesc->getParentType() != thisOpnd->getType()) {
        Type * type = thisOpnd->getType();
        if (!type->isNullObject() && !type->isUnresolvedObject() && !type->isInterface()) {
            // need to refine the method descriptor before doing any optimization
            MethodDesc *overriding = compilationInterface.getOverridingMethod(
                                  (NamedType*)type,methodDesc);
            if (overriding && overriding != methodDesc && !overriding->getParentType()->isInterface()) {
                methodDesc = overriding;
            }
        }
    }

    if (returnType == NULL) {
        // This means that it was not resolved successfully but it can be resolved later
        // inside the callee (with some "magic" custom class loader for example)
        // Or respective exception will be thrown there (in the callee) at the attempt to create (new)
        // an object of unresolved type
        const char* methodSig_string = methodSignatureString(constPoolIndex);
        returnType = JavaLabelPrepass::getRetTypeBySignature(compilationInterface, methodToCompile.getParentHandle(), methodSig_string);
    }
    dst = irBuilder.genTauVirtualCall(methodDesc,
        returnType,
        tauNullChecked, 
        0, // let IRBuilder handle types
        numArgs,
        srcOpnds);
    // push the return type
    if (returnType->tag != Type::Void)
        pushOpnd(dst);
}
//-----------------------------------------------------------------------------
// object allocation byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::new_(U_32 constPoolIndex) {
    NamedType* type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex, ResolveNewCheck_DoCheck);
    jitrino_assert(type);
    if (type->isUnresolvedObject()) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_NEW);
        }
        pushOpnd(irBuilder.genNewObjWithResolve(methodToCompile.getParentType()->asObjectType(), constPoolIndex));
    } else {
#ifdef _DEBUG
        const char* typeName = type->getName();
        assert(!VMMagicUtils::isVMMagicClass(typeName));
#endif
        pushOpnd(irBuilder.genNewObj(type));
    }
}
void 
JavaByteCodeTranslator::newarray(U_8 atype) {
    NamedType* type = NULL;
    switch (atype) {
    case 4:    // boolean
        type = typeManager.getBooleanType(); break;
    case 5: // char
        type = typeManager.getCharType(); break;
    case 6: // float
        type = typeManager.getSingleType(); break;
    case 7: // double
        type = typeManager.getDoubleType(); break;
    case 8: // byte
        type = typeManager.getInt8Type(); break;
    case 9: // short
        type = typeManager.getInt16Type(); break;
    case 10: // int
        type = typeManager.getInt32Type(); break;
    case 11: // long
        type = typeManager.getInt64Type(); break;
    default: jitrino_assert(0);
    }
    Opnd* arrayOpnd = irBuilder.genNewArray(type,popOpnd());
    pushOpnd(arrayOpnd);
    if (translationFlags.optArrayInit) {
        const U_8* byteCodes = parser.getByteCodes();
        const U_32 byteCodeLength = parser.getByteCodeLength();
        U_32 offset = currentOffset + 2/*newarray length*/;
        U_32 length = checkForArrayInitializer(arrayOpnd, byteCodes, offset, byteCodeLength);
        currentOffset += length;
    }
}

void 
JavaByteCodeTranslator::anewarray(U_32 constPoolIndex) {
    NamedType* type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex);
    Opnd* sizeOpnd = popOpnd();
    if (type->isUnresolvedType()) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_ANEWARRAY);
        }
        //res type can be an array of multi array with uninitialized dimensions.
        pushOpnd(irBuilder.genNewArrayWithResolve(type, sizeOpnd, methodToCompile.getParentType()->asObjectType(), constPoolIndex));
    } else {
        pushOpnd(irBuilder.genNewArray(type,sizeOpnd));
    }
}

void 
JavaByteCodeTranslator::multianewarray(U_32 constPoolIndex,U_8 dimensions) {
    NamedType* arraytype = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex);
    assert(arraytype->isArray());
    jitrino_assert(dimensions > 0);
    Opnd** countOpnds = new (memManager) Opnd*[dimensions];
    // pop the sizes
    for (int i = dimensions - 1; i >= 0; i--) {
        countOpnds[i] = popOpnd();
    }
    if (arraytype->isUnresolvedType()) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_MULTIANEWARRAY);
        }
        pushOpnd(irBuilder.genMultianewarrayWithResolve(
            arraytype, methodToCompile.getParentType()->asObjectType(),constPoolIndex, dimensions,countOpnds
            ));
    } else {
        pushOpnd(irBuilder.genMultianewarray(arraytype,dimensions,countOpnds));
    }
}

void 
JavaByteCodeTranslator::arraylength() {
    Type::Tag arrayLenType = Type::Int32;
    pushOpnd(irBuilder.genArrayLen(typeManager.getInt32Type(),arrayLenType,popOpnd()));
}

void 
JavaByteCodeTranslator::athrow() {
    lastInstructionWasABranch = true;
    irBuilder.genThrow(Throw_NoModifier, popOpnd());
    LabelInst *label = irBuilder.createLabel();
    cfgBuilder.genBlockAfterCurrent(label);
}

//-----------------------------------------------------------------------------
// type checking byte codes
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::checkcast(U_32 constPoolIndex) {
    NamedType *type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex);
    Opnd* objOpnd = popOpnd();
    if (type->isUnresolvedType()) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_CHECKCAST);
        }
        pushOpnd(irBuilder.genCastWithResolve(objOpnd, type, methodToCompile.getParentType()->asObjectType(), constPoolIndex));
    } else {
        pushOpnd(irBuilder.genCast(objOpnd, type));
    }
}

int  
JavaByteCodeTranslator::instanceof(const U_8* bcp, U_32 constPoolIndex, U_32 off)   {
    NamedType *type = compilationInterface.getNamedType(methodToCompile.getParentHandle(), constPoolIndex);
    Opnd* src = popOpnd();
    Type* srcType = src->getType();
    Opnd* res = NULL;

    if (type->isUnresolvedType()) {
        if (!typeManager.isLazyResolutionMode()) {
            linkingException(constPoolIndex, OPCODE_INSTANCEOF);
        }
        res = irBuilder.genInstanceOfWithResolve(src, methodToCompile.getParentType()->asObjectType(), constPoolIndex);
    } else if( !srcType->isUnresolvedType() 
        && !srcType->isInterface() 
        && !Simplifier::isExactType(src) 
        && ((ObjectType*)type)->isFinalClass() )
    {
        // if target type is final just compare VTables
        // This can not be done by Simplifier as it can not generate branches
        // (srcType->isExactType() case will be simplified by Simplifier)

        Type* intPtrType = typeManager.getIntPtrType();

        LabelInst* ObjIsNullLabel = irBuilder.createLabel();
        LabelInst* Exit = irBuilder.createLabel();
        VarOpnd* resVar = irBuilder.genVarDef(intPtrType, false);

        newFallthroughBlock();

        Opnd * nullObj = irBuilder.genLdNull();
        irBuilder.genBranch(Type::IntPtr, Cmp_EQ, ObjIsNullLabel, nullObj, src);        

        // src is not null here
        newFallthroughBlock();
        Opnd* srcIsSafe = irBuilder.genTauSafe();
        Opnd* dynamicVTable = irBuilder.genTauLdVTable(src, srcIsSafe, srcType);
        Opnd* staticVTable = irBuilder.genGetVTable((ObjectType*) type);
        irBuilder.genStVar(resVar, irBuilder.genCmp(intPtrType,Type::IntPtr,Cmp_EQ,staticVTable,dynamicVTable));
        irBuilder.genJump(Exit);

        // src is null, instanceOf returns 0
        irBuilder.genLabel(ObjIsNullLabel);
        cfgBuilder.genBlockAfterCurrent(ObjIsNullLabel);
        Opnd * zero = irBuilder.genLdConstant((I_32)0);
        irBuilder.genStVar(resVar, zero);
        irBuilder.genJump(Exit);

        irBuilder.genLabel(Exit);
        cfgBuilder.genBlockAfterCurrent(Exit);
        res = irBuilder.genLdVar(intPtrType,resVar);
    } else {
        res = irBuilder.genInstanceOf(src,type);
    }

    assert(res);
    pushOpnd(res);
    return 3;
}

//
// synchronization
//
void 
JavaByteCodeTranslator::monitorenter() {
   if (translationFlags.ignoreSync) 
        popOpnd();
   else if (translationFlags.syncAsEnterFence)
        irBuilder.genMonitorEnterFence(popOpnd());
   else
        irBuilder.genMonitorEnter(popOpnd());
}

void 
JavaByteCodeTranslator::monitorexit() {
    if (translationFlags.ignoreSync || translationFlags.syncAsEnterFence)
        popOpnd();
    else
        irBuilder.genMonitorExit(popOpnd());
}

//-----------------------------------------------------------------------------
// variable access helpers
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::genLdVar(U_32 varIndex,JavaLabelPrepass::JavaVarType javaType) {
    Opnd *var = getVarOpndLdVar(javaType,varIndex);
    if (VMMagicUtils::isVMMagicClass(var->getType()->getName())) {
        var->setType(convertVMMagicType2HIR(typeManager, var->getType()));
    }
    Opnd *opnd;
    if (var->isVarOpnd()) {
        opnd = irBuilder.genLdVar(var->getType(),(VarOpnd*)var);
    } else {
        opnd = var;
    }
    pushOpnd(opnd);
}

void 
JavaByteCodeTranslator::genTypeStVar(uint16 varIndex) {
    Opnd *src = popOpnd();
    JavaLabelPrepass::JavaVarType javaType;
    if (src->getType() == typeManager.getIntPtrType())
        javaType = JavaLabelPrepass::RET;
    else
        javaType = JavaLabelPrepass::A;
    VarOpnd *var = getVarOpndStVar(javaType,varIndex,src);
    if (var != NULL) {
        irBuilder.genStVar(var,src);
    }
}

void 
JavaByteCodeTranslator::genStVar(U_32 varIndex,JavaLabelPrepass::JavaVarType javaType) {
    Opnd *src = popOpnd();
    VarOpnd *var = getVarOpndStVar(javaType,varIndex,src);
    if (var != NULL)
        irBuilder.genStVar(var,src);
}

//-----------------------------------------------------------------------------
// method return helpers
//-----------------------------------------------------------------------------
bool 
JavaByteCodeTranslator::needsReturnLabel(U_32 off) {
    if (!moreThanOneReturn && methodToCompile.getByteCodeSize()-1 != off) {
        if (!jumpToTheEnd) {
           // allocate one more label
           labels[numLabels++] = (LabelInst*)irBuilder.getInstFactory()->makeLabel();
        }
        jumpToTheEnd      = true;
        moreThanOneReturn = true;
    }
    return moreThanOneReturn;
}

// for non-void returns
void 
JavaByteCodeTranslator::genReturn(JavaLabelPrepass::JavaVarType javaType, U_32 off) {
    Opnd *ret = popOpndStVar();
    if (methodToCompile.isSynchronized()) {
        // Create a new block to break exception region.  The monexit exception should
        // go to unwind.
        cfgBuilder.genBlock(irBuilder.createLabel());
        if (methodToCompile.isStatic()) {
            //irBuilder.genTypeMonitorExit(methodToCompile.getParentType());
            Opnd* classObjectOpnd = irBuilder.genGetClassObj((ObjectType*) methodToCompile.getParentType());
            pushOpnd(classObjectOpnd);
            genMethodMonitorExit();
        } else {
            genLdVar(0,JavaLabelPrepass::A);
            genMethodMonitorExit();
        }
    }
    irBuilder.genReturn(ret,javaTypeMap[javaType]);
    opndStack.makeEmpty();
}

// for void returns
void
JavaByteCodeTranslator::genReturn(U_32 off) {
    if (methodToCompile.isSynchronized()) {
        // Create a new block to break exception region. The monexit exception should
        // go to unwind.
        cfgBuilder.genBlock(irBuilder.createLabel());
        if (methodToCompile.isStatic()) {
           // irBuilder.genTypeMonitorExit(methodToCompile.getParentType());
            Opnd* classObjectOpnd = irBuilder.genGetClassObj((ObjectType*) methodToCompile.getParentType());
            pushOpnd(classObjectOpnd);
            genMethodMonitorExit();
        } else {
            genLdVar(0,JavaLabelPrepass::A);
            genMethodMonitorExit();
        }
    }
    irBuilder.genReturn();
    // some manually written test case can leave non empty opnd stack after return
    opndStack.makeEmpty();
}

//-----------------------------------------------------------------------------
// arithmetic & logical helpers
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::genAdd(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genAdd(dstType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src1,src2));
}

void 
JavaByteCodeTranslator::genSub(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genSub(dstType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src1,src2));
}

void 
JavaByteCodeTranslator::genMul(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genMul(dstType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),src1,src2));
}

void 
JavaByteCodeTranslator::genDiv(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genDiv(dstType,Modifier(SignedOp)|Modifier(Strict_No),src1,src2));
}

void 
JavaByteCodeTranslator::genRem(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genRem(dstType,Modifier(SignedOp)|Modifier(Strict_No),src1,src2));
}

void 
JavaByteCodeTranslator::genNeg(Type* dstType) {
    Opnd*    src = popOpnd();
    pushOpnd(irBuilder.genNeg(dstType,src));
}

void 
JavaByteCodeTranslator::genFPAdd(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never);
    if (methodToCompile.isStrict())
        mod = mod | Modifier(Strict_Yes);
    else
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genAdd(dstType,mod,src1,src2));
}

void 
JavaByteCodeTranslator::genFPSub(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never);
    if (methodToCompile.isStrict())
        mod = mod | Modifier(Strict_Yes);
    else
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genSub(dstType,mod,src1,src2));
}

void 
JavaByteCodeTranslator::genFPMul(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never);
    if (methodToCompile.isStrict())
        mod  = mod | Modifier(Strict_Yes);
    else
        mod  = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genMul(dstType,mod,src1,src2));
}

void 
JavaByteCodeTranslator::genFPDiv(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    Modifier mod = SignedOp;
    if (methodToCompile.isStrict())
        mod = mod | Modifier(Strict_Yes);
    else
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genDiv(dstType,mod,src1,src2));
}

void 
JavaByteCodeTranslator::genFPRem(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    Modifier mod = SignedOp;
    if (methodToCompile.isStrict())
        mod = mod | Modifier(Strict_Yes);
    else
        mod = mod | Modifier(Strict_No);
    pushOpnd(irBuilder.genRem(dstType,mod,src1,src2));
}

void 
JavaByteCodeTranslator::genAnd(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genAnd(dstType,src1,src2));
}

void 
JavaByteCodeTranslator::genOr(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genOr(dstType,src1,src2));
}

void 
JavaByteCodeTranslator::genXor(Type* dstType) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    pushOpnd(irBuilder.genXor(dstType,src1,src2));
}

void 
JavaByteCodeTranslator::genShl(Type* type, ShiftMaskModifier mod) {
    Opnd*    shiftAmount = popOpnd();
    Opnd*    value = popOpnd(); 
    pushOpnd(irBuilder.genShl(type,mod,value,shiftAmount));
}

void 
JavaByteCodeTranslator::genShr(Type* type, SignedModifier mod1,
                               ShiftMaskModifier mod2) {
    Opnd*    shiftAmount = popOpnd();
    Opnd*    value = popOpnd(); 
    pushOpnd(irBuilder.genShr(type,Modifier(mod1)|Modifier(mod2), value, shiftAmount));
}

//-----------------------------------------------------------------------------
// array access helpers
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::genArrayLoad(Type* type) {
    Opnd* index = popOpnd();
    Opnd* base = popOpnd();
    pushOpnd(irBuilder.genLdElem(type,base,index));
}

void 
JavaByteCodeTranslator::genTypeArrayLoad() {
    Opnd* index = popOpnd();
    Opnd* base = popOpnd();
    Type *type = base->getType();
    if (!type->isArrayType()) {
        if (type->isNullObject()) {
            irBuilder.genThrowSystemException(CompilationInterface::Exception_NullPointer);
            pushOpnd(irBuilder.genLdNull());
            return;
        }
        if (Log::isEnabled()) {
            Log::out() << "Array type is ";
            type->print(Log::out()); Log::out() << ::std::endl;
            stateInfo->stack[5].type->print(Log::out()); Log::out() << ::std::endl;
            Log::out() << "CONFLICT IN ARRAY ACCESS\n";
        }
        type = typeManager.getSystemObjectType();
    } else
        type = ((ArrayType*)type)->getElementType();
    pushOpnd(irBuilder.genLdElem(type,base,index));
}

void 
JavaByteCodeTranslator::genArrayStore(Type* type) {
    Opnd*    value = popOpnd();
    Opnd*    index = popOpnd();
    Opnd*    base = popOpnd();
    irBuilder.genStElem(type,base,index,value);
}

void 
JavaByteCodeTranslator::genTypeArrayStore() {
    Opnd*    value = popOpnd();
    Opnd*    index = popOpnd();
    Opnd*    base = popOpnd();
    Type *type = base->getType();
    if (!type->isArrayType()) {
        if (type->isNullObject()) {
            irBuilder.genThrowSystemException(CompilationInterface::Exception_NullPointer);
            return;
        }
        type = typeManager.getSystemObjectType();
        Log::out() << "CONFLICT IN ARRAY ACCESS\n";
    } else
        type = ((ArrayType*)type)->getElementType();
    irBuilder.genStElem(type,base,index,value);
}

//-----------------------------------------------------------------------------
// control transfer helpers
//-----------------------------------------------------------------------------
void 
JavaByteCodeTranslator::genIf1(ComparisonModifier mod,
                               I_32 targetOffset,
                               I_32 nextOffset) {
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    Opnd*    src2 = irBuilder.genLdConstant((I_32)0);
    irBuilder.genBranch(Type::Int32,mod,target,src1,src2);
}

void 
JavaByteCodeTranslator::genIf1Commute(ComparisonModifier mod,
                                      I_32 targetOffset,
                                      I_32 nextOffset) {
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    Opnd*    src2 = irBuilder.genLdConstant((I_32)0);
    irBuilder.genBranch(Type::Int32,mod,target,src2,src1);
}

void 
JavaByteCodeTranslator::genIf2(ComparisonModifier mod,
                               I_32 targetOffset,
                               I_32 nextOffset) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    irBuilder.genBranch(Type::Int32,mod,target,src1,src2);
}

void 
JavaByteCodeTranslator::genIf2Commute(ComparisonModifier mod,
                                      I_32 targetOffset,
                                      I_32 nextOffset) {
    Opnd*    src2 = popOpnd();
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));
    irBuilder.genBranch(Type::Int32,mod,target,src2,src1);
}

void 
JavaByteCodeTranslator::genIfNull(ComparisonModifier mod,
                                  I_32 targetOffset,
                                  I_32 nextOffset) {
    Opnd*    src1 = popOpnd();
    if (targetOffset == nextOffset)
        return;
    if (targetOffset < nextOffset) {
        irBuilder.genPseudoThrow();
    }
    lastInstructionWasABranch = true;
    checkStack();
    LabelInst *target = getLabel(labelId(targetOffset));

    if (src1->getType() == typeManager.getNullObjectType()) {
        if (mod == Cmp_Zero)
            irBuilder.genJump(target);
        return;
    }
    irBuilder.genBranch(Type::SystemObject,mod,target,src1);
}

void 
JavaByteCodeTranslator::genThreeWayCmp(Type::Tag cmpType,
                                       ComparisonModifier src1ToSrc2) {
    Opnd* src2 = popOpnd();
    Opnd* src1 = popOpnd();
    Type* dstType = typeManager.getInt32Type();
    pushOpnd(irBuilder.genCmp3(dstType,cmpType,src1ToSrc2,src1,src2));
}

//-----------------------------------------------------------------------------
// method calls helpers
//-----------------------------------------------------------------------------

void 
JavaByteCodeTranslator::genInvokeStatic(MethodDesc * methodDesc,
                                        U_32       numArgs,
                                        Opnd **      srcOpnds,
                                        Type *       returnType) {
    Opnd *dst;

    const char* kname = methodDesc->getParentType()->getName(); 
    const char* mname = methodDesc->getName(); 
    if (VMMagicUtils::isVMMagicClass(kname)) {
        UNUSED bool res = genVMMagic(mname, numArgs, srcOpnds, returnType);    
        assert(res);
        return;
    } else if (isVMHelperClass(kname) && !methodDesc->isNative()) {
        bool res = genVMHelper(mname, numArgs, srcOpnds, returnType);
        if (res) {
            return;
        }
    }
    Opnd *tauNullChecked = irBuilder.genTauSafe(); // always safe, is a static method call
    Type* resType = returnType;
    if (VMMagicUtils::isVMMagicClass(resType->getName())) {
        resType = convertVMMagicType2HIR(typeManager, resType);
    }
    dst = irBuilder.genDirectCall(methodDesc, 
                        resType,
                        tauNullChecked,
                        0, // let IRBuilder check types
                        numArgs,
                        srcOpnds);
    if (returnType->tag != Type::Void)
        pushOpnd(dst);
}

void
JavaByteCodeTranslator::newFallthroughBlock() {
    LabelInst * labelInst = irBuilder.createLabel();
    irBuilder.genFallThroughLabel(labelInst);
    cfgBuilder.genBlockAfterCurrent(labelInst);
}

bool
JavaByteCodeTranslator::genMinMax(MethodDesc * methodDesc, 
                                  U_32       numArgs,
                                  Opnd **      srcOpnds,
                                  Type *       returnType) {

    const char *className = methodDesc->getParentType()->getName();
    if (strcmp(className, "java/lang/Math") == 0) {
        const char *methodName = methodDesc->getName();
        //
        //  Check for certain math methods and inline them
        // 
        if (strcmp(methodName, "min") == 0) {
            assert(numArgs == 2);
            Opnd *src0 = srcOpnds[0];
            Opnd *src1 = srcOpnds[1];
            Type *type = src0->getType();
            assert(type == src1->getType());

            IRManager& irm = *irBuilder.getIRManager();
            MethodDesc& md = irm.getMethodDesc();
            if (Log::isEnabled()) {
                Log::out() << "Saw call to java/lang/Math::min from "
                           << md.getParentType()->getName()
                           << "::"
                           << md.getName()
                           << ::std::endl;
            }
            Opnd *res = irBuilder.genMin(type, src0, src1);
            if (res) {
                pushOpnd(res);
                return true;
            }
        } else if (strcmp(methodName, "max") == 0) {
            assert(numArgs == 2);
            Opnd *src0 = srcOpnds[0];
            Opnd *src1 = srcOpnds[1];
            Type *type = src0->getType();
            assert(type == src1->getType());
            
            IRManager& irm = *irBuilder.getIRManager();
            MethodDesc& md = irm.getMethodDesc();
            if (Log::isEnabled()) {
                Log::out() << "Saw call to java/lang/Math::max from "
                           << md.getParentType()->getName()
                           << "::"
                           << md.getName()
                           << ::std::endl;
            }
            
            Opnd *res = irBuilder.genMax(type, src0, src1);
            if (res) {
                pushOpnd(res);
                return true;
            }
            
        } else if (strcmp(methodName, "abs") == 0) {
            assert(numArgs == 1);
            Opnd *src0 = srcOpnds[0];
            Type *type = src0->getType();
            
            IRManager& irm = *irBuilder.getIRManager();
            MethodDesc& md = irm.getMethodDesc();
            if (Log::isEnabled()) {
                Log::out() << "Saw call to java/lang/Math::abs from "
                           << md.getParentType()->getName()
                           << "::"
                           << md.getName()
                           << ::std::endl;
            }
            
            Opnd *res = irBuilder.genAbs(type, src0);
            if (res) {
                pushOpnd(res);
                return true;
            }
        } else {
            return false;
        }
    }
    return false;
}

//------------------------------------------------
//  synchronization helpers
//------------------------------------------------

void
JavaByteCodeTranslator::genMethodMonitorEnter() {
    if (translationFlags.ignoreSync) {
        popOpnd();
        return;
    }
    if (translationFlags.syncAsEnterFence) {
        irBuilder.genMonitorEnterFence(popOpnd());
    } 
    else if (! translationFlags.onlyBalancedSync) {
        irBuilder.genMonitorEnter(popOpnd());
    }
    else {
        assert(lockAddr == NULL && oldLockValue == NULL);
        Opnd * obj = popOpnd();
        Type * lockType = typeManager.getUInt16Type();
        Type * lockAddrType = typeManager.getManagedPtrType(lockType);
        Type * oldValueType = typeManager.getInt32Type();
        lockAddr = irBuilder.genLdLockAddr(lockAddrType,obj);
        oldLockValue = irBuilder.genBalancedMonitorEnter(oldValueType,obj,lockAddr);
    }
}

void
JavaByteCodeTranslator::genMethodMonitorExit() {
    if (translationFlags.ignoreSync || translationFlags.syncAsEnterFence) {
        popOpnd();
        return;
    }
    
    if (! translationFlags.onlyBalancedSync) {
        irBuilder.genMonitorExit(popOpnd());
    }
    else {
        assert(lockAddr != NULL && oldLockValue != NULL);
        irBuilder.genBalancedMonitorExit(popOpnd(),lockAddr,oldLockValue);
    }
}

U_32 JavaByteCodeTranslator::checkForArrayInitializer(Opnd* arrayOpnd, const U_8* byteCodes, U_32 offset, const U_32 byteCodeLength)
{
    assert(offset < byteCodeLength);
    const U_32 MIN_NUMBER_OF_INIT_ELEMS = 2;

    const U_8 BYTE_JAVA_SIZE    = 1;
    const U_8 SHORT_JAVA_SIZE   = 2;
    const U_8 INT_JAVA_SIZE     = 4;
    const U_8 LONG_JAVA_SIZE    = 8;

    // Skip short array initializers.
    // Average length of an array element initializer is 4.
    if ((byteCodeLength - offset)/4 < MIN_NUMBER_OF_INIT_ELEMS) return 0;

    // Size of the array elements
    U_8 elem_size = 0;
    // Number of initialized array elements
    U_32 elems = 0;

    ArrayType* arrayType = arrayOpnd->getType()->asArrayType();
    assert(arrayType);
    Type* elemType = arrayType->getElementType();
    if (elemType->isBoolean() || elemType->isInt1()) {
        elem_size = BYTE_JAVA_SIZE;
    } else if (elemType->isInt2() || elemType->isChar()) {
        elem_size = SHORT_JAVA_SIZE;
    } else if (elemType->isInt4() || elemType->isSingle()) {
        elem_size = INT_JAVA_SIZE;
    } else if (elemType->isInt8() || elemType->isDouble()) {
        elem_size = LONG_JAVA_SIZE;
    } else {
        assert(0);
    }

    ::std::vector<uint64> array_data;

    // Current offset.
    U_32 off = offset;
    U_32 predoff = offset;
    // Array element indexes
    uint64 oldIndex = 0;
    uint64 newIndex = 0;
    // Array element value
    uint64 value = 0;

    bool exitScan = false;
    U_32 tmpOff = 0;

    while (byteCodes[off++] == 0x59/*dup*/) {
        if (off >= byteCodeLength) break;

        // Get array element index
        tmpOff = getNumericValue(byteCodes, off, byteCodeLength, newIndex);
        if (!tmpOff || ((off += tmpOff) >= byteCodeLength)) break;
        if (newIndex != (oldIndex++)) break;

        // Get array element value
        tmpOff = getNumericValue(byteCodes, off, byteCodeLength, value);
        if (!tmpOff || ((off += tmpOff) >= byteCodeLength)) break;

        // Store array element
        switch (byteCodes[off++]) {
            case 0x4f:        // iastore
                assert(elem_size == INT_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x50:        // lastore
                assert(elem_size == LONG_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x51:        // fastore
                assert(elem_size == INT_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x52:        // dastore
                assert(elem_size == LONG_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x54:        // bastore
                assert(elem_size == BYTE_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x55:        // castore
                assert(elem_size == SHORT_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            case 0x56:        // sastore
                assert(elem_size == SHORT_JAVA_SIZE);
                array_data.push_back((uint64)value);
                break;
            default:
                exitScan = true;
                break;
        }
        if (exitScan || (off >= byteCodeLength)) break;
        predoff = off;
        elems++;
    }/*end_while*/

    if (elems < MIN_NUMBER_OF_INIT_ELEMS) return 0;

    const U_32 data_size = elems* elem_size;
    U_8* init_array_data = new U_8[data_size];

    for (U_32 i = 0; i < elems; i++) {
        switch (elem_size) {
            case BYTE_JAVA_SIZE:
                init_array_data[i] = (U_8)(array_data[i]);
                break;
            case SHORT_JAVA_SIZE:
                *((uint16*)(init_array_data + (i * SHORT_JAVA_SIZE))) = (uint16)(array_data[i]);
                break;
            case INT_JAVA_SIZE:
                *((U_32*)(init_array_data + (i * INT_JAVA_SIZE))) = (U_32)(array_data[i]);
                break;
            case LONG_JAVA_SIZE:
                *((uint64*)(init_array_data + (i * LONG_JAVA_SIZE))) = (uint64)(array_data[i]);
                break;
           default:
                assert(0);
        }
    }

    Type* returnType = typeManager.getVoidType();
    Opnd* arrayDataOpnd = irBuilder.genLdConstant((POINTER_SIZE_SINT)init_array_data);
    Opnd* arrayElemsOffset = irBuilder.genLdConstant((I_32)(arrayType->getArrayElemOffset()));
    Opnd* elemsOpnd = irBuilder.genLdConstant((I_32)data_size);

    const U_32 numArgs = 4;
    Opnd* args[numArgs] = {arrayOpnd, arrayElemsOffset, arrayDataOpnd, elemsOpnd};
    irBuilder.genJitHelperCall(InitializeArray, returnType, numArgs, args);


    return predoff - offset;
}

U_32 JavaByteCodeTranslator::getNumericValue(const U_8* byteCodes, U_32 offset, const U_32 byteCodeLength, uint64& value) {
    assert(offset < byteCodeLength);
    U_32 off = offset;
    switch (byteCodes[off++]) {
        case 0x02:        // iconst_m1
            value = (uint64)(-1);
            break;
        case 0x03:        // iconst_0
        case 0x09:        // lconst_0
            value = 0;
            break;
        case 0x04:        // iconst_1
        case 0x0a:        // lconst_1
            value = 1;
            break;
        case 0x05:        // iconst_2
            value = 2;
            break;
        case 0x06:        // iconst_3
            value = 3;
            break;
        case 0x07:        // iconst_4
            value = 4;
            break;
        case 0x08:        // iconst_5
            value = 5;
            break;
        case 0x0b:        // fconst_0
            {
                float val = 0.0f;
                value = (uint64)(*((U_32*)(&val)));
            }
            break;
        case 0x0c:        // fconst_1
            {
                float val = 1.0f;
                value = (uint64)(*((U_32*)(&val)));
            }
            break;
        case 0x0d:        // fconst_2
            {
                float val = 2.0f;
                value = (uint64)(*((U_32*)(&val)));
            }
            break;
        case 0x0e:        // dconst_0
            {
                double val = 0.0;
                value = *((uint64*)(&val));
            }
            break;
        case 0x0f:        // dconst_1
            {
                double val = 1.0;
                value = *((uint64*)(&val));
            }
            break;
        case 0x10:        // bipush
            if (off >= byteCodeLength) return 0;
            value = (uint64)si8(byteCodes + (off++));
            break;
        case 0x11:        // sipush
            if ((off + 1) >= byteCodeLength) return 0;
            value = (uint64)si16(byteCodes + off);
            off += 2;
            break;
        case 0x12:        // ldc
            {
                if (off >= byteCodeLength) return 0;
                U_32 constPoolIndex = su8(byteCodes + (off++));
                // load 32-bit quantity from constant pool
                Type* constantType = compilationInterface.getConstantType(&methodToCompile,constPoolIndex);
                if ( !(constantType->isInt4() || constantType->isSingle()) ) {
                    // only integer and floating-point types 
                    //     are implemented for streamed array loads
                    return 0;
                }
                const void* constantAddress =
                    compilationInterface.getConstantValue(&methodToCompile,constPoolIndex);
                value = *(U_32*)constantAddress;
            }
            break;
        case 0x13:        // ldc_w
            {
                if ((off + 1) >= byteCodeLength) return 0;
                U_32 constPoolIndex = su16(byteCodes + off);
                // load 32-bit quantity from constant pool
                Type* constantType = compilationInterface.getConstantType(&methodToCompile,constPoolIndex);
                if ( !(constantType->isInt4() || constantType->isSingle()) ) {
                    // only integer and floating-point types 
                    //     are implemented for streamed array loads
                    return 0;
                }
                const void* constantAddress =
                    compilationInterface.getConstantValue(&methodToCompile,constPoolIndex);
                value = *(U_32*)constantAddress;
            }
            off += 2;
            break;
        case 0x14:        // ldc2_w
            {
                if ((off + 1) >= byteCodeLength) return 0;
                U_32 constPoolIndex = su16(byteCodes + off);
                // load 64-bit quantity from constant pool
                Type* constantType = compilationInterface.getConstantType(&methodToCompile,constPoolIndex);
                if ( !(constantType->isInt8() || constantType->isDouble()) ) {
                    // only integer and floating-point types 
                    //     are implemented for streamed array loads
                    return 0;
                }
                const void* constantAddress =
                    compilationInterface.getConstantValue(&methodToCompile,constPoolIndex);
                value = *(uint64*)constantAddress;
            }
            off += 2;
            break;
        default:
            return 0;
    }
    return off - offset;
}

bool JavaByteCodeTranslator::genVMMagic(const char* mname, U_32 numArgs, Opnd **srcOpnds, Type *magicRetType) {
    Type* resType = convertVMMagicType2HIR(typeManager, magicRetType);
    Type* cmpResType = typeManager.getInt32Type();
    Opnd* tauSafe = irBuilder.genTauSafe();
    Opnd* arg0 = numArgs > 0 ? srcOpnds[0]: NULL;
    Opnd* arg1 = numArgs > 1 ? srcOpnds[1]: NULL;
    Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No);

    
    // max, one, zero
    POINTER_SIZE_INT theConst = 0;
    bool loadConst = false;
    if (!strcmp(mname, "max"))          { loadConst = true; theConst = ~(POINTER_SIZE_INT)0;}
    else if (!strcmp(mname, "one"))     { loadConst = true; theConst =  1;}
    else if (!strcmp(mname, "zero"))    { loadConst = true; theConst =  0;}
    else if (!strcmp(mname, "nullReference")) { loadConst = true; theConst =  0;}
    if (loadConst) {
        ConstInst::ConstValue v;
#ifdef _EM64T_
        v.i8 = theConst;
#else
        v.i4 = theConst;        
#endif
        Opnd* res = irBuilder.genLdConstant(typeManager.getUIntPtrType(), v);

        if (resType->isPtr()) {
            res = irBuilder.genConv(resType, resType->tag, mod, res);
        }
        pushOpnd(res);
        return true;
    }

    //
    // prefetch
    //
    if (!strcmp(mname, "prefetch"))
    {
        Opnd* prefetchingAddress = arg0;
        irBuilder.genPrefetch(prefetchingAddress);
        return true;
    }

    //
    // fromXXX, toXXX - static creation from something
    //
    if (!strcmp(mname, "fromLong") 
        || !strcmp(mname, "fromIntSignExtend") 
        || !strcmp(mname, "fromIntZeroExtend")
        || !strcmp(mname, "fromObject")  
        || !strcmp(mname, "toAddress") 
        || !strcmp(mname, "toObjectReference")
        || !strcmp(mname, "toInt")
        || !strcmp(mname, "toLong")
        || !strcmp(mname, "toObjectRef")
        || !strcmp(mname, "toWord")
        || !strcmp(mname, "toAddress")
        || !strcmp(mname, "toObject")
        || !strcmp(mname, "toExtent")
        || !strcmp(mname, "toOffset"))
    {
        assert(numArgs == 1);
        Type* srcType = arg0->getType();
        if (resType == srcType) {
            pushOpnd(irBuilder.genCopy(arg0));
            return true;
        }
        Opnd* res = NULL;
        
        if ((srcType->isObject() && resType->isUnmanagedPtr())
            || (resType->isObject() && srcType->isUnmanagedPtr())) 
        {
            res = irBuilder.genConvUnmanaged(resType, resType->tag, mod, arg0);
        } else if (!strcmp(mname, "fromIntZeroExtend")) {
            res = irBuilder.genConvZE(resType, resType->tag, mod, arg0);
        } else {
            res = irBuilder.genConv(resType, resType->tag, mod, arg0);
        }
        pushOpnd(res);
        return true;
    }

    //
    // is<Smth> one arg testing
    //
    bool isOp = false;
    if (!strcmp(mname, "isZero")) { isOp = true; theConst = 0; }
    else if (!strcmp(mname, "isMax")) { isOp = true; theConst = ~(POINTER_SIZE_INT)0; }
    else if (!strcmp(mname, "isNull")) { isOp = true; theConst = 0; }
    if (isOp) {
        assert(numArgs == 1);
        Opnd* res = irBuilder.genCmp(cmpResType, arg0->getType()->tag, Cmp_EQ, arg0, irBuilder.genLdConstant((POINTER_SIZE_SINT)theConst));
        pushOpnd(res);
        return true;
    }


    //
    // EQ, GE, GT, LE, LT, sXX - 2 args compare
    //
    ComparisonModifier cm = Cmp_Mask;
    bool commuteOpnds=false;
    if (!strcmp(mname, "EQ"))         { cm = Cmp_EQ; }
    else if (!strcmp(mname, "equals")){ cm = Cmp_EQ; }
    else if (!strcmp(mname, "NE"))    { cm = Cmp_NE_Un; }
    else if (!strcmp(mname, "GE"))    { cm = Cmp_GTE_Un;}
    else if (!strcmp(mname, "GT"))    { cm = Cmp_GT_Un; }
    else if (!strcmp(mname, "LE"))    { cm = Cmp_GTE_Un; commuteOpnds = true;}
    else if (!strcmp(mname, "LT"))    { cm = Cmp_GT_Un;  commuteOpnds = true;}
    else if (!strcmp(mname, "sGE"))   { cm = Cmp_GTE;}
    else if (!strcmp(mname, "sGT"))   { cm = Cmp_GT; }
    else if (!strcmp(mname, "sLE"))   { cm = Cmp_GTE; commuteOpnds = true;}
    else if (!strcmp(mname, "sLT"))   { cm = Cmp_GT;  commuteOpnds = true;}

    if (cm!=Cmp_Mask) {
        assert(numArgs == 2);
        assert(arg0->getType() == arg1->getType());
        Opnd* op0 = commuteOpnds ? arg1 : arg0;
        Opnd* op1 = commuteOpnds ? arg0 : arg1;
        Opnd* res = irBuilder.genCmp(cmpResType, arg0->getType()->tag, cm, op0, op1);
        pushOpnd(res);
        return true;
    }

   
    //
    // plus, minus, xor, or, and ... etc - 1,2 args arithmetics
    //
    if (!strcmp(mname, "plus")) { 
        assert(numArgs==2); 
        if (resType->isPtr()) {
            pushOpnd(irBuilder.genAddScaledIndex(arg0, arg1)); 
        } else {
            pushOpnd(irBuilder.genAdd(resType, mod, arg0, arg1)); 
        }
        return true;
    }
    if (!strcmp(mname, "minus")){ 
        assert(numArgs==2); 
        if (resType->isPtr()) {
            Type* negType = arg1->getType()->isUIntPtr() ? typeManager.getIntPtrType() : arg1->getType();
            Opnd* negArg1 = irBuilder.genNeg(negType, arg1);
            pushOpnd(irBuilder.genAddScaledIndex(arg0, negArg1)); 
        } else {
            pushOpnd(irBuilder.genSub(resType, mod, arg0, arg1)); 
        }
        return true;
    }
    if (!strcmp(mname, "or"))   { assert(numArgs==2); pushOpnd(irBuilder.genOr (resType, arg0, arg1)); return true;}
    if (!strcmp(mname, "xor"))  { assert(numArgs==2); pushOpnd(irBuilder.genXor(resType, arg0, arg1)); return true;}
    if (!strcmp(mname, "and"))  { assert(numArgs==2); pushOpnd(irBuilder.genAnd(resType, arg0, arg1)); return true;}
    if (!strcmp(mname, "not"))  { assert(numArgs==1); pushOpnd(irBuilder.genNot(resType, arg0)); return true;}
    if (!strcmp(mname, "diff")) { assert(numArgs==2); pushOpnd(irBuilder.genSub(resType, mod, arg0, arg1)); return true;}

    
    //
    // shifts
    //
    Modifier shMod(ShiftMask_Masked);
    if (!strcmp(mname, "lsh"))      {assert(numArgs==2); pushOpnd(irBuilder.genShl(resType, shMod|SignedOp, arg0, arg1));  return true;}
    else if (!strcmp(mname, "rsha")){assert(numArgs==2); pushOpnd(irBuilder.genShr(resType, shMod|SignedOp, arg0, arg1)); return true;}
    else if (!strcmp(mname, "rshl")){assert(numArgs==2); pushOpnd(irBuilder.genShr(resType, shMod |UnsignedOp, arg0, arg1)); return true;}

    
    //
    // loadXYZ.. prepareXYZ..
    //
    if (!strcmp(mname, "loadObjectReference")
        || !strcmp(mname, "loadAddress")
        || !strcmp(mname, "loadWord")
        || !strcmp(mname, "loadByte")
        || !strcmp(mname, "loadChar")
        || !strcmp(mname, "loadDouble")
        || !strcmp(mname, "loadFloat")
        || !strcmp(mname, "loadInt")
        || !strcmp(mname, "loadLong")
        || !strcmp(mname, "loadShort")
        || !strcmp(mname, "prepareWord")
        || !strcmp(mname, "prepareObjectReference")
        || !strcmp(mname, "prepareAddress")
        || !strcmp(mname, "prepareInt"))
    {
        assert(numArgs == 1 || numArgs == 2);
        Opnd* effectiveAddress = arg0;
        if (numArgs == 2) {//load by offset
            effectiveAddress = irBuilder.genAddScaledIndex(arg0, arg1);
        }
        Opnd* res = irBuilder.genTauLdInd(AutoCompress_No, resType, resType->tag, effectiveAddress, tauSafe, tauSafe);
        pushOpnd(res);
        return true;
    }

    //
    // store(XYZ)
    //
    if (!strcmp(mname, "store")) {
        assert(numArgs==2 || numArgs == 3);
        Opnd* effectiveAddress = arg0;
        if (numArgs == 3) { // store by offset
            effectiveAddress = irBuilder.genAddScaledIndex(arg0, srcOpnds[2]);
        }
        irBuilder.genTauStInd(arg1->getType(), effectiveAddress, arg1, tauSafe, tauSafe, tauSafe);
        return true;
    }

    if (!strcmp(mname, "attempt")) {
        assert(numArgs == 3 || numArgs == 4);
        Opnd* effectiveAddress = arg0;
        if (numArgs == 4) { // offset opnd
            effectiveAddress = irBuilder.genAddScaledIndex(arg0, srcOpnds[3]);
        }
        Opnd* opnds[3] = {effectiveAddress, arg1, srcOpnds[2]};
        Opnd* res = irBuilder.genJitHelperCall(LockedCompareAndExchange, resType, 3, opnds);
        pushOpnd(res);
        return true;
    }

    //
    //Arrays
    //
    if (!strcmp(mname, "create")) { assert(numArgs==1); pushOpnd(irBuilder.genNewArray(resType->asNamedType(),arg0)); return true;} 
    if (!strcmp(mname, "set")) {
        assert(numArgs == 3);
        Opnd* arg2 = srcOpnds[2];
        Type* opType = convertVMMagicType2HIR(typeManager, arg2->getType());
        irBuilder.genStElem(opType, arg0, arg1, arg2, tauSafe, tauSafe, tauSafe); 
        return true;
    }
    if (!strcmp(mname, "get")) {
        assert(numArgs == 2);
        Opnd* res = irBuilder.genLdElem(resType, arg0, arg1, tauSafe, tauSafe);
        pushOpnd(res);
        return true;
    }
    if (!strcmp(mname, "length")) {    
        pushOpnd(irBuilder.genArrayLen(typeManager.getInt32Type(), Type::Int32, arg0));
        return true;
    }

    return false;
}

bool JavaByteCodeTranslator::genVMHelper(const char* mname, U_32 numArgs, Opnd **srcOpnds, Type *returnType) {
    Type* resType = VMMagicUtils::isVMMagicClass(returnType->getName()) ? convertVMMagicType2HIR(typeManager, returnType) : returnType;

//VMHelper methods

    if (!strcmp(mname,"getTlsBaseAddress")) {
        assert(numArgs == 0);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_GC_GET_TLS_BASE, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"newResolvedUsingAllocHandleAndSize")) {
        assert(numArgs == 2);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_NEW_RESOLVED_USING_VTABLE_AND_SIZE, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"newVectorUsingAllocHandle")) {
        assert(numArgs == 2);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_NEW_VECTOR_USING_VTABLE, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"monitorEnter")) {
        assert(numArgs == 1);
        irBuilder.genVMHelperCall(VM_RT_MONITOR_ENTER, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname,"monitorExit")) {
        assert(numArgs == 1);
        irBuilder.genVMHelperCall(VM_RT_MONITOR_EXIT, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname,"writeBarrier")) {
        assert(numArgs == 3);
        irBuilder.genVMHelperCall(VM_RT_GC_HEAP_WRITE_REF, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname, "memset0"))
    {
	assert(numArgs == 2);
        irBuilder.genJitHelperCall(Memset0, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname, "prefetch"))
    {
        assert(numArgs == 3);
        irBuilder.genJitHelperCall(Prefetch, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname,"getInterfaceVTable")) {
        assert(numArgs == 2);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_GET_INTERFACE_VTABLE_VER0, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"checkCast")) {
        assert(numArgs == 2);
        irBuilder.genVMHelperCall(VM_RT_CHECKCAST, resType, numArgs, srcOpnds);
        return true;
    }

    if (!strcmp(mname,"instanceOf")) {
        assert(numArgs == 2);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_INSTANCEOF, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }


    //no VMHelpers exist for these magics -> use internal JIT helpers

    if (!strcmp(mname,"isArray")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassIsArray, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getAllocationHandle")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassGetAllocationHandle, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getTypeSize")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassGetTypeSize, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getArrayElemSize")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassGetArrayElemSize, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"isInterface")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassIsInterface, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"isFinal")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassIsFinal, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getArrayClass")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassGetArrayClass, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"isFinalizable")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassIsFinalizable, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getFastTypeCheckDepth")) {
        assert(numArgs == 1 && srcOpnds[0]->getType()->isUnmanagedPtr());
        Opnd* res = irBuilder.genJitHelperCall(ClassGetFastCheckDepth, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"isVMMagicPackageSupported")) {
        assert(numArgs == 0);
        ObjectType* base = compilationInterface.findClassUsingBootstrapClassloader(VMHELPER_TYPE_NAME);
        int ready = base!=NULL && !base->needsInitialization() ? 1 : 0;
        Opnd* res = irBuilder.genLdConstant((I_32)ready);
        pushOpnd(res);
        return true;
    }

    if (!strcmp(mname,"getHashcode")) {
        assert(numArgs == 1);
        Opnd* res = irBuilder.genVMHelperCall(VM_RT_GET_IDENTITY_HASHCODE, resType, numArgs, srcOpnds);
        pushOpnd(res);
        return true;
    }
    
    return false;
}

} //namespace Jitrino 
