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