| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | extern ICorJitHost* g_jitHost; |
| 6 | |
| 7 | class CILJit : public ICorJitCompiler |
| 8 | { |
| 9 | CorJitResult __stdcall compileMethod(ICorJitInfo* comp, /* IN */ |
| 10 | CORINFO_METHOD_INFO* methodInfo, /* IN */ |
| 11 | unsigned flags, /* IN */ |
| 12 | BYTE** nativeEntry, /* OUT */ |
| 13 | ULONG* nativeSizeOfCode /* OUT */ |
| 14 | ); |
| 15 | |
| 16 | void clearCache(void); |
| 17 | BOOL isCacheCleanupRequired(void); |
| 18 | |
| 19 | void ProcessShutdownWork(ICorStaticInfo* statInfo); |
| 20 | |
| 21 | void getVersionIdentifier(GUID* versionIdentifier /* OUT */ |
| 22 | ); |
| 23 | |
| 24 | unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags); |
| 25 | |
| 26 | void setRealJit(ICorJitCompiler* realJitCompiler); |
| 27 | }; |
| 28 | |
| 29 | /***************************************************************************** |
| 30 | * |
| 31 | * Functions to get various handles |
| 32 | */ |
| 33 | |
| 34 | FORCEINLINE |
| 35 | void Compiler::eeGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, |
| 36 | CORINFO_RESOLVED_TOKEN* pConstrainedToken, |
| 37 | CORINFO_CALLINFO_FLAGS flags, |
| 38 | CORINFO_CALL_INFO* pResult) |
| 39 | { |
| 40 | info.compCompHnd->getCallInfo(pResolvedToken, pConstrainedToken, info.compMethodHnd, flags, pResult); |
| 41 | } |
| 42 | |
| 43 | FORCEINLINE |
| 44 | void Compiler::eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, |
| 45 | CORINFO_ACCESS_FLAGS accessFlags, |
| 46 | CORINFO_FIELD_INFO* pResult) |
| 47 | { |
| 48 | info.compCompHnd->getFieldInfo(pResolvedToken, info.compMethodHnd, accessFlags, pResult); |
| 49 | } |
| 50 | |
| 51 | /***************************************************************************** |
| 52 | * |
| 53 | * VOS info, method sigs, etc |
| 54 | */ |
| 55 | |
| 56 | FORCEINLINE |
| 57 | BOOL Compiler::eeIsValueClass(CORINFO_CLASS_HANDLE clsHnd) |
| 58 | { |
| 59 | return info.compCompHnd->isValueClass(clsHnd); |
| 60 | } |
| 61 | |
| 62 | FORCEINLINE |
| 63 | void Compiler::eeGetSig(unsigned sigTok, |
| 64 | CORINFO_MODULE_HANDLE scope, |
| 65 | CORINFO_CONTEXT_HANDLE context, |
| 66 | CORINFO_SIG_INFO* retSig) |
| 67 | { |
| 68 | info.compCompHnd->findSig(scope, sigTok, context, retSig); |
| 69 | |
| 70 | assert(!varTypeIsComposite(JITtype2varType(retSig->retType)) || retSig->retTypeClass != nullptr); |
| 71 | } |
| 72 | |
| 73 | FORCEINLINE |
| 74 | void Compiler::eeGetMethodSig(CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sigRet, CORINFO_CLASS_HANDLE owner) |
| 75 | { |
| 76 | info.compCompHnd->getMethodSig(methHnd, sigRet, owner); |
| 77 | |
| 78 | assert(!varTypeIsComposite(JITtype2varType(sigRet->retType)) || sigRet->retTypeClass != nullptr); |
| 79 | } |
| 80 | |
| 81 | /********************************************************************** |
| 82 | * For varargs we need the number of arguments at the call site |
| 83 | */ |
| 84 | |
| 85 | FORCEINLINE |
| 86 | void Compiler::eeGetCallSiteSig(unsigned sigTok, |
| 87 | CORINFO_MODULE_HANDLE scope, |
| 88 | CORINFO_CONTEXT_HANDLE context, |
| 89 | CORINFO_SIG_INFO* sigRet) |
| 90 | { |
| 91 | info.compCompHnd->findCallSiteSig(scope, sigTok, context, sigRet); |
| 92 | |
| 93 | assert(!varTypeIsComposite(JITtype2varType(sigRet->retType)) || sigRet->retTypeClass != nullptr); |
| 94 | } |
| 95 | |
| 96 | /*****************************************************************************/ |
| 97 | inline var_types Compiler::eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig) |
| 98 | { |
| 99 | CORINFO_CLASS_HANDLE argClass; |
| 100 | return (JITtype2varType(strip(info.compCompHnd->getArgType(sig, list, &argClass)))); |
| 101 | } |
| 102 | |
| 103 | /*****************************************************************************/ |
| 104 | inline var_types Compiler::eeGetArgType(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO* sig, bool* isPinned) |
| 105 | { |
| 106 | CORINFO_CLASS_HANDLE argClass; |
| 107 | CorInfoTypeWithMod type = info.compCompHnd->getArgType(sig, list, &argClass); |
| 108 | *isPinned = ((type & ~CORINFO_TYPE_MASK) != 0); |
| 109 | return JITtype2varType(strip(type)); |
| 110 | } |
| 111 | |
| 112 | /***************************************************************************** |
| 113 | * |
| 114 | * Native Direct Optimizations |
| 115 | */ |
| 116 | |
| 117 | inline CORINFO_EE_INFO* Compiler::eeGetEEInfo() |
| 118 | { |
| 119 | if (!eeInfoInitialized) |
| 120 | { |
| 121 | info.compCompHnd->getEEInfo(&eeInfo); |
| 122 | eeInfoInitialized = true; |
| 123 | } |
| 124 | |
| 125 | return &eeInfo; |
| 126 | } |
| 127 | |
| 128 | /***************************************************************************** |
| 129 | * |
| 130 | * Convert the type returned from the VM to a var_type. |
| 131 | */ |
| 132 | |
| 133 | inline var_types JITtype2varType(CorInfoType type) |
| 134 | { |
| 135 | |
| 136 | static const unsigned char varTypeMap[CORINFO_TYPE_COUNT] = { |
| 137 | // see the definition of enum CorInfoType in file inc/corinfo.h |
| 138 | TYP_UNDEF, // CORINFO_TYPE_UNDEF = 0x0, |
| 139 | TYP_VOID, // CORINFO_TYPE_VOID = 0x1, |
| 140 | TYP_BOOL, // CORINFO_TYPE_BOOL = 0x2, |
| 141 | TYP_USHORT, // CORINFO_TYPE_CHAR = 0x3, |
| 142 | TYP_BYTE, // CORINFO_TYPE_BYTE = 0x4, |
| 143 | TYP_UBYTE, // CORINFO_TYPE_UBYTE = 0x5, |
| 144 | TYP_SHORT, // CORINFO_TYPE_SHORT = 0x6, |
| 145 | TYP_USHORT, // CORINFO_TYPE_USHORT = 0x7, |
| 146 | TYP_INT, // CORINFO_TYPE_INT = 0x8, |
| 147 | TYP_INT, // CORINFO_TYPE_UINT = 0x9, |
| 148 | TYP_LONG, // CORINFO_TYPE_LONG = 0xa, |
| 149 | TYP_LONG, // CORINFO_TYPE_ULONG = 0xb, |
| 150 | TYP_I_IMPL, // CORINFO_TYPE_NATIVEINT = 0xc, |
| 151 | TYP_I_IMPL, // CORINFO_TYPE_NATIVEUINT = 0xd, |
| 152 | TYP_FLOAT, // CORINFO_TYPE_FLOAT = 0xe, |
| 153 | TYP_DOUBLE, // CORINFO_TYPE_DOUBLE = 0xf, |
| 154 | TYP_REF, // CORINFO_TYPE_STRING = 0x10, // Not used, should remove |
| 155 | TYP_I_IMPL, // CORINFO_TYPE_PTR = 0x11, |
| 156 | TYP_BYREF, // CORINFO_TYPE_BYREF = 0x12, |
| 157 | TYP_STRUCT, // CORINFO_TYPE_VALUECLASS = 0x13, |
| 158 | TYP_REF, // CORINFO_TYPE_CLASS = 0x14, |
| 159 | TYP_STRUCT, // CORINFO_TYPE_REFANY = 0x15, |
| 160 | |
| 161 | // Generic type variables only appear when we're doing |
| 162 | // verification of generic code, in which case we're running |
| 163 | // in "import only" mode. Annoyingly the "import only" |
| 164 | // mode of the JIT actually does a fair bit of compilation, |
| 165 | // so we have to trick the compiler into thinking it's compiling |
| 166 | // a real instantiation. We do that by just pretending we're |
| 167 | // compiling the "object" instantiation of the code, i.e. by |
| 168 | // turing all generic type variables refs, except for a few |
| 169 | // choice places to do with verification, where we use |
| 170 | // verification types and CLASS_HANDLEs to track the difference. |
| 171 | |
| 172 | TYP_REF, // CORINFO_TYPE_VAR = 0x16, |
| 173 | }; |
| 174 | |
| 175 | // spot check to make certain enumerations have not changed |
| 176 | |
| 177 | assert(varTypeMap[CORINFO_TYPE_CLASS] == TYP_REF); |
| 178 | assert(varTypeMap[CORINFO_TYPE_BYREF] == TYP_BYREF); |
| 179 | assert(varTypeMap[CORINFO_TYPE_PTR] == TYP_I_IMPL); |
| 180 | assert(varTypeMap[CORINFO_TYPE_INT] == TYP_INT); |
| 181 | assert(varTypeMap[CORINFO_TYPE_UINT] == TYP_INT); |
| 182 | assert(varTypeMap[CORINFO_TYPE_DOUBLE] == TYP_DOUBLE); |
| 183 | assert(varTypeMap[CORINFO_TYPE_VOID] == TYP_VOID); |
| 184 | assert(varTypeMap[CORINFO_TYPE_VALUECLASS] == TYP_STRUCT); |
| 185 | assert(varTypeMap[CORINFO_TYPE_REFANY] == TYP_STRUCT); |
| 186 | |
| 187 | assert(type < CORINFO_TYPE_COUNT); |
| 188 | assert(varTypeMap[type] != TYP_UNDEF); |
| 189 | |
| 190 | return ((var_types)varTypeMap[type]); |
| 191 | }; |
| 192 | |
| 193 | inline CORINFO_CALLINFO_FLAGS combine(CORINFO_CALLINFO_FLAGS flag1, CORINFO_CALLINFO_FLAGS flag2) |
| 194 | { |
| 195 | return (CORINFO_CALLINFO_FLAGS)(flag1 | flag2); |
| 196 | } |
| 197 | inline CORINFO_CALLINFO_FLAGS Compiler::addVerifyFlag(CORINFO_CALLINFO_FLAGS flags) |
| 198 | { |
| 199 | if (tiVerificationNeeded) |
| 200 | { |
| 201 | flags = combine(flags, CORINFO_CALLINFO_VERIFICATION); |
| 202 | } |
| 203 | return flags; |
| 204 | } |
| 205 | |