Merge pull request #10808 from sdmaclea/PR-ARM64-enable-initblk-unroll
[platform/upstream/coreclr.git] / src / ildasm / dasm_sz.cpp
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 #include "ildasmpch.h"
6
7 #include <metadata.h>
8 #include <utilcode.h>
9 #include "debugmacros.h"
10 #include "dasm_sz.h"
11 #include "ceeload.h"
12
13 extern PELoader *g_pPELoader;
14
15 unsigned SizeOfValueType(mdToken tk, IMDInternalImport* pImport)
16 {
17     unsigned ret = 0xFFFFFFFF;
18     if((TypeFromToken(tk)==mdtTypeDef)&&RidFromToken(tk)&&pImport)
19     {
20         DWORD dwAttrs;
21         mdToken tkExtends;
22         if (FAILED(pImport->GetTypeDefProps(tk, &dwAttrs, &tkExtends)))
23         {
24             return ret;
25         }
26         if(!(IsTdInterface(dwAttrs)||IsTdAbstract(dwAttrs)||IsTdImport(dwAttrs)))
27         {
28             mdToken tkField;
29             DWORD dwFieldAttrs;
30             unsigned uFieldSize;
31             ULONG ulPack=0, 
32                   ulSize = 0, 
33                   ulInstFieldSize = 0;
34
35             if (FAILED(pImport->GetClassPackSize(tk,&ulPack))) ulPack = 0;
36             if (FAILED(pImport->GetClassTotalSize(tk,&ulSize))) ulSize = 0;
37
38             if (IsTdExplicitLayout(dwAttrs))
39             {
40                 MD_CLASS_LAYOUT hLayout;
41                 if (SUCCEEDED(pImport->GetClassLayoutInit(tk,&hLayout)))
42                 {
43                     ULONG ulOffset;
44                     while (SUCCEEDED(pImport->GetClassLayoutNext(&hLayout,&tkField,&ulOffset)) && RidFromToken(tkField))
45                     {
46                         if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
47                         {
48                             break;
49                         }
50                         if (!(IsFdStatic(dwFieldAttrs)||IsFdLiteral(dwFieldAttrs)))
51                         {
52                             uFieldSize = SizeOfField(tkField,pImport);
53                             if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
54                             uFieldSize += ulOffset;
55                             if (uFieldSize > ulInstFieldSize) ulInstFieldSize = uFieldSize;
56                         }
57                     }
58                 }
59             }
60             else 
61             {
62                 HENUMInternal hEnumField;
63                 unsigned      cFieldsMax = 0;
64                 if (SUCCEEDED(pImport->EnumInit(mdtFieldDef, tk, &hEnumField)))
65                 {
66                     if ((cFieldsMax = pImport->EnumGetCount(&hEnumField)) != 0)
67                     {
68                         while (pImport->EnumNext(&hEnumField, &tkField) && RidFromToken(tkField))
69                         {
70                             if (FAILED(pImport->GetFieldDefProps(tkField, &dwFieldAttrs)))
71                             {
72                                 break;
73                             }
74                             if (!IsFdStatic(dwFieldAttrs) && !IsFdLiteral(dwFieldAttrs))
75                             {
76                                 uFieldSize = SizeOfField(tkField,pImport);
77                                 if (uFieldSize == 0xFFFFFFFF) return uFieldSize;
78                                 if (ulPack > 1)
79                                 {
80                                     ULONG ulDelta = ulInstFieldSize % ulPack;
81                                     if (ulDelta != 0) ulInstFieldSize += ulPack - ulDelta;
82                                 }
83                                 ulInstFieldSize += uFieldSize;
84                             }
85                         }
86                     }
87                     pImport->EnumClose(&hEnumField);
88                 }
89             }
90             ret = (ulInstFieldSize > ulSize) ? ulInstFieldSize : ulSize;
91             if(ret == 0) ret = 1; // zero-sized value types automatically get 1 byte
92         }
93     }
94     return ret;
95 }
96
97 unsigned SizeOfField(mdToken tk, IMDInternalImport* pImport)
98 {
99     unsigned ret = 0xFFFFFFFF;
100     if((TypeFromToken(tk) == mdtFieldDef) && RidFromToken(tk) && pImport)
101     {
102         PCCOR_SIGNATURE pSig;
103         ULONG           cSig;
104         if (FAILED(pImport->GetSigOfFieldDef(tk, &cSig, &pSig)))
105         {
106             return ret;
107         }
108         ret = SizeOfField(&pSig,cSig,pImport);
109     }
110     return ret;
111 }
112
113 unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport)
114 {
115     unsigned ret = 0xFFFFFFFF;
116     if(ppSig && *ppSig && cSig && pImport)
117     {
118         unsigned callConv = CorSigUncompressData(*ppSig);  
119         if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
120         {
121             mdToken  tk;    
122             int typ;
123             BOOL Reiterate;
124             unsigned uElementNumber = 1;
125             PCCOR_SIGNATURE pSigStart = *ppSig;
126             PCCOR_SIGNATURE pSigEnd = *ppSig+cSig;
127
128             // Size of the pointer depends on bitness of the assembly
129             unsigned nSizeOfPointer = g_pPELoader->IsPE32() ? 4 : 8;
130
131             do {
132                 Reiterate = FALSE;
133                 switch(typ = *(*ppSig)++) {    
134                     case ELEMENT_TYPE_VOID          :   
135                         return 0;
136                         
137                     case ELEMENT_TYPE_I1            :   
138                     case ELEMENT_TYPE_U1            :   
139                     case ELEMENT_TYPE_BOOLEAN       :   
140                         return uElementNumber; 
141
142                     case ELEMENT_TYPE_CHAR          :   
143                     case ELEMENT_TYPE_I2            :   
144                     case ELEMENT_TYPE_U2            :   
145                         return (uElementNumber << 1); 
146
147                     case ELEMENT_TYPE_I4            :   
148                     case ELEMENT_TYPE_U4            :   
149                     case ELEMENT_TYPE_R4            :   
150                         return (uElementNumber << 2); 
151                         
152                     case ELEMENT_TYPE_I8            :   
153                     case ELEMENT_TYPE_U8            :   
154                     case ELEMENT_TYPE_R8            :   
155                         return (uElementNumber << 3); 
156                         
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); 
167                         
168                     case ELEMENT_TYPE_TYPEDBYREF        :   // pair of ptrs
169                         return (uElementNumber * nSizeOfPointer * 2); 
170
171                     case ELEMENT_TYPE_VALUETYPE    :
172                         *ppSig += CorSigUncompressToken(*ppSig, &tk); 
173                         ret = SizeOfValueType(tk,pImport);
174                         if(ret != 0xFFFFFFFF) ret *= uElementNumber;
175                         return ret;
176
177                         // Modifiers or depedant types  
178
179                     case ELEMENT_TYPE_ARRAY       :   
180                         ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigStart), pImport);
181                         if(ret != 0xFFFFFFFF)
182                         {
183                             unsigned rank = CorSigUncompressData(*ppSig);  
184                             if (rank == 0) ret = 0xFFFFFFFF;
185                             else 
186                             {
187                                 int* lowerBounds = new (nothrow) int[2*rank];
188                                 int* sizes       = &lowerBounds[rank];  
189                                 memset(lowerBounds, 0, sizeof(int)*2*rank); 
190                                 
191                                 unsigned numSizes = CorSigUncompressData(*ppSig);  
192                                 _ASSERTE(numSizes <= rank);
193                                 unsigned i;
194                                 for(i =0; i < numSizes; i++)
195                                     sizes[i] = CorSigUncompressData(*ppSig);   
196                                 
197                                 unsigned numLowBounds = CorSigUncompressData(*ppSig);  
198                                 _ASSERTE(numLowBounds <= rank); 
199                                 for(i = 0; i < numLowBounds; i++)   
200                                     *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]); 
201                                 
202                                 for(i = 0; i < numSizes; i++)   
203                                 {   
204                                     if (sizes[i]) uElementNumber *= sizes[i];
205                                 }   
206                                 ret *= uElementNumber;
207                                 delete[] lowerBounds;
208                             }
209                         }
210                         return ret;    
211
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;
218                         break;  
219
220                     default:    
221                     case ELEMENT_TYPE_SENTINEL      :   
222                     case ELEMENT_TYPE_END           :   
223                         break;  
224                 } // end switch
225             } while(Reiterate);
226         } // end if(CALLCONV_FIELD)
227     } // end if(signature && import)
228     return ret;
229 }