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