// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. extern ICorJitHost* g_jitHost; class CILJit : public ICorJitCompiler { CorJitResult __stdcall compileMethod(ICorJitInfo* comp, /* IN */ CORINFO_METHOD_INFO* methodInfo, /* IN */ unsigned flags, /* IN */ BYTE** nativeEntry, /* OUT */ ULONG* nativeSizeOfCode /* OUT */ ); void clearCache(void); BOOL isCacheCleanupRequired(void); void ProcessShutdownWork(ICorStaticInfo* statInfo); void getVersionIdentifier(GUID* versionIdentifier /* OUT */ ); unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags); void setRealJit(ICorJitCompiler* realJitCompiler); }; /***************************************************************************** * * Functions to get various handles */ FORCEINLINE void Compiler::eeGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedToken, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult) { info.compCompHnd->getCallInfo(pResolvedToken, pConstrainedToken, info.compMethodHnd, flags, pResult); } FORCEINLINE void Compiler::eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS accessFlags, CORINFO_FIELD_INFO* pResult) { info.compCompHnd->getFieldInfo(pResolvedToken, info.compMethodHnd, accessFlags, pResult); } /***************************************************************************** * * VOS info, method sigs, etc */ FORCEINLINE BOOL Compiler::eeIsValueClass(CORINFO_CLASS_HANDLE clsHnd) { return info.compCompHnd->isValueClass(clsHnd); } FORCEINLINE void Compiler::eeGetSig(unsigned sigTok, CORINFO_MODULE_HANDLE scope, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* retSig) { info.compCompHnd->findSig(scope, sigTok, context, retSig); assert(!varTypeIsComposite(JITtype2varType(retSig->retType)) || retSig->retTypeClass != nullptr); } 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); } /********************************************************************** * For varargs we need the number of arguments at the call site */ 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); } /*****************************************************************************/ 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)))); } /*****************************************************************************/ 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)); } /***************************************************************************** * * Native Direct Optimizations */ inline CORINFO_EE_INFO* Compiler::eeGetEEInfo() { if (!eeInfoInitialized) { info.compCompHnd->getEEInfo(&eeInfo); eeInfoInitialized = true; } return &eeInfo; } /***************************************************************************** * * Convert the type returned from the VM to a var_type. */ inline var_types JITtype2varType(CorInfoType type) { static const unsigned char varTypeMap[CORINFO_TYPE_COUNT] = { // see the definition of enum CorInfoType in file inc/corinfo.h TYP_UNDEF, // CORINFO_TYPE_UNDEF = 0x0, TYP_VOID, // CORINFO_TYPE_VOID = 0x1, TYP_BOOL, // CORINFO_TYPE_BOOL = 0x2, TYP_USHORT, // CORINFO_TYPE_CHAR = 0x3, TYP_BYTE, // CORINFO_TYPE_BYTE = 0x4, TYP_UBYTE, // CORINFO_TYPE_UBYTE = 0x5, TYP_SHORT, // CORINFO_TYPE_SHORT = 0x6, TYP_USHORT, // CORINFO_TYPE_USHORT = 0x7, TYP_INT, // CORINFO_TYPE_INT = 0x8, TYP_INT, // CORINFO_TYPE_UINT = 0x9, TYP_LONG, // CORINFO_TYPE_LONG = 0xa, TYP_LONG, // CORINFO_TYPE_ULONG = 0xb, TYP_I_IMPL, // CORINFO_TYPE_NATIVEINT = 0xc, TYP_I_IMPL, // CORINFO_TYPE_NATIVEUINT = 0xd, TYP_FLOAT, // CORINFO_TYPE_FLOAT = 0xe, TYP_DOUBLE, // CORINFO_TYPE_DOUBLE = 0xf, TYP_REF, // CORINFO_TYPE_STRING = 0x10, // Not used, should remove TYP_I_IMPL, // CORINFO_TYPE_PTR = 0x11, TYP_BYREF, // CORINFO_TYPE_BYREF = 0x12, TYP_STRUCT, // CORINFO_TYPE_VALUECLASS = 0x13, TYP_REF, // CORINFO_TYPE_CLASS = 0x14, TYP_STRUCT, // CORINFO_TYPE_REFANY = 0x15, // Generic type variables only appear when we're doing // verification of generic code, in which case we're running // in "import only" mode. Annoyingly the "import only" // mode of the JIT actually does a fair bit of compilation, // so we have to trick the compiler into thinking it's compiling // a real instantiation. We do that by just pretending we're // compiling the "object" instantiation of the code, i.e. by // turing all generic type variables refs, except for a few // choice places to do with verification, where we use // verification types and CLASS_HANDLEs to track the difference. TYP_REF, // CORINFO_TYPE_VAR = 0x16, }; // spot check to make certain enumerations have not changed assert(varTypeMap[CORINFO_TYPE_CLASS] == TYP_REF); assert(varTypeMap[CORINFO_TYPE_BYREF] == TYP_BYREF); assert(varTypeMap[CORINFO_TYPE_PTR] == TYP_I_IMPL); assert(varTypeMap[CORINFO_TYPE_INT] == TYP_INT); assert(varTypeMap[CORINFO_TYPE_UINT] == TYP_INT); assert(varTypeMap[CORINFO_TYPE_DOUBLE] == TYP_DOUBLE); assert(varTypeMap[CORINFO_TYPE_VOID] == TYP_VOID); assert(varTypeMap[CORINFO_TYPE_VALUECLASS] == TYP_STRUCT); assert(varTypeMap[CORINFO_TYPE_REFANY] == TYP_STRUCT); assert(type < CORINFO_TYPE_COUNT); assert(varTypeMap[type] != TYP_UNDEF); return ((var_types)varTypeMap[type]); }; inline CORINFO_CALLINFO_FLAGS combine(CORINFO_CALLINFO_FLAGS flag1, CORINFO_CALLINFO_FLAGS flag2) { return (CORINFO_CALLINFO_FLAGS)(flag1 | flag2); } inline CORINFO_CALLINFO_FLAGS Compiler::addVerifyFlag(CORINFO_CALLINFO_FLAGS flags) { if (tiVerificationNeeded) { flags = combine(flags, CORINFO_CALLINFO_VERIFICATION); } return flags; }