コード例 #1
0
ファイル: ee_il_dll.hpp プロジェクト: DrewScoggins/coreclr
FORCEINLINE
void Compiler::eeGetMethodSig(CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sigRet, CORINFO_CLASS_HANDLE owner)
{
    info.compCompHnd->getMethodSig(methHnd, sigRet, owner);

    assert(!varTypeIsComposite(JITtype2varType(sigRet->retType)) || sigRet->retTypeClass != nullptr);
}
コード例 #2
0
ファイル: ee_il_dll.hpp プロジェクト: DrewScoggins/coreclr
inline var_types Compiler::eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig, bool* isPinned)
{
    CORINFO_CLASS_HANDLE argClass;
    CorInfoTypeWithMod   type = info.compCompHnd->getArgType(sig, list, &argClass);
    *isPinned                 = ((type & ~CORINFO_TYPE_MASK) != 0);
    return JITtype2varType(strip(type));
}
コード例 #3
0
ファイル: rationalize.cpp プロジェクト: ROOTU/coreclr
void Rationalizer::RewriteNodeAsCall(GenTree**             use,
                                     ArrayStack<GenTree*>& parents,
                                     CORINFO_METHOD_HANDLE callHnd,
#ifdef FEATURE_READYTORUN_COMPILER
                                     CORINFO_CONST_LOOKUP entryPoint,
#endif
                                     GenTreeArgList* args)
{
    GenTree* const tree           = *use;
    GenTree* const treeFirstNode  = comp->fgGetFirstNode(tree);
    GenTree* const insertionPoint = treeFirstNode->gtPrev;

    BlockRange().Remove(treeFirstNode, tree);

    // Create the call node
    GenTreeCall* call = comp->gtNewCallNode(CT_USER_FUNC, callHnd, tree->gtType, args);

#if DEBUG
    CORINFO_SIG_INFO sig;
    comp->eeGetMethodSig(callHnd, &sig);
    assert(JITtype2varType(sig.retType) == tree->gtType);
#endif // DEBUG

    call = comp->fgMorphArgs(call);
    // Determine if this call has changed any codegen requirements.
    comp->fgCheckArgCnt();

#ifdef FEATURE_READYTORUN_COMPILER
    call->gtCall.setEntryPoint(entryPoint);
#endif

    // Replace "tree" with "call"
    if (parents.Height() > 1)
    {
        parents.Index(1)->ReplaceOperand(use, call);
    }
    else
    {
        // If there's no parent, the tree being replaced is the root of the
        // statement (and no special handling is necessary).
        *use = call;
    }

    comp->gtSetEvalOrder(call);
    BlockRange().InsertAfter(insertionPoint, LIR::Range(comp->fgSetTreeSeq(call), call));

    // Propagate flags of "call" to its parents.
    // 0 is current node, so start at 1
    for (int i = 1; i < parents.Height(); i++)
    {
        parents.Index(i)->gtFlags |= (call->gtFlags & GTF_ALL_EFFECT) | GTF_CALL;
    }

    // Since "tree" is replaced with "call", pop "tree" node (i.e the current node)
    // and replace it with "call" on parent stack.
    assert(parents.Top() == tree);
    (void)parents.Pop();
    parents.Push(call);
}
コード例 #4
0
ファイル: ee_il_dll.hpp プロジェクト: DrewScoggins/coreclr
FORCEINLINE
void Compiler::eeGetCallSiteSig(unsigned               sigTok,
                                CORINFO_MODULE_HANDLE  scope,
                                CORINFO_CONTEXT_HANDLE context,
                                CORINFO_SIG_INFO*      sigRet)
{
    info.compCompHnd->findCallSiteSig(scope, sigTok, context, sigRet);

    assert(!varTypeIsComposite(JITtype2varType(sigRet->retType)) || sigRet->retTypeClass != nullptr);
}
コード例 #5
0
ファイル: ee_il_dll.hpp プロジェクト: DrewScoggins/coreclr
inline var_types Compiler::eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig)
{
    CORINFO_CLASS_HANDLE argClass;
    return (JITtype2varType(strip(info.compCompHnd->getArgType(sig, list, &argClass))));
}
コード例 #6
0
ファイル: rationalize.cpp プロジェクト: DrewScoggins/coreclr
void Rationalizer::RewriteNodeAsCall(GenTree**             use,
                                     Compiler::fgWalkData* data,
                                     CORINFO_METHOD_HANDLE callHnd,
#ifdef FEATURE_READYTORUN_COMPILER
                                     CORINFO_CONST_LOOKUP entryPoint,
#endif
                                     GenTreeArgList* args)
{
    GenTreePtr tree          = *use;
    Compiler*  comp          = data->compiler;
    SplitData* tmpState      = (SplitData*)data->pCallbackData;
    GenTreePtr root          = tmpState->root;
    GenTreePtr treeFirstNode = comp->fgGetFirstNode(tree);
    GenTreePtr treeLastNode  = tree;
    GenTreePtr treePrevNode  = treeFirstNode->gtPrev;
    GenTreePtr treeNextNode  = treeLastNode->gtNext;

    // Create the call node
    GenTreeCall* call = comp->gtNewCallNode(CT_USER_FUNC, callHnd, tree->gtType, args);

#if DEBUG
    CORINFO_SIG_INFO sig;
    comp->eeGetMethodSig(callHnd, &sig);
    assert(JITtype2varType(sig.retType) == tree->gtType);
#endif // DEBUG

    call = comp->fgMorphArgs(call);
    // Determine if this call has changed any codegen requirements.
    comp->fgCheckArgCnt();

#ifdef FEATURE_READYTORUN_COMPILER
    call->gtCall.setEntryPoint(entryPoint);
#endif

    // Replace "tree" with "call"
    if (data->parentStack->Height() > 1)
    {
        data->parentStack->Index(1)->ReplaceOperand(use, call);
    }
    else
    {
        // If there's no parent, the tree being replaced is the root of the
        // statement (and no special handling is necessary).
        *use = call;
    }

    // Rebuild the evaluation order.
    comp->gtSetStmtInfo(root);

    // Rebuild the execution order.
    comp->fgSetTreeSeq(call, treePrevNode);

    // Restore linear-order Prev and Next for "call".
    if (treePrevNode)
    {
        treeFirstNode         = comp->fgGetFirstNode(call);
        treeFirstNode->gtPrev = treePrevNode;
        treePrevNode->gtNext  = treeFirstNode;
    }
    else
    {
        // Update the linear oder start of "root" if treeFirstNode
        // appears to have replaced the original first node.
        assert(treeFirstNode == root->gtStmt.gtStmtList);
        root->gtStmt.gtStmtList = comp->fgGetFirstNode(call);
    }

    if (treeNextNode)
    {
        treeLastNode         = call;
        treeLastNode->gtNext = treeNextNode;
        treeNextNode->gtPrev = treeLastNode;
    }

    // Propagate flags of "call" to its parents.
    // 0 is current node, so start at 1
    for (int i = 1; i < data->parentStack->Height(); i++)
    {
        GenTree* node = data->parentStack->Index(i);
        node->gtFlags |= GTF_CALL;
        node->gtFlags |= call->gtFlags & GTF_ALL_EFFECT;
    }

    // Since "tree" is replaced with "call", pop "tree" node (i.e the current node)
    // and replace it with "call" on parent stack.
    assert(data->parentStack->Top() == tree);
    (void)data->parentStack->Pop();
    data->parentStack->Push(call);
}
コード例 #7
0
ファイル: hwintrinsicArm64.cpp プロジェクト: svick/coreclr
//------------------------------------------------------------------------
// impHWIntrinsic: dispatch hardware intrinsics to their own implementation
// function
//
// Arguments:
//    intrinsic -- id of the intrinsic function.
//    method    -- method handle of the intrinsic function.
//    sig       -- signature of the intrinsic call
//
// Return Value:
//    the expanded intrinsic.
//
GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
                                  CORINFO_METHOD_HANDLE method,
                                  CORINFO_SIG_INFO*     sig,
                                  bool                  mustExpand)
{
    GenTree*             retNode       = nullptr;
    GenTree*             op1           = nullptr;
    GenTree*             op2           = nullptr;
    GenTree*             op3           = nullptr;
    CORINFO_CLASS_HANDLE simdClass     = nullptr;
    var_types            simdType      = TYP_UNKNOWN;
    var_types            simdBaseType  = TYP_UNKNOWN;
    unsigned             simdSizeBytes = 0;

    switch (HWIntrinsicInfo::lookup(intrinsic).form)
    {
        case HWIntrinsicInfo::SimdBinaryOp:
        case HWIntrinsicInfo::SimdInsertOp:
        case HWIntrinsicInfo::SimdSelectOp:
        case HWIntrinsicInfo::SimdSetAllOp:
        case HWIntrinsicInfo::SimdUnaryOp:
        case HWIntrinsicInfo::SimdBinaryRMWOp:
        case HWIntrinsicInfo::SimdTernaryRMWOp:
        case HWIntrinsicInfo::Sha1HashOp:
            simdClass = sig->retTypeClass;
            break;
        case HWIntrinsicInfo::SimdExtractOp:
            info.compCompHnd->getArgType(sig, sig->args, &simdClass);
            break;
        default:
            break;
    }

    // Simd instantiation type check
    if (simdClass != nullptr)
    {
        compFloatingPointUsed = true;

        simdBaseType = getBaseTypeAndSizeOfSIMDType(simdClass, &simdSizeBytes);

        if (simdBaseType == TYP_UNKNOWN)
        {
            return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
        }
        simdType = getSIMDTypeForSize(simdSizeBytes);
    }

    switch (HWIntrinsicInfo::lookup(intrinsic).form)
    {
        case HWIntrinsicInfo::IsSupported:
            return gtNewIconNode((intrinsic == NI_ARM64_IsSupported_True) ? 1 : 0);

        case HWIntrinsicInfo::Unsupported:
            return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand);

        case HWIntrinsicInfo::UnaryOp:
            op1 = impPopStack().val;

            return gtNewScalarHWIntrinsicNode(JITtype2varType(sig->retType), op1, intrinsic);

        case HWIntrinsicInfo::SimdBinaryOp:
        case HWIntrinsicInfo::SimdBinaryRMWOp:
            // op1 is the first operand
            // op2 is the second operand
            op2 = impSIMDPopStack(simdType);
            op1 = impSIMDPopStack(simdType);

            return gtNewSimdHWIntrinsicNode(simdType, op1, op2, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::SimdTernaryRMWOp:
        case HWIntrinsicInfo::SimdSelectOp:
            // op1 is the first operand
            // op2 is the second operand
            // op3 is the third operand
            op3 = impSIMDPopStack(simdType);
            op2 = impSIMDPopStack(simdType);
            op1 = impSIMDPopStack(simdType);

            return gtNewSimdHWIntrinsicNode(simdType, op1, op2, op3, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::SimdSetAllOp:
            op1 = impPopStack().val;

            return gtNewSimdHWIntrinsicNode(simdType, op1, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::SimdUnaryOp:
            op1 = impSIMDPopStack(simdType);

            return gtNewSimdHWIntrinsicNode(simdType, op1, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::SimdExtractOp:
            if (!mustExpand && !impCheckImmediate(impStackTop(0).val, getSIMDVectorLength(simdSizeBytes, simdBaseType)))
            {
                // Immediate lane not constant or out of range
                return nullptr;
            }
            op2 = impPopStack().val;
            op1 = impSIMDPopStack(simdType);

            return gtNewScalarHWIntrinsicNode(JITtype2varType(sig->retType), op1, op2, intrinsic);

        case HWIntrinsicInfo::SimdInsertOp:
            if (!mustExpand && !impCheckImmediate(impStackTop(1).val, getSIMDVectorLength(simdSizeBytes, simdBaseType)))
            {
                // Immediate lane not constant or out of range
                return nullptr;
            }
            op3 = impPopStack().val;
            op2 = impPopStack().val;
            op1 = impSIMDPopStack(simdType);

            return gtNewSimdHWIntrinsicNode(simdType, op1, op2, op3, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::Sha1HashOp:
            op3 = impSIMDPopStack(simdType);
            op2 = impPopStack().val;
            op1 = impSIMDPopStack(simdType);

            return gtNewSimdHWIntrinsicNode(simdType, op1, op2, op3, intrinsic, simdBaseType, simdSizeBytes);

        case HWIntrinsicInfo::Sha1RotateOp:
            assert(sig->numArgs == 1);
            compFloatingPointUsed = true;
            return gtNewScalarHWIntrinsicNode(TYP_UINT, impPopStack().val, NI_ARM64_Sha1FixedRotate);

        default:
            JITDUMP("Not implemented hardware intrinsic form");
            assert(!"Unimplemented SIMD Intrinsic form");

            break;
    }
    return retNode;
}