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.
9 #include "debugmacros.h"
13 extern PELoader *g_pPELoader;
15 unsigned SizeOfValueType(mdToken tk, IMDInternalImport* pImport)
17 unsigned ret = 0xFFFFFFFF;
18 if((TypeFromToken(tk)==mdtTypeDef)&&RidFromToken(tk)&&pImport)
22 if (FAILED(pImport->GetTypeDefProps(tk, &dwAttrs, &tkExtends)))
26 if(!(IsTdInterface(dwAttrs)||IsTdAbstract(dwAttrs)||IsTdImport(dwAttrs)))
35 if (FAILED(pImport->GetClassPackSize(tk,&ulPack))) ulPack = 0;
36 if (FAILED(pImport->GetClassTotalSize(tk,&ulSize))) ulSize = 0;
38 if (IsTdExplicitLayout(dwAttrs))
40 MD_CLASS_LAYOUT hLayout;
41 if (SUCCEEDED(pImport->GetClassLayoutInit(tk,&hLayout)))
44 while (SUCCEEDED(pImport->GetClassLayoutNext(&hLayout,&tkField,&ulOffset)) && RidFromToken(tkField))
46 if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
50 if (!(IsFdStatic(dwFieldAttrs)||IsFdLiteral(dwFieldAttrs)))
52 uFieldSize = SizeOfField(tkField,pImport);
53 if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
54 uFieldSize += ulOffset;
55 if (uFieldSize > ulInstFieldSize) ulInstFieldSize = uFieldSize;
62 HENUMInternal hEnumField;
63 unsigned cFieldsMax = 0;
64 if (SUCCEEDED(pImport->EnumInit(mdtFieldDef, tk, &hEnumField)))
66 if ((cFieldsMax = pImport->EnumGetCount(&hEnumField)) != 0)
68 while (pImport->EnumNext(&hEnumField, &tkField) && RidFromToken(tkField))
70 if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
74 if (!IsFdStatic(dwFieldAttrs) && !IsFdLiteral(dwFieldAttrs))
76 uFieldSize = SizeOfField(tkField,pImport);
77 if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
80 ULONG ulDelta = ulInstFieldSize % ulPack;
81 if (ulDelta != 0) ulInstFieldSize += ulPack - ulDelta;
83 ulInstFieldSize += uFieldSize;
87 pImport->EnumClose(&hEnumField);
90 ret = (ulInstFieldSize > ulSize) ? ulInstFieldSize : ulSize;
91 if(ret == 0) ret = 1; // zero-sized value types automatically get 1 byte
97 unsigned SizeOfField(mdToken tk, IMDInternalImport* pImport)
99 unsigned ret = 0xFFFFFFFF;
100 if((TypeFromToken(tk) == mdtFieldDef) && RidFromToken(tk) && pImport)
102 PCCOR_SIGNATURE pSig;
104 if (FAILED(pImport->GetSigOfFieldDef(tk, &cSig, &pSig)))
108 ret = SizeOfField(&pSig,cSig,pImport);
113 unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport)
115 unsigned ret = 0xFFFFFFFF;
116 if(ppSig && *ppSig && cSig && pImport)
118 unsigned callConv = CorSigUncompressData(*ppSig);
119 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
124 unsigned uElementNumber = 1;
125 PCCOR_SIGNATURE pSigStart = *ppSig;
126 PCCOR_SIGNATURE pSigEnd = *ppSig+cSig;
128 // Size of the pointer depends on bitness of the assembly
129 unsigned nSizeOfPointer = g_pPELoader->IsPE32() ? 4 : 8;
133 switch(typ = *(*ppSig)++) {
134 case ELEMENT_TYPE_VOID :
137 case ELEMENT_TYPE_I1 :
138 case ELEMENT_TYPE_U1 :
139 case ELEMENT_TYPE_BOOLEAN :
140 return uElementNumber;
142 case ELEMENT_TYPE_CHAR :
143 case ELEMENT_TYPE_I2 :
144 case ELEMENT_TYPE_U2 :
145 return (uElementNumber << 1);
147 case ELEMENT_TYPE_I4 :
148 case ELEMENT_TYPE_U4 :
149 case ELEMENT_TYPE_R4 :
150 return (uElementNumber << 2);
152 case ELEMENT_TYPE_I8 :
153 case ELEMENT_TYPE_U8 :
154 case ELEMENT_TYPE_R8 :
155 return (uElementNumber << 3);
157 case ELEMENT_TYPE_OBJECT :
158 case ELEMENT_TYPE_STRING :
159 case ELEMENT_TYPE_FNPTR :
160 case ELEMENT_TYPE_CLASS :
161 case ELEMENT_TYPE_PTR :
162 case ELEMENT_TYPE_BYREF :
163 //case ELEMENT_TYPE_VAR :
164 case ELEMENT_TYPE_U :
165 case ELEMENT_TYPE_I :
166 return (uElementNumber * nSizeOfPointer);
168 case ELEMENT_TYPE_TYPEDBYREF : // pair of ptrs
169 return (uElementNumber * nSizeOfPointer * 2);
171 case ELEMENT_TYPE_VALUETYPE :
172 *ppSig += CorSigUncompressToken(*ppSig, &tk);
173 ret = SizeOfValueType(tk,pImport);
174 if(ret != 0xFFFFFFFF) ret *= uElementNumber;
177 // Modifiers or depedant types
179 case ELEMENT_TYPE_ARRAY :
180 ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigStart), pImport);
181 if(ret != 0xFFFFFFFF)
183 unsigned rank = CorSigUncompressData(*ppSig);
184 if (rank == 0) ret = 0xFFFFFFFF;
187 int* lowerBounds = new (nothrow) int[2*rank];
188 int* sizes = &lowerBounds[rank];
189 memset(lowerBounds, 0, sizeof(int)*2*rank);
191 unsigned numSizes = CorSigUncompressData(*ppSig);
192 _ASSERTE(numSizes <= rank);
194 for(i =0; i < numSizes; i++)
195 sizes[i] = CorSigUncompressData(*ppSig);
197 unsigned numLowBounds = CorSigUncompressData(*ppSig);
198 _ASSERTE(numLowBounds <= rank);
199 for(i = 0; i < numLowBounds; i++)
200 *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]);
202 for(i = 0; i < numSizes; i++)
204 if (sizes[i]) uElementNumber *= sizes[i];
206 ret *= uElementNumber;
207 delete[] lowerBounds;
212 case ELEMENT_TYPE_CMOD_OPT :
213 case ELEMENT_TYPE_CMOD_REQD :
214 *ppSig += CorSigUncompressToken(*ppSig, &tk);
215 case ELEMENT_TYPE_PINNED :
216 case ELEMENT_TYPE_SZARRAY : // uElementNumber doesn't change
217 if(*ppSig < pSigEnd) Reiterate = TRUE;
221 case ELEMENT_TYPE_SENTINEL :
222 case ELEMENT_TYPE_END :
226 } // end if(CALLCONV_FIELD)
227 } // end if(signature && import)