bool JavaByteCodeTranslator::genVMMagic()

in vm/jitrino/src/translator/java/JavaByteCodeTranslator.cpp [2742:2981]


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;
}