1//
2// Copyright (c) Microsoft. All rights reserved.
3// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4//
5
6//----------------------------------------------------------
7// SpmiRecordHelper.h - a helper to copy data between agnostic/non-agnostic types.
8//----------------------------------------------------------
9#ifndef _SpmiRecordsHelper
10#define _SpmiRecordsHelper
11
12#include "methodcontext.h"
13
14class SpmiRecordsHelper
15{
16public:
17 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKENin CreateAgnostic_CORINFO_RESOLVED_TOKENin(
18 CORINFO_RESOLVED_TOKEN* pResolvedToken);
19
20 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout CreateAgnostic_CORINFO_RESOLVED_TOKENout_without_buffers(
21 CORINFO_RESOLVED_TOKEN* pResolvedToken);
22
23 template <typename key, typename value>
24 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout StoreAgnostic_CORINFO_RESOLVED_TOKENout(
25 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers);
26
27 template <typename key, typename value>
28 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout RestoreAgnostic_CORINFO_RESOLVED_TOKENout(
29 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers);
30
31 template <typename key, typename value>
32 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN StoreAgnostic_CORINFO_RESOLVED_TOKEN(
33 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers);
34
35 template <typename key, typename value>
36 static MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN RestoreAgnostic_CORINFO_RESOLVED_TOKEN(
37 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers);
38
39 // Restore the out values in the first argument from the second.
40 // Can't just return whole CORINFO_RESOLVED_TOKEN because [in] values in it are important too.
41 template <typename key, typename value>
42 static void Restore_CORINFO_RESOLVED_TOKENout(CORINFO_RESOLVED_TOKEN* pResolvedToken,
43 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout& token,
44 LightWeightMap<key, value>* buffers);
45
46 static MethodContext::Agnostic_CORINFO_SIG_INFO CreateAgnostic_CORINFO_SIG_INFO_without_buffers(
47 CORINFO_SIG_INFO& sigInfo);
48
49 template <typename key, typename value>
50 static MethodContext::Agnostic_CORINFO_SIG_INFO StoreAgnostic_CORINFO_SIG_INFO(CORINFO_SIG_INFO& sigInfo,
51 LightWeightMap<key, value>* buffers);
52
53 template <typename key, typename value>
54 static MethodContext::Agnostic_CORINFO_SIG_INFO RestoreAgnostic_CORINFO_SIG_INFO(
55 CORINFO_SIG_INFO& sigInfo, LightWeightMap<key, value>* buffers);
56
57 template <typename key, typename value>
58 static CORINFO_SIG_INFO Restore_CORINFO_SIG_INFO(MethodContext::Agnostic_CORINFO_SIG_INFO& sigInfo,
59 LightWeightMap<key, value>* buffers);
60
61 static MethodContext::Agnostic_CORINFO_LOOKUP_KIND CreateAgnostic_CORINFO_LOOKUP_KIND(
62 const CORINFO_LOOKUP_KIND* pGenericLookupKind);
63
64 static CORINFO_LOOKUP_KIND RestoreCORINFO_LOOKUP_KIND(MethodContext::Agnostic_CORINFO_LOOKUP_KIND& lookupKind);
65
66 static MethodContext::Agnostic_CORINFO_CONST_LOOKUP StoreAgnostic_CORINFO_CONST_LOOKUP(
67 CORINFO_CONST_LOOKUP* pLookup);
68
69 static CORINFO_CONST_LOOKUP RestoreCORINFO_CONST_LOOKUP(MethodContext::Agnostic_CORINFO_CONST_LOOKUP& lookup);
70
71 static MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP StoreAgnostic_CORINFO_RUNTIME_LOOKUP(
72 CORINFO_RUNTIME_LOOKUP* pLookup);
73
74 static CORINFO_RUNTIME_LOOKUP RestoreCORINFO_RUNTIME_LOOKUP(MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP& Lookup);
75
76 static MethodContext::Agnostic_CORINFO_LOOKUP StoreAgnostic_CORINFO_LOOKUP(CORINFO_LOOKUP* pLookup);
77
78 static CORINFO_LOOKUP RestoreCORINFO_LOOKUP(MethodContext::Agnostic_CORINFO_LOOKUP& agnosticLookup);
79};
80
81inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKENin SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(
82 CORINFO_RESOLVED_TOKEN* pResolvedToken)
83{
84 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENin tokenIn;
85 ZeroMemory(&tokenIn, sizeof(tokenIn));
86 tokenIn.tokenContext = (DWORDLONG)pResolvedToken->tokenContext;
87 tokenIn.tokenScope = (DWORDLONG)pResolvedToken->tokenScope;
88 tokenIn.token = (DWORD)pResolvedToken->token;
89 tokenIn.tokenType = (DWORD)pResolvedToken->tokenType;
90 return tokenIn;
91}
92
93inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout SpmiRecordsHelper::
94 CreateAgnostic_CORINFO_RESOLVED_TOKENout_without_buffers(CORINFO_RESOLVED_TOKEN* pResolvedToken)
95{
96 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout tokenOut;
97 ZeroMemory(&tokenOut, sizeof(tokenOut));
98 tokenOut.hClass = (DWORDLONG)pResolvedToken->hClass;
99 tokenOut.hMethod = (DWORDLONG)pResolvedToken->hMethod;
100 tokenOut.hField = (DWORDLONG)pResolvedToken->hField;
101
102 tokenOut.cbTypeSpec = (DWORD)pResolvedToken->cbTypeSpec;
103 tokenOut.cbMethodSpec = (DWORD)pResolvedToken->cbMethodSpec;
104
105 tokenOut.pTypeSpec_Index = -1;
106 tokenOut.pMethodSpec_Index = -1;
107
108 return tokenOut;
109}
110
111template <typename key, typename value>
112inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKENout(
113 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers)
114{
115 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout tokenOut(
116 CreateAgnostic_CORINFO_RESOLVED_TOKENout_without_buffers(pResolvedToken));
117
118 tokenOut.pTypeSpec_Index =
119 (DWORD)buffers->AddBuffer((unsigned char*)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
120 tokenOut.pMethodSpec_Index =
121 (DWORD)buffers->AddBuffer((unsigned char*)pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
122
123 return tokenOut;
124}
125
126template <typename key, typename value>
127inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKENout(
128 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers)
129{
130 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout tokenOut(
131 CreateAgnostic_CORINFO_RESOLVED_TOKENout_without_buffers(pResolvedToken));
132 tokenOut.pTypeSpec_Index =
133 (DWORD)buffers->Contains((unsigned char*)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
134 tokenOut.pMethodSpec_Index =
135 (DWORD)buffers->Contains((unsigned char*)pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
136 return tokenOut;
137}
138
139template <typename key, typename value>
140inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(
141 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers)
142{
143 MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN token;
144 token.inValue = CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
145 token.outValue = StoreAgnostic_CORINFO_RESOLVED_TOKENout(pResolvedToken, buffers);
146 return token;
147}
148
149template <typename key, typename value>
150inline MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(
151 CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers)
152{
153 MethodContext::Agnostic_CORINFO_RESOLVED_TOKEN token;
154 ZeroMemory(&token, sizeof(token));
155 token.inValue = CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
156 token.outValue = RestoreAgnostic_CORINFO_RESOLVED_TOKENout(pResolvedToken, buffers);
157 return token;
158}
159
160template <typename key, typename value>
161inline void SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKENout(
162 CORINFO_RESOLVED_TOKEN* pResolvedToken,
163 MethodContext::Agnostic_CORINFO_RESOLVED_TOKENout& tokenOut,
164 LightWeightMap<key, value>* buffers)
165{
166 pResolvedToken->hClass = (CORINFO_CLASS_HANDLE)tokenOut.hClass;
167 pResolvedToken->hMethod = (CORINFO_METHOD_HANDLE)tokenOut.hMethod;
168 pResolvedToken->hField = (CORINFO_FIELD_HANDLE)tokenOut.hField;
169 pResolvedToken->pTypeSpec = (PCCOR_SIGNATURE)buffers->GetBuffer(tokenOut.pTypeSpec_Index);
170 pResolvedToken->cbTypeSpec = (ULONG)tokenOut.cbTypeSpec;
171 pResolvedToken->pMethodSpec = (PCCOR_SIGNATURE)buffers->GetBuffer(tokenOut.pMethodSpec_Index);
172 pResolvedToken->cbMethodSpec = (ULONG)tokenOut.cbMethodSpec;
173}
174
175inline MethodContext::Agnostic_CORINFO_SIG_INFO SpmiRecordsHelper::CreateAgnostic_CORINFO_SIG_INFO_without_buffers(
176 CORINFO_SIG_INFO& sigInfo)
177{
178 MethodContext::Agnostic_CORINFO_SIG_INFO sig;
179 ZeroMemory(&sig, sizeof(sig));
180 sig.callConv = (DWORD)sigInfo.callConv;
181 sig.retTypeClass = (DWORDLONG)sigInfo.retTypeClass;
182 sig.retTypeSigClass = (DWORDLONG)sigInfo.retTypeSigClass;
183 sig.retType = (DWORD)sigInfo.retType;
184 sig.flags = (DWORD)sigInfo.flags;
185 sig.numArgs = (DWORD)sigInfo.numArgs;
186 sig.sigInst_classInstCount = (DWORD)sigInfo.sigInst.classInstCount;
187 sig.sigInst_methInstCount = (DWORD)sigInfo.sigInst.methInstCount;
188 sig.args = (DWORDLONG)sigInfo.args;
189 sig.cbSig = (DWORD)sigInfo.cbSig;
190 sig.scope = (DWORDLONG)sigInfo.scope;
191 sig.token = (DWORD)sigInfo.token;
192 return sig;
193}
194
195template <typename key, typename value>
196inline MethodContext::Agnostic_CORINFO_SIG_INFO SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(
197 CORINFO_SIG_INFO& sigInfo, LightWeightMap<key, value>* buffers)
198{
199 MethodContext::Agnostic_CORINFO_SIG_INFO sig(CreateAgnostic_CORINFO_SIG_INFO_without_buffers(sigInfo));
200 sig.sigInst_classInst_Index =
201 buffers->AddBuffer((unsigned char*)sigInfo.sigInst.classInst, sigInfo.sigInst.classInstCount * 8);
202 sig.sigInst_methInst_Index =
203 buffers->AddBuffer((unsigned char*)sigInfo.sigInst.methInst, sigInfo.sigInst.methInstCount * 8);
204 sig.pSig_Index = (DWORD)buffers->AddBuffer((unsigned char*)sigInfo.pSig, sigInfo.cbSig);
205 return sig;
206}
207
208template <typename key, typename value>
209inline MethodContext::Agnostic_CORINFO_SIG_INFO SpmiRecordsHelper::RestoreAgnostic_CORINFO_SIG_INFO(
210 CORINFO_SIG_INFO& sigInfo, LightWeightMap<key, value>* buffers)
211{
212 MethodContext::Agnostic_CORINFO_SIG_INFO sig(CreateAgnostic_CORINFO_SIG_INFO_without_buffers(sigInfo));
213 sig.sigInst_classInst_Index =
214 buffers->Contains((unsigned char*)sigInfo.sigInst.classInst, sigInfo.sigInst.classInstCount * 8);
215 sig.sigInst_methInst_Index =
216 buffers->Contains((unsigned char*)sigInfo.sigInst.methInst, sigInfo.sigInst.methInstCount * 8);
217 sig.pSig_Index = (DWORD)buffers->Contains((unsigned char*)sigInfo.pSig, sigInfo.cbSig);
218 return sig;
219}
220
221template <typename key, typename value>
222inline CORINFO_SIG_INFO SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(MethodContext::Agnostic_CORINFO_SIG_INFO& sigInfo,
223 LightWeightMap<key, value>* buffers)
224{
225 CORINFO_SIG_INFO sig;
226 sig.callConv = (CorInfoCallConv)sigInfo.callConv;
227 sig.retTypeClass = (CORINFO_CLASS_HANDLE)sigInfo.retTypeClass;
228 sig.retTypeSigClass = (CORINFO_CLASS_HANDLE)sigInfo.retTypeSigClass;
229 sig.retType = (CorInfoType)sigInfo.retType;
230 sig.flags = (unsigned)sigInfo.flags;
231 sig.numArgs = (unsigned)sigInfo.numArgs;
232 sig.sigInst.classInstCount = (unsigned)sigInfo.sigInst_classInstCount;
233 sig.sigInst.classInst = (CORINFO_CLASS_HANDLE*)buffers->GetBuffer(sigInfo.sigInst_classInst_Index);
234 sig.sigInst.methInstCount = (unsigned)sigInfo.sigInst_methInstCount;
235 sig.sigInst.methInst = (CORINFO_CLASS_HANDLE*)buffers->GetBuffer(sigInfo.sigInst_methInst_Index);
236 sig.args = (CORINFO_ARG_LIST_HANDLE)sigInfo.args;
237 sig.cbSig = (unsigned int)sigInfo.cbSig;
238 sig.pSig = (PCCOR_SIGNATURE)buffers->GetBuffer(sigInfo.pSig_Index);
239 sig.scope = (CORINFO_MODULE_HANDLE)sigInfo.scope;
240 sig.token = (mdToken)sigInfo.token;
241 return sig;
242}
243
244inline MethodContext::Agnostic_CORINFO_LOOKUP_KIND SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(
245 const CORINFO_LOOKUP_KIND* pGenericLookupKind)
246{
247 MethodContext::Agnostic_CORINFO_LOOKUP_KIND genericLookupKind;
248 ZeroMemory(&genericLookupKind, sizeof(genericLookupKind));
249 if (pGenericLookupKind != nullptr)
250 {
251 genericLookupKind.needsRuntimeLookup = (DWORD)pGenericLookupKind->needsRuntimeLookup;
252 genericLookupKind.runtimeLookupKind = (DWORD)pGenericLookupKind->runtimeLookupKind;
253 genericLookupKind.runtimeLookupFlags = pGenericLookupKind->runtimeLookupFlags;
254 }
255 // We don't store result->runtimeLookupArgs, which is opaque data. Ok?
256 return genericLookupKind;
257}
258
259inline CORINFO_LOOKUP_KIND SpmiRecordsHelper::RestoreCORINFO_LOOKUP_KIND(
260 MethodContext::Agnostic_CORINFO_LOOKUP_KIND& lookupKind)
261{
262 CORINFO_LOOKUP_KIND genericLookupKind;
263 genericLookupKind.needsRuntimeLookup = lookupKind.needsRuntimeLookup != 0;
264 genericLookupKind.runtimeLookupKind = (CORINFO_RUNTIME_LOOKUP_KIND)lookupKind.runtimeLookupKind;
265 genericLookupKind.runtimeLookupFlags = lookupKind.runtimeLookupFlags;
266 genericLookupKind.runtimeLookupArgs = nullptr; // We don't store this opaque data. Ok?
267 return genericLookupKind;
268}
269
270inline MethodContext::Agnostic_CORINFO_CONST_LOOKUP SpmiRecordsHelper::StoreAgnostic_CORINFO_CONST_LOOKUP(
271 CORINFO_CONST_LOOKUP* pLookup)
272{
273 MethodContext::Agnostic_CORINFO_CONST_LOOKUP constLookup;
274 ZeroMemory(&constLookup, sizeof(constLookup));
275 constLookup.accessType = (DWORD)pLookup->accessType;
276 constLookup.handle = (DWORDLONG)pLookup->handle;
277 return constLookup;
278}
279
280inline CORINFO_CONST_LOOKUP SpmiRecordsHelper::RestoreCORINFO_CONST_LOOKUP(
281 MethodContext::Agnostic_CORINFO_CONST_LOOKUP& lookup)
282{
283 CORINFO_CONST_LOOKUP constLookup;
284 constLookup.accessType = (InfoAccessType)lookup.accessType;
285 constLookup.handle = (CORINFO_GENERIC_HANDLE)lookup.handle;
286 return constLookup;
287}
288
289inline MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP SpmiRecordsHelper::StoreAgnostic_CORINFO_RUNTIME_LOOKUP(
290 CORINFO_RUNTIME_LOOKUP* pLookup)
291{
292 MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP runtimeLookup;
293 ZeroMemory(&runtimeLookup, sizeof(runtimeLookup));
294 runtimeLookup.signature = (DWORDLONG)pLookup->signature;
295 runtimeLookup.helper = (DWORD)pLookup->helper;
296 runtimeLookup.indirections = (DWORD)pLookup->indirections;
297 runtimeLookup.testForNull = (DWORD)pLookup->testForNull;
298 runtimeLookup.testForFixup = (DWORD)pLookup->testForFixup;
299 runtimeLookup.indirectFirstOffset = (DWORD)pLookup->indirectFirstOffset;
300 runtimeLookup.indirectSecondOffset = (DWORD)pLookup->indirectSecondOffset;
301 for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++)
302 runtimeLookup.offsets[i] = (DWORDLONG)pLookup->offsets[i];
303 return runtimeLookup;
304}
305
306inline CORINFO_RUNTIME_LOOKUP SpmiRecordsHelper::RestoreCORINFO_RUNTIME_LOOKUP(
307 MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP& lookup)
308{
309 CORINFO_RUNTIME_LOOKUP runtimeLookup;
310 runtimeLookup.signature = (LPVOID)lookup.signature;
311 runtimeLookup.helper = (CorInfoHelpFunc)lookup.helper;
312 runtimeLookup.indirections = (WORD)lookup.indirections;
313 runtimeLookup.testForNull = lookup.testForNull != 0;
314 runtimeLookup.testForFixup = lookup.testForFixup != 0;
315 runtimeLookup.indirectFirstOffset = lookup.indirectFirstOffset != 0;
316 runtimeLookup.indirectSecondOffset = lookup.indirectSecondOffset != 0;
317 for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++)
318 runtimeLookup.offsets[i] = (size_t)lookup.offsets[i];
319 return CORINFO_RUNTIME_LOOKUP();
320}
321
322inline MethodContext::Agnostic_CORINFO_LOOKUP SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(CORINFO_LOOKUP* pLookup)
323{
324 MethodContext::Agnostic_CORINFO_LOOKUP lookup;
325 ZeroMemory(&lookup, sizeof(lookup));
326 lookup.lookupKind = CreateAgnostic_CORINFO_LOOKUP_KIND(&pLookup->lookupKind);
327 if (pLookup->lookupKind.needsRuntimeLookup)
328 {
329 lookup.runtimeLookup = StoreAgnostic_CORINFO_RUNTIME_LOOKUP(&pLookup->runtimeLookup);
330 }
331 else
332 {
333 lookup.constLookup = StoreAgnostic_CORINFO_CONST_LOOKUP(&pLookup->constLookup);
334 }
335 return lookup;
336}
337
338inline CORINFO_LOOKUP SpmiRecordsHelper::RestoreCORINFO_LOOKUP(MethodContext::Agnostic_CORINFO_LOOKUP& agnosticLookup)
339{
340 CORINFO_LOOKUP lookup;
341 ZeroMemory(&lookup, sizeof(lookup));
342 lookup.lookupKind = RestoreCORINFO_LOOKUP_KIND(agnosticLookup.lookupKind);
343 if (lookup.lookupKind.needsRuntimeLookup)
344 {
345 lookup.runtimeLookup = RestoreCORINFO_RUNTIME_LOOKUP(agnosticLookup.runtimeLookup);
346 }
347 else
348 {
349 lookup.constLookup = RestoreCORINFO_CONST_LOOKUP(agnosticLookup.constLookup);
350 }
351 return lookup;
352}
353
354#endif
355