Index: jitrino/src/optimizer/arraycopyoptimize.cpp =================================================================== --- jitrino/src/optimizer/arraycopyoptimize.cpp (revision 0) +++ jitrino/src/optimizer/arraycopyoptimize.cpp (revision 0) @@ -0,0 +1,490 @@ +#include "arraycopyoptimize.h" +#include "Opcode.h" + +namespace Jitrino { + + +ArrayCopyOptimizer::ArrayCopyOptimizer(IRManager& irmanager, MemoryManager& mm) +: acmm(mm) +{ + irm = &irmanager; + instFactory = &irm->getInstFactory(); + opndManager = &irm->getOpndManager(); + typeManager = &irm->getTypeManager(); + cfg = &irm->getFlowGraph(); + exam2Insts = new (acmm) Insts(acmm); +} + +bool +ArrayCopyOptimizer::methodIsArraycopy(MethodDesc * methodDesc) { + + return (strcmp(methodDesc->getName(),"arraycopy") == 0 && + strcmp(methodDesc->getParentType()->getName(),"java/lang/System") ==0); +} + + +bool +ArrayCopyOptimizer::arraycopyOptimizable(MethodDesc * methodDesc, + uint32 numArgs, + Opnd ** srcOpnds) { + + // + // an ArrayStoreException is thrown and the destination is not modified: + // + // - The src argument refers to an object that is not an array. + // - The dest argument refers to an object that is not an array. + // - The src argument and dest argument refer to arrays whose component types are different primitive types. + // - The src argument refers to an array with a primitive component type and the dest argument + // refers to an array with a reference component type. + // - The src argument refers to an array with a reference component type and the dest argument + // refers to an array with a primitive component type. + // + assert(numArgs == 5); + Opnd * src = srcOpnds[0]; + Type * srcType = src->getType(); + Opnd * dst = srcOpnds[2]; + Type * dstType = dst->getType(); + assert(srcType->isObject() && + srcOpnds[1]->getType()->isInt4() && // 1 - srcPos + dstType->isObject() && + srcOpnds[3]->getType()->isInt4() && // 3 - dstPos + srcOpnds[4]->getType()->isInt4()); // 4 - length + + bool throwsASE = false; + bool srcIsArray = srcType->isArray() && !srcType->isUnresolvedType(); + bool dstIsArray = dstType->isArray() && !dstType->isUnresolvedType(); + ArrayType* srcAsArrayType = srcType->asArrayType(); + ArrayType* dstAsArrayType = dstType->asArrayType(); + bool srcIsArrOfPrimitive = srcIsArray && VMInterface::isArrayOfPrimitiveElements(srcAsArrayType->getVMTypeHandle()); + bool dstIsArrOfPrimitive = dstIsArray && VMInterface::isArrayOfPrimitiveElements(dstAsArrayType->getVMTypeHandle()); + if ( !(srcIsArray && dstIsArray) ) { + throwsASE = true; + } else if ( srcIsArrOfPrimitive ) { + if( !dstIsArrOfPrimitive || srcType != dstType ) + throwsASE = true; + } else if( dstIsArrOfPrimitive ) { + throwsASE = true; + } else { // the both are of objects + // Here is some inaccuracy. If src is a subclass of dst there is no ASE for sure. + // If it is not, we should check the assignability of each element being copied. + // To avoid this we just reject the inlining of System::arraycopy call in this case. + NamedType* srcElemType = srcAsArrayType->getElementType(); + NamedType* dstElemType = dstAsArrayType->getElementType(); + throwsASE = srcElemType->getVMTypeHandle() != dstElemType->getVMTypeHandle(); + } + if ( throwsASE ) + return false; + else + return true; +} + + +void +ArrayCopyOptimizer::genOptimizedArrayCopy(uint32 numArgs, Opnd** srcOpnds, Node* firstNode, Node* lastNode) +{ + Opnd * src = srcOpnds[0]; + Opnd * srcPos = srcOpnds[1]; + Type * srcPosType = srcPos->getType(); + Opnd * dst = srcOpnds[2]; + Opnd * dstPos = srcOpnds[3]; + Type * dstPosType = dstPos->getType(); + Opnd * len = srcOpnds[4]; + + // + // Generate exception condition checks: + // chknull src + // chknull dst + // cmpbr srcPos < 0, boundsException + // cmpbr dstPos < 0, boundsException + // cmpbr len < 0, boundsException + // srcEnd = add srcPos, len + // srcLen = src.length + // cmpbr srcEnd > srcLen, boundsException + // dstEnd = add dstPos, len + // dstLen = dst.length + // cmpbr dstEnd > dstLen, boundsException + // Skip trivial: + // cmpbr (src == dst) && (dstPos == srcPos), Exit + // Choose a direction: + // cmpbr (dstPos > srcPos) && (src == dst), Reverse + // + // Intrinsic calls will be codeselected into rep move instruction. + // Direct: + // IntrinsicCall id=ArrayCopyDirect + // goto Exit + // Reverse: + // srcPos = srcPos + len - 1 + // dstPos = dstPos + len - 1 + // IntrinsicCall id=ArrayCopyReverse + // goto Exit + // + // boundsException: + // chkbounds -1, src + // Exit: + // + + Node *currNode, *prevNode; + Node* dispatch = cfg->getUnwindNode(); + + + // Referenced nodes creation + LabelInst * reverseCopying = (LabelInst*)instFactory->makeLabel(); + LabelInst * boundsException = (LabelInst*)instFactory->makeLabel(); + LabelInst * Exit = (LabelInst*)instFactory->makeLabel(); + + Node *exitNode = cfg->createBlockNode(Exit); + Node *BExcNode = cfg->createBlockNode(boundsException); + Node *RevCopyNode = cfg->createBlockNode(reverseCopying); + + //Other nodes creation and filling + Opnd *tauSrcNullChecked = genTauCheckNull(src, firstNode); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(firstNode, currNode); + cfg->addEdge(currNode, dispatch, 0.001); + prevNode = currNode; + Opnd *tauDstNullChecked = genTauCheckNull(dst, currNode); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.999); + prevNode = currNode; + Opnd *tauNullCheckedRefArgs = genTauAnd(tauSrcNullChecked, tauDstNullChecked, currNode); + + Type * intType = typeManager->getInt32Type(); + Type::Tag intTag = intType->tag; + Type * voidType = typeManager->getVoidType(); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode); + cfg->addEdge(currNode, BExcNode, 0.01); + prevNode = currNode; + + Opnd * zero = genLdConstant((int32)0, currNode); + Opnd * minusone = genLdConstant((int32)-1, currNode); + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,zero,srcPos,boundsException)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, BExcNode, 0.01); + prevNode = currNode; + + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,zero,dstPos,boundsException)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, BExcNode, 0.01); + prevNode = currNode; + + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,zero,len,boundsException)); + + Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, BExcNode, 0.01); + prevNode = currNode; + + Opnd * srcLen = genArrayLen(intType, intTag, src, tauSrcNullChecked, currNode); + Opnd * srcEnd = genAdd(intType,mod,srcPos,len, currNode); + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,srcEnd,srcLen,boundsException)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, BExcNode, 0.01); + prevNode = currNode; + + Opnd * dstEnd = genAdd(intType,mod,dstPos,len, currNode); + Opnd * dstLen = genArrayLen(intType, intTag, dst, tauDstNullChecked, currNode); + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,dstEnd,dstLen,boundsException)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, exitNode, 0.02); + prevNode = currNode; + + // The case of same arrays and same positions + Opnd * diff = genCmp3(intType,intTag,Cmp_GT,dstPos,srcPos, currNode); + Opnd * sameArrays = genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst, currNode); + Opnd * zeroDiff = genCmp(intType,intTag,Cmp_EQ,diff,zero, currNode); + Opnd * nothingToCopy = genAnd(intType,sameArrays,zeroDiff, currNode); + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,nothingToCopy,zero,Exit)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.98); + cfg->addEdge(currNode, RevCopyNode, 0.01); + prevNode = currNode; + + Opnd* tauTypesChecked = genTauSafe(currNode); + + // Choosing direction + Opnd * dstIsGreater = genCmp(intType,intTag,Cmp_GT,diff,zero, currNode); + Opnd * reverseCopy = genAnd(intType,sameArrays,dstIsGreater, currNode); + currNode->appendInst(instFactory->makeBranch(Cmp_GT,intTag,reverseCopy,zero,reverseCopying)); + + // node + currNode = cfg->createBlockNode(instFactory->makeLabel()); + cfg->addEdge(prevNode, currNode, 0.99); + cfg->addEdge(currNode, exitNode, 0.989); + cfg->addEdge(currNode, dispatch, 0.001); + + { // Direct Copying + genIntrinsicCall(ArrayCopyDirect,voidType, + tauNullCheckedRefArgs, + tauTypesChecked, + numArgs,srcOpnds, currNode); + } // End of Direct Copying + + + // Referenced nodes filling + // Reverse Copy + cfg->addEdge(RevCopyNode, exitNode, 0.989); + cfg->addEdge(RevCopyNode, dispatch, 0.001); + { // Reverse Copying + + Opnd* lastSrcIdx = genAdd(srcPosType,mod,srcEnd,minusone, RevCopyNode); + Opnd* lastDstIdx = genAdd(dstPosType,mod,dstEnd,minusone, RevCopyNode); + + Opnd** reverseArgs = new (acmm) Opnd*[numArgs]; + + reverseArgs[0] = srcOpnds[0]; // src + reverseArgs[1] = lastSrcIdx; // srcPos+len-1 + reverseArgs[2] = srcOpnds[2]; // dst + reverseArgs[3] = lastDstIdx; // dstPos+len-1 + reverseArgs[4] = srcOpnds[4]; // len + // copy + genIntrinsicCall(ArrayCopyReverse,voidType, + tauNullCheckedRefArgs, + tauTypesChecked, + numArgs,reverseArgs, RevCopyNode); + } // End of Reverse Copying + + // Bounds Exception + cfg->addEdge(BExcNode, exitNode, 0.999); + cfg->addEdge(BExcNode, dispatch, 0.001); + genTauCheckBounds(src,minusone,tauSrcNullChecked, BExcNode); + + // Exit + cfg->addEdge(exitNode, lastNode); + + cfg->removeEdge(lastNode->findEdge(true, dispatch)); + + cfg->orderNodes(true); +} + + +Opnd* +ArrayCopyOptimizer::createOpnd(Type* type) { + if (type->tag == Type::Void) + return OpndManager::getNullOpnd(); + return opndManager->createSsaTmpOpnd(type); +} + +Opnd* +ArrayCopyOptimizer::genTauCheckNull(Opnd* base, Node* currNode) +{ + Opnd* dst = createOpnd(typeManager->getTauType()); + currNode->appendInst(instFactory->makeTauCheckNull(dst, base)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genAnd(Type* dstType, Opnd* src1, Opnd* src2, Node* currNode) { + Opnd* dst = createOpnd(dstType); + currNode->appendInst(instFactory->makeAnd(dst, src1, src2)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genTauAnd(Opnd *src1, Opnd *src2, Node* currNode) { + if (src1->getId() > src2->getId()) { + Opnd *tmp = src1; + src1 = src2; + src2 = tmp; + } + Opnd* dst = createOpnd(typeManager->getTauType()); + Opnd* srcs[2] = { src1, src2 }; + currNode->appendInst(instFactory->makeTauAnd(dst, 2, srcs)); + + return dst; +} + +Opnd* +ArrayCopyOptimizer::genAdd(Type* dstType, Modifier mod, Opnd* src1, Opnd* src2, Node* currNode) { + Opnd* dst = createOpnd(dstType); + Inst *newi = instFactory->makeAdd(mod, dst, src1, src2); + currNode->appendInst(newi); + return dst; +} + + +Opnd* +ArrayCopyOptimizer::genLdConstant(int32 val, Node* currNode) { + Opnd* dst = createOpnd(typeManager->getInt32Type()); + currNode->appendInst(instFactory->makeLdConst(dst, val)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genArrayLen(Type* dstType, Type::Tag type, Opnd* array, Opnd* tauNonNull, Node* currNode) { + Opnd *tauIsArray = genTauHasType(array, array->getType(), currNode); + + return genTauArrayLen(dstType, type, array, tauNonNull, tauIsArray, currNode); +} + +Opnd* +ArrayCopyOptimizer::genTauArrayLen(Type* dstType, Type::Tag type, Opnd* array, + Opnd* tauNullChecked, Opnd *tauTypeChecked, Node* currNode) { + Opnd* dst = createOpnd(dstType); + currNode->appendInst(instFactory->makeTauArrayLen(dst, type, array, tauNullChecked, + tauTypeChecked)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genCmp3(Type* dstType, + Type::Tag instType, // source type for inst + ComparisonModifier mod, + Opnd* src1, + Opnd* src2, + Node* currNode) { + // result of comparison is always a 32-bit int + Opnd* dst = createOpnd(dstType); + Inst* i = instFactory->makeCmp3(mod, instType, dst, src1, src2); + currNode->appendInst(i); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genCmp(Type* dstType, + Type::Tag instType, // source type for inst + ComparisonModifier mod, + Opnd* src1, + Opnd* src2, + Node* currNode) { + // result of comparison is always a 32-bit int + Opnd* dst = createOpnd(dstType); + Inst *i = instFactory->makeCmp(mod, instType, dst, src1, src2); + currNode->appendInst(i); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genTauSafe(Node* currNode) { + Opnd* dst = createOpnd(typeManager->getTauType()); + currNode->appendInst(instFactory->makeTauSafe(dst)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genTauCheckBounds(Opnd* array, Opnd* index, Opnd *tauNullChecked, Node* currNode) { + Opnd *tauArrayTypeChecked = genTauHasType(array, array->getType(), currNode); + Opnd* arrayLen = genTauArrayLen(typeManager->getInt32Type(), Type::Int32, array, + tauNullChecked, tauArrayTypeChecked, currNode); + + Opnd* dst = genTauCheckBounds(arrayLen, index, currNode); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genTauCheckBounds(Opnd* ub, Opnd *index, Node* currNode) { + Opnd* dst = createOpnd(typeManager->getTauType()); + currNode->appendInst(instFactory->makeTauCheckBounds(dst, ub, index)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genTauHasType(Opnd *src, Type *castType, Node* currNode) { + Opnd* dst = createOpnd(typeManager->getTauType()); + currNode->appendInst(instFactory->makeTauHasType(dst, src, castType)); + return dst; +} + +Opnd* +ArrayCopyOptimizer::genIntrinsicCall(IntrinsicCallId intrinsicId, + Type* returnType, + Opnd* tauNullCheckedRefArgs, + Opnd* tauTypesChecked, + uint32 numArgs, + Opnd* args[], + Node* currNode) { + Opnd * dst = createOpnd(returnType); + currNode->appendInst(instFactory->makeIntrinsicCall(dst, intrinsicId, + tauNullCheckedRefArgs, + tauTypesChecked, + numArgs, args)); + return dst; +} + +void +ArrayCopyOptimizer::OptimizeArrayCopy(IRManager& irm) +{ + Opnd *srcOpnds[7]; + + const Nodes& nodes = irm.getFlowGraph().getNodes(); + for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) + { + Node* node = *it; + if (node->isBlockNode()) { + for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) { + Opcode opcode = inst->getOpcode(); + switch(opcode) + { + case Op_DirectCall: + { + MethodCallInst * call = (MethodCallInst *)inst; + MethodDesc * methDesc = call->getMethodDesc(); + if ( methodIsArraycopy(methDesc) ) + { + uint32 numArgs = call->getNumSrcOperands(); + + for (uint32 i = 0; igetSrc(i+2); + } + + if (arraycopyOptimizable(methDesc, numArgs-2, srcOpnds)) + { + exam2Insts->push_back(inst); + } + } + + break; + } + } + } + } + } + + for (Insts::iterator it = exam2Insts->begin(), end = exam2Insts->end(); it!=end; ++it) + { + Inst* inst = *it; + MethodCallInst * call = (MethodCallInst *)inst; + MethodDesc * methDesc = call->getMethodDesc(); + + uint32 numArgs = call->getNumSrcOperands(); + + for (uint32 i = 0; igetSrc(i+2); + } + + Node* currNode = inst->getNode(); + Node* nextNode = cfg->splitNodeAtInstruction(inst, true, true, instFactory->makeLabel()); + inst->unlink(); + cfg->removeEdge(currNode->findEdge(true, nextNode)); + + genOptimizedArrayCopy(numArgs-2, srcOpnds, currNode, nextNode); + } +} + + +} //namespace Jitrino \ No newline at end of file Index: jitrino/src/optimizer/arraycopyoptimize.h =================================================================== --- jitrino/src/optimizer/arraycopyoptimize.h (revision 0) +++ jitrino/src/optimizer/arraycopyoptimize.h (revision 0) @@ -0,0 +1,67 @@ + +#ifndef _ARRCOPYOPT_H_ +#define _ARRCOPYOPT_H_ + +#include "optpass.h" +#include "Inst.h" +#include "IRManager.h" + +namespace Jitrino { + +class ArrayCopyOptimizer { +public: + ArrayCopyOptimizer(IRManager& irmanager, MemoryManager& mm); + void OptimizeArrayCopy(IRManager& irm); + +private: + bool methodIsArraycopy(MethodDesc * methodDesc); + bool arraycopyOptimizable(MethodDesc * methodDesc, uint32 numArgs, Opnd ** srcOpnds); + void genOptimizedArrayCopy(uint32 numArgs, Opnd** srcOpnds, Node* firstNode, Node* lastNode); + + Opnd* createOpnd(Type* type); + Opnd* genTauCheckNull(Opnd* base, Node* currNode); + Opnd* genAnd(Type* dstType, Opnd* src1, Opnd* src2, Node* currNode); + Opnd* genTauAnd(Opnd *src1, Opnd *src2, Node* currNode); + Opnd* genAdd(Type* dstType, Modifier mod, Opnd* src1, Opnd* src2, Node* currNode); + Opnd* genLdConstant(int32 val, Node* currNode); + Opnd* genArrayLen(Type* dstType, Type::Tag type, Opnd* array, Opnd* tauNonNull, Node* currNode); + Opnd* genTauArrayLen(Type* dstType, Type::Tag type, Opnd* array, + Opnd* tauNullChecked, Opnd *tauTypeChecked, Node* currNode); + Opnd* genCmp3(Type* dstType, Type::Tag instType, // source type for inst + ComparisonModifier mod, Opnd* src1, Opnd* src2, Node* currNode); + Opnd* genCmp(Type* dstType, Type::Tag instType, // source type for inst + ComparisonModifier mod, Opnd* src1, Opnd* src2, Node* currNode); + Opnd* genTauSafe(Node* currNode); + Opnd* genTauCheckBounds(Opnd* array, Opnd* index, Opnd *tauNullChecked, Node* currNode); + Opnd* genTauCheckBounds(Opnd* ub, Opnd *index, Node* currNode); + Opnd* genTauHasType(Opnd *src, Type *castType, Node* currNode); + Opnd* genIntrinsicCall(IntrinsicCallId intrinsicId, Type* returnType, Opnd* tauNullCheckedRefArgs, + Opnd* tauTypesChecked, uint32 numArgs, Opnd* args[], Node* currNode); + + typedef StlList Insts; + +private: + IRManager* irm; + InstFactory* instFactory; + OpndManager* opndManager; + TypeManager* typeManager; + ControlFlowGraph* cfg; + MemoryManager& acmm; + + Insts *exam2Insts; +}; + +DEFINE_SESSION_ACTION(ArrayCopyOptimizePass, arrcpy, "Array Copy Optimization") + +void +ArrayCopyOptimizePass::_run(IRManager& irm) +{ + MemoryManager acMemManager("Arraycopyoptimizer mm"); + ArrayCopyOptimizer arrcpyopt(irm, acMemManager); + + arrcpyopt.OptimizeArrayCopy(irm); +} + +} //namespace Jitrino + +#endif // _ARRCOPYOPT_H_ Index: jitrino/src/optimizer/IRBuilder.cpp =================================================================== --- jitrino/src/optimizer/IRBuilder.cpp (revision 560245) +++ jitrino/src/optimizer/IRBuilder.cpp (working copy) @@ -931,7 +931,7 @@ } if (!dst) { dst = createOpnd(dstType); - Inst* inst = instFactory->makeConv(ovfMod, toType, dst, src); + Inst* inst = instFactory->makeConv(ovfMod, toType, dst, src); appendInst(inst); } insertHash(hashcode, src->getId(), dst->getInst()); @@ -983,7 +983,7 @@ } if (!dst) { dst = createOpnd(dstType); - Inst* inst = instFactory->makeConvZE(ovfMod, toType, dst, src); + Inst* inst = instFactory->makeConvZE(ovfMod, toType, dst, src); appendInst(inst); } insertHash(hashcode, src->getId(), dst->getInst()); @@ -1397,35 +1397,6 @@ } Opnd* -IRBuilder::genIntrinsicCall(IntrinsicCallId intrinsicId, - Type* returnType, - Opnd* tauNullCheckedRefArgs, - Opnd* tauTypesChecked, - uint32 numArgs, - Opnd* args[]) { - for (uint32 i=0; igetType()); - Opnd *tauTypesCheckedDst = genTauHasType(args[2], args[2]->getType()); - tauTypesChecked = genTauAnd(tauTypesCheckedSrc, - tauTypesCheckedDst); - } else { - tauTypesChecked = propagateCopy(tauTypesChecked); - } - - appendInst(instFactory->makeIntrinsicCall(dst, intrinsicId, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs, args)); - return dst; -} - -Opnd* IRBuilder::genJitHelperCall(JitHelperCallId helperId, Type* returnType, uint32 numArgs, Index: jitrino/src/translator/java/JavaByteCodeTranslator.cpp =================================================================== --- jitrino/src/translator/java/JavaByteCodeTranslator.cpp (revision 560245) +++ jitrino/src/translator/java/JavaByteCodeTranslator.cpp (working copy) @@ -1610,23 +1610,13 @@ returnType = typeManager.getNullObjectType(); } // - // Try some optimizations for System::arraycopy(...), Min, Max, Abs... + // Try some optimizations for Min, Max, Abs... // - if (translationFlags.genArrayCopyRepMove == true && - genArrayCopyRepMove(methodDesc,numArgs,srcOpnds)) { - return; - } else if (translationFlags.genArrayCopy == true && - genArrayCopy(methodDesc,numArgs,srcOpnds)) { - return; - } else if (translationFlags.genCharArrayCopy == true && - genCharArrayCopy(methodDesc,numArgs,srcOpnds,returnType)) { - return; - } else if (translationFlags.genMinMaxAbs == true && + if (translationFlags.genMinMaxAbs == true && genMinMax(methodDesc,numArgs,srcOpnds,returnType)) { return; - } else { + } else genInvokeStatic(methodDesc,numArgs,srcOpnds,returnType); - } } void @@ -2312,579 +2302,6 @@ } bool -JavaByteCodeTranslator::methodIsArraycopy(MethodDesc * methodDesc) { - - return (strcmp(methodDesc->getName(),"arraycopy") == 0 && - strcmp(methodDesc->getParentType()->getName(),"java/lang/System") ==0); -} - -bool -JavaByteCodeTranslator::arraycopyOptimizable(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - // - // an ArrayStoreException is thrown and the destination is not modified: - // - // - The src argument refers to an object that is not an array. - // - The dest argument refers to an object that is not an array. - // - The src argument and dest argument refer to arrays whose component types are different primitive types. - // - The src argument refers to an array with a primitive component type and the dest argument - // refers to an array with a reference component type. - // - The src argument refers to an array with a reference component type and the dest argument - // refers to an array with a primitive component type. - // - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Type * srcType = src->getType(); - Opnd * dst = srcOpnds[2]; - Type * dstType = dst->getType(); - assert(srcType->isObject() && - srcOpnds[1]->getType()->isInt4() && // 1 - srcPos - dstType->isObject() && - srcOpnds[3]->getType()->isInt4() && // 3 - dstPos - srcOpnds[4]->getType()->isInt4()); // 4 - length - - bool throwsASE = false; - bool srcIsArray = srcType->isArray() && !srcType->isUnresolvedType(); - bool dstIsArray = dstType->isArray() && !dstType->isUnresolvedType(); - ArrayType* srcAsArrayType = srcType->asArrayType(); - ArrayType* dstAsArrayType = dstType->asArrayType(); - bool srcIsArrOfPrimitive = srcIsArray && VMInterface::isArrayOfPrimitiveElements(srcAsArrayType->getVMTypeHandle()); - bool dstIsArrOfPrimitive = dstIsArray && VMInterface::isArrayOfPrimitiveElements(dstAsArrayType->getVMTypeHandle()); - if ( !(srcIsArray && dstIsArray) ) { - throwsASE = true; - } else if ( srcIsArrOfPrimitive ) { - if( !dstIsArrOfPrimitive || srcType != dstType ) - throwsASE = true; - } else if( dstIsArrOfPrimitive ) { - throwsASE = true; - } else { // the both are of objects - // Here is some inaccuracy. If src is a subclass of dst there is no ASE for sure. - // If it is not, we should check the assignability of each element being copied. - // To avoid this we just reject the inlining of System::arraycopy call in this case. - NamedType* srcElemType = srcAsArrayType->getElementType(); - NamedType* dstElemType = dstAsArrayType->getElementType(); - throwsASE = srcElemType->getVMTypeHandle() != dstElemType->getVMTypeHandle(); - } - if ( throwsASE ) - return false; - else - return true; -} - -bool -JavaByteCodeTranslator::genArrayCopyRepMove(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - if( !methodIsArraycopy(methodDesc) || - !arraycopyOptimizable(methodDesc,numArgs,srcOpnds) ) - { - // reject the inlining of System::arraycopy call - return false; - } - - if (Log::isEnabled()) { - Log::out() << "XXX array copy into 'rep move': "; - methodDesc->printFullName(Log::out()); - Log::out() << ::std::endl; - } - - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Opnd * srcPos = srcOpnds[1]; - Type * srcPosType = srcPos->getType(); - Opnd * dst = srcOpnds[2]; - Opnd * dstPos = srcOpnds[3]; - Type * dstPosType = dstPos->getType(); - Opnd * len = srcOpnds[4]; - - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // Skip trivial: - // cmpbr (src == dst) && (dstPos == srcPos), Exit - // Choose a direction: - // cmpbr (dstPos > srcPos) && (src == dst), Reverse - // - // Intrinsic calls will be codeselected into rep move instruction. - // Direct: - // IntrinsicCall id=ArrayCopyDirect - // goto Exit - // Reverse: - // srcPos = srcPos + len - 1 - // dstPos = dstPos + len - 1 - // IntrinsicCall id=ArrayCopyReverse - // goto Exit - // - // boundsException: - // chkbounds -1, src - // Exit: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - Opnd *tauNullCheckedRefArgs = irBuilder.genTauAnd(tauSrcNullChecked,tauDstNullChecked); - - LabelInst * reverseCopying = irBuilder.createLabel(); - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * Exit = irBuilder.createLabel(); - - Type * intType = typeManager.getInt32Type(); - Type::Tag intTag = intType->tag; - Type * voidType = typeManager.getVoidType(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - Opnd * minusone = irBuilder.genLdConstant((int32)-1); - - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,zero,len); - - Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,intTag,src); - Opnd * srcEnd = irBuilder.genAdd(intType,mod,srcPos,len); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,mod,dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,intTag,dst); - irBuilder.genBranch(intTag,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - - // The case of same arrays and same positions - Opnd * diff = irBuilder.genCmp3(intType,intTag,Cmp_GT,dstPos,srcPos); - Opnd * sameArrays = irBuilder.genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst); - Opnd * zeroDiff = irBuilder.genCmp(intType,intTag,Cmp_EQ,diff,zero); - Opnd * nothingToCopy = irBuilder.genAnd(intType,sameArrays,zeroDiff); - irBuilder.genBranch(intTag,Cmp_GT,Exit,nothingToCopy,zero); - - newFallthroughBlock(); - - Opnd* tauTypesChecked = irBuilder.genTauSafe(); - - // Choosing direction - Opnd * dstIsGreater = irBuilder.genCmp(intType,intTag,Cmp_GT,diff,zero); - Opnd * reverseCopy = irBuilder.genAnd(intType,sameArrays,dstIsGreater); - irBuilder.genBranch(intTag,Cmp_GT,reverseCopying,reverseCopy,zero); - - newFallthroughBlock(); - - { // Direct Copying - irBuilder.genIntrinsicCall(ArrayCopyDirect,voidType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,srcOpnds); - irBuilder.genJump(Exit); - } // End of Direct Copying - - irBuilder.genLabel(reverseCopying); - cfgBuilder.genBlockAfterCurrent(reverseCopying); - { // Reverse Copying - - Opnd* lastSrcIdx = irBuilder.genAdd(srcPosType,mod,srcEnd,minusone); - Opnd* lastDstIdx = irBuilder.genAdd(dstPosType,mod,dstEnd,minusone); - - Opnd** reverseArgs = new (memManager) Opnd*[numArgs]; - reverseArgs[0] = srcOpnds[0]; // src - reverseArgs[1] = lastSrcIdx; // srcPos+len-1 - reverseArgs[2] = srcOpnds[2]; // dst - reverseArgs[3] = lastDstIdx; // dstPos+len-1 - reverseArgs[4] = srcOpnds[4]; // len - // copy - irBuilder.genIntrinsicCall(ArrayCopyReverse,voidType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,reverseArgs); - irBuilder.genJump(Exit); - } // End of Reverse Copying - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - irBuilder.genTauCheckBounds(src,minusone,tauSrcNullChecked); - - irBuilder.genLabel(Exit); - cfgBuilder.genBlockAfterCurrent(Exit); - - return true; -} - -bool -JavaByteCodeTranslator::genArrayCopy(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds) { - - if( !methodIsArraycopy(methodDesc) || - !arraycopyOptimizable(methodDesc,numArgs,srcOpnds) ) - { - // reject the inlining of System::arraycopy call - return false; - } - - if (Log::isEnabled()) { - Log::out() << "XXX array copy: "; methodDesc->printFullName(Log::out()); Log::out() << ::std::endl; - } - - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Type * srcType = src->getType(); - Opnd * srcPos = srcOpnds[1]; - Type * srcPosType = srcPos->getType(); - Opnd * dst = srcOpnds[2]; - Type * dstType = dst->getType(); - Opnd * dstPos = srcOpnds[3]; - Type * dstPosType = dstPos->getType(); - Opnd * len = srcOpnds[4]; - - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // - // diff = Cmp3(dstPos,srcPos) - // // 1 if dstPos > srcPos - // // 0 if dstPos == srcPos - // // -1 if dstPos < srcPos - // if (src == dst && diff == 0) // nothing to do - // goto L1: - // - // if (diff > 0) - // goto reverseCopying: - // - // indexSrc = srcPos - // indexDst = dstPos - // increment = 1 - // copyDirectLoopHeader: - // if (indexSrc == srcEnd) - // goto L1: - // dst[indexDst] = src[indexSrc] - // indexSrc += increment - // indexDst += increment - // goto copyDirectLoopHeader: - // - // reverseCopying: - // indexSrc = srcPos + len - 1 - // indexDst = dstPos + len - 1 - // decrement = 1 - // copyReverseLoopHeader: - // if (indexSrc < srcPos) - // goto L1: - // dst[indexDst] = src[indexSrc] - // indexSrc -= decrement - // indexDst -= decrement - // goto copyReverseLoopHeader: - // - // boundsException: - // chkbounds -1, src - // L1: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - - LabelInst * reverseCopying = irBuilder.createLabel(); - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * L1 = irBuilder.createLabel(); - Type * intType = typeManager.getInt32Type(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - Opnd * one = irBuilder.genLdConstant((int32)1); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,len); - - Modifier mod = Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,Type::Int32,src); - Opnd * srcEnd = irBuilder.genAdd(intType,mod,srcPos,len); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,mod,dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,Type::Int32,dst); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - - // The case of same arrays and same positions - Opnd * diff = irBuilder.genCmp3(intType,Type::Int32,Cmp_GT,dstPos,srcPos); - Opnd * sameArrays = irBuilder.genCmp(intType,Type::IntPtr,Cmp_EQ,src,dst); - Opnd * zeroDiff = irBuilder.genCmp(intType,Type::Int32,Cmp_EQ,diff,zero); - Opnd * nothingToCopy = irBuilder.genAnd(intType,sameArrays,zeroDiff); - irBuilder.genBranch(Type::Int32,Cmp_GT,L1,nothingToCopy,zero); - - newFallthroughBlock(); - - // Choosing direction - - irBuilder.genBranch(Type::Int32,Cmp_GT,reverseCopying,diff,zero); - - newFallthroughBlock(); - - { //Direct Copying - - // indexes for using inside the loop - VarOpnd* srcPosVar = irBuilder.genVarDef(srcPosType, false); - VarOpnd* dstPosVar = irBuilder.genVarDef(dstPosType, false); - - irBuilder.genStVar(srcPosVar, srcPos); - irBuilder.genStVar(dstPosVar, dstPos); - - Opnd* srcPosOpnd = NULL; - Opnd* dstPosOpnd = NULL; - - // Loop Header - LabelInst * loopHead = irBuilder.createLabel(); - irBuilder.genLabel(loopHead); - cfgBuilder.genBlockAfterCurrent(loopHead); - - // loop exit condition (srcIndex = srcStartIndex + len) - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - irBuilder.genBranch(Type::Int32,Cmp_EQ,L1,srcPosOpnd,srcEnd); - - newFallthroughBlock(); - // array bounds have been checked directly - // the types have been checked above so tauAddressInRange is tauSafe - Opnd *tauSrcAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstBaseTypeChecked = irBuilder.genTauSafe(); - - // load indexes - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - dstPosOpnd = irBuilder.genLdVar(dstPosType,dstPosVar); - - Type* srcElemType = srcType->asArrayType()->getElementType(); - Type* dstElemType = dstType->asArrayType()->getElementType(); - - // copy element - // (Checks are performed before the loop) - Opnd* elem = irBuilder.genLdElem(srcElemType,src,srcPosOpnd, - tauSrcNullChecked, tauSrcAddressInRange); - irBuilder.genStElem(dstElemType,dst,dstPosOpnd,elem, - tauDstNullChecked, tauDstBaseTypeChecked, tauDstAddressInRange); - - // increment indexes - srcPosOpnd = irBuilder.genAdd(srcPosType,mod,srcPosOpnd,one); - dstPosOpnd = irBuilder.genAdd(dstPosType,mod,dstPosOpnd,one); - - // store indexes - irBuilder.genStVar(srcPosVar, srcPosOpnd); - irBuilder.genStVar(dstPosVar, dstPosOpnd); - - // back edge - irBuilder.genPseudoThrow(); - irBuilder.genJump(loopHead); - - } // End of Direct Copying - - { //Reverse Copying - irBuilder.genLabel(reverseCopying); - cfgBuilder.genBlockAfterCurrent(reverseCopying); - - // indexes for using inside the loop - VarOpnd* srcPosVar = irBuilder.genVarDef(srcPosType, false); - VarOpnd* dstPosVar = irBuilder.genVarDef(dstPosType, false); - - Opnd* lastSrcIdx = irBuilder.genSub(srcPosType,mod,srcEnd,one); - Opnd* lastDstIdx = irBuilder.genSub(dstPosType,mod,dstEnd,one); - - irBuilder.genStVar(srcPosVar, lastSrcIdx); - irBuilder.genStVar(dstPosVar, lastDstIdx); - - Opnd* srcPosOpnd = NULL; - Opnd* dstPosOpnd = NULL; - - // Loop Header - LabelInst * loopHead = irBuilder.createLabel(); - irBuilder.genLabel(loopHead); - cfgBuilder.genBlockAfterCurrent(loopHead); - - // loop exit condition (srcIndex < srcPos) - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - irBuilder.genBranch(Type::Int32,Cmp_GT,L1,srcPos,srcPosOpnd); - - newFallthroughBlock(); - // array bounds have been checked directly - // the types have been checked above so tauAddressInRange is tauSafe - Opnd *tauSrcAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstAddressInRange = irBuilder.genTauSafe(); - Opnd *tauDstBaseTypeChecked = irBuilder.genTauSafe(); - - // load indexes - srcPosOpnd = irBuilder.genLdVar(srcPosType,srcPosVar); - dstPosOpnd = irBuilder.genLdVar(dstPosType,dstPosVar); - - Type* srcElemType = srcType->asArrayType()->getElementType(); - Type* dstElemType = dstType->asArrayType()->getElementType(); - - // copy element - // (Checks are performed before the loop) - Opnd* elem = irBuilder.genLdElem(srcElemType,src,srcPosOpnd, - tauSrcNullChecked, tauSrcAddressInRange); - irBuilder.genStElem(dstElemType,dst,dstPosOpnd,elem, - tauDstNullChecked, tauDstBaseTypeChecked, tauDstAddressInRange); - - // decrement indexes - srcPosOpnd = irBuilder.genSub(srcPosType,mod,srcPosOpnd,one); - dstPosOpnd = irBuilder.genSub(dstPosType,mod,dstPosOpnd,one); - - // store indexes - irBuilder.genStVar(srcPosVar, srcPosOpnd); - irBuilder.genStVar(dstPosVar, dstPosOpnd); - - // back edge - irBuilder.genPseudoThrow(); - irBuilder.genJump(loopHead); - - } // End of Reverse Copying - - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - Opnd * minusOne = irBuilder.genLdConstant((int32)-1); - irBuilder.genTauCheckBounds(src,minusOne,tauSrcNullChecked); - - irBuilder.genLabel(L1); - cfgBuilder.genBlockAfterCurrent(L1); - - return true; -} - -bool -JavaByteCodeTranslator::genCharArrayCopy(MethodDesc * methodDesc, - uint32 numArgs, - Opnd ** srcOpnds, - Type * returnType) { - // - // Check if method is java/lang/System.arraycopy - // (Object src, int srcPos, Object dst, int dstPos, int len) - // - if (strcmp(methodDesc->getName(),"arraycopy") != 0 || - strcmp(methodDesc->getParentType()->getName(),"java/lang/System") !=0) - return false; - // - // Check if arguments are arrays of characters - // - assert(numArgs == 5); - Opnd * src = srcOpnds[0]; - Opnd * srcPos = srcOpnds[1]; - Opnd * dst = srcOpnds[2]; - Opnd * dstPos = srcOpnds[3]; - Opnd * len = srcOpnds[4]; - assert(src->getType()->isObject() && - srcPos->getType()->isInt4() && - dst->getType()->isObject() && - dstPos->getType()->isInt4() && - len->getType()->isInt4()); - Type * srcType = src->getType(); - Type * dstType = dst->getType(); - if (!(srcType->isArray() && dstType->isArray() && - ((ArrayType *)srcType)->getElementType()->isChar() && - ((ArrayType *)dstType)->getElementType()->isChar())) - return false; - - if (Log::isEnabled()) { - Log::out() << "XXX char array copy: "; methodDesc->printFullName(Log::out()); Log::out() << ::std::endl; - } - // - // Generate exception condition checks: - // chknull src - // chknull dst - // cmpbr srcPos < 0, boundsException - // cmpbr dstPos < 0, boundsException - // cmpbr len < 0, boundsException - // srcEnd = add srcPos, len - // srcLen = src.length - // cmpbr srcEnd > srcLen, boundsException - // dstEnd = add dstPos, len - // dstLen = dst.length - // cmpbr dstEnd > dstLen, boundsException - // callintr charArrayCopy(src,srcPos,dst,dstPos,len) - // goto L1: - // boundsException: - // chkbounds -1, src - // L1: - // - Opnd *tauSrcNullChecked = irBuilder.genTauCheckNull(src); - Opnd *tauDstNullChecked = irBuilder.genTauCheckNull(dst); - - LabelInst * boundsException = irBuilder.createLabel(); - LabelInst * L1 = irBuilder.createLabel(); - Type * intType = typeManager.getInt32Type(); - - newFallthroughBlock(); - Opnd * zero = irBuilder.genLdConstant((int32)0); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,srcPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,dstPos); - - newFallthroughBlock(); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,zero,len); - - newFallthroughBlock(); - Opnd * srcLen = irBuilder.genArrayLen(intType,Type::Int32,src); - Opnd * srcEnd = irBuilder.genAdd(intType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),srcPos,len); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,srcEnd,srcLen); - - newFallthroughBlock(); - Opnd * dstEnd = irBuilder.genAdd(intType,Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),dstPos,len); - Opnd * dstLen = irBuilder.genArrayLen(intType,Type::Int32,dst); - irBuilder.genBranch(Type::Int32,Cmp_GT,boundsException,dstEnd,dstLen); - - newFallthroughBlock(); - Opnd *tauNullCheckedRefArgs = - irBuilder.genTauAnd(tauSrcNullChecked, tauDstNullChecked); - Opnd *tauTypesChecked = 0; - irBuilder.genIntrinsicCall(CharArrayCopy,returnType, - tauNullCheckedRefArgs, - tauTypesChecked, - numArgs,srcOpnds); - irBuilder.genJump(L1); - - irBuilder.genLabel(boundsException); - cfgBuilder.genBlockAfterCurrent(boundsException); - Opnd * minusOne = irBuilder.genLdConstant((int32)-1); - irBuilder.genTauCheckBounds(src,minusOne,tauSrcNullChecked); - - irBuilder.genLabel(L1); - cfgBuilder.genBlockAfterCurrent(L1); - return true; -} - -bool JavaByteCodeTranslator::genMinMax(MethodDesc * methodDesc, uint32 numArgs, Opnd ** srcOpnds, @@ -3287,12 +2704,12 @@ if (loadConst) { ConstInst::ConstValue v; #ifdef _EM64T_ - v.i8 = theConst; + v.i8 = theConst; #else - v.i4 = theConst; + v.i4 = theConst; #endif Opnd* res = irBuilder.genLdConstant(typeManager.getUIntPtrType(), v); - + if (resType->isPtr()) { res = irBuilder.genConv(resType, resType->tag, mod, res); }