1*9c15e1abSPedro Giffuni /*
2*9c15e1abSPedro Giffuni * Licensed to the Apache Software Foundation (ASF) under one
3*9c15e1abSPedro Giffuni * or more contributor license agreements. See the NOTICE file
4*9c15e1abSPedro Giffuni * distributed with this work for additional information
5*9c15e1abSPedro Giffuni * regarding copyright ownership. The ASF licenses this file
6*9c15e1abSPedro Giffuni * to you under the Apache License, Version 2.0 (the
7*9c15e1abSPedro Giffuni * "License"); you may not use this file except in compliance
8*9c15e1abSPedro Giffuni * with the License. You may obtain a copy of the License at
9*9c15e1abSPedro Giffuni *
10*9c15e1abSPedro Giffuni * http://www.apache.org/licenses/LICENSE-2.0
11*9c15e1abSPedro Giffuni *
12*9c15e1abSPedro Giffuni * Unless required by applicable law or agreed to in writing,
13*9c15e1abSPedro Giffuni * software distributed under the License is distributed on an
14*9c15e1abSPedro Giffuni * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*9c15e1abSPedro Giffuni * KIND, either express or implied. See the License for the
16*9c15e1abSPedro Giffuni * specific language governing permissions and limitations
17*9c15e1abSPedro Giffuni * under the License.
18*9c15e1abSPedro Giffuni */
19*9c15e1abSPedro Giffuni
20*9c15e1abSPedro Giffuni
21*9c15e1abSPedro Giffuni // MARKER(update_precomp.py): autogen include statement, do not remove
22*9c15e1abSPedro Giffuni #include "precompiled_bridges.hxx"
23*9c15e1abSPedro Giffuni
24*9c15e1abSPedro Giffuni // This is an implementation of the parameter-classification rules of the
25*9c15e1abSPedro Giffuni // AArch64 procedure call standard ("Procedure Call Standard for the Arm 64-bit
26*9c15e1abSPedro Giffuni // Architecture", ARM IHI 0055).
27*9c15e1abSPedro Giffuni //
28*9c15e1abSPedro Giffuni // Unlike the System V AMD64 ABI (used by the x86-64 bridge), AAPCS64 does not
29*9c15e1abSPedro Giffuni // split aggregates into per-eightbyte INTEGER/SSE classes. Instead:
30*9c15e1abSPedro Giffuni // * scalars go in one GPR (x) or one FP/SIMD (v) register;
31*9c15e1abSPedro Giffuni // * a Homogeneous Floating-point Aggregate (HFA: <= 4 members, all the same
32*9c15e1abSPedro Giffuni // FP type, recursively) goes in consecutive v registers;
33*9c15e1abSPedro Giffuni // * any other aggregate <= 16 bytes goes in 1-2 GPRs;
34*9c15e1abSPedro Giffuni // * a non-HFA aggregate > 16 bytes is passed indirectly (a pointer to a
35*9c15e1abSPedro Giffuni // caller-allocated copy).
36*9c15e1abSPedro Giffuni // Register fill is "all or nothing": if an aggregate does not fit entirely in
37*9c15e1abSPedro Giffuni // the remaining registers of its bank, it is passed wholly on the stack.
38*9c15e1abSPedro Giffuni //
39*9c15e1abSPedro Giffuni // This is a clean-room implementation from the public specifications; see
40*9c15e1abSPedro Giffuni // ../../../../AAPCS64_BRIDGE_SPEC.md.
41*9c15e1abSPedro Giffuni
42*9c15e1abSPedro Giffuni #include "abi.hxx"
43*9c15e1abSPedro Giffuni
44*9c15e1abSPedro Giffuni #include "bridges/cpp_uno/shared/types.hxx"
45*9c15e1abSPedro Giffuni
46*9c15e1abSPedro Giffuni #include <rtl/ustring.hxx>
47*9c15e1abSPedro Giffuni #include <string.h>
48*9c15e1abSPedro Giffuni
49*9c15e1abSPedro Giffuni using namespace aarch64;
50*9c15e1abSPedro Giffuni
51*9c15e1abSPedro Giffuni namespace {
52*9c15e1abSPedro Giffuni
53*9c15e1abSPedro Giffuni // The element type of a Homogeneous Floating-point Aggregate.
54*9c15e1abSPedro Giffuni enum HfaKind
55*9c15e1abSPedro Giffuni {
56*9c15e1abSPedro Giffuni HFA_NONE, // not (yet) an HFA
57*9c15e1abSPedro Giffuni HFA_FLOAT, // all members are FLOAT (4-byte)
58*9c15e1abSPedro Giffuni HFA_DOUBLE // all members are DOUBLE (8-byte)
59*9c15e1abSPedro Giffuni };
60*9c15e1abSPedro Giffuni
61*9c15e1abSPedro Giffuni // Combine the running HFA kind with a newly-seen member kind. Two members
62*9c15e1abSPedro Giffuni // of different FP types, or any non-FP member, break the homogeneity.
mergeHfa(HfaKind running,HfaKind seen)63*9c15e1abSPedro Giffuni HfaKind mergeHfa( HfaKind running, HfaKind seen )
64*9c15e1abSPedro Giffuni {
65*9c15e1abSPedro Giffuni if ( seen == HFA_NONE )
66*9c15e1abSPedro Giffuni return HFA_NONE;
67*9c15e1abSPedro Giffuni if ( running == HFA_NONE )
68*9c15e1abSPedro Giffuni return seen;
69*9c15e1abSPedro Giffuni return ( running == seen ) ? running : HFA_NONE;
70*9c15e1abSPedro Giffuni }
71*9c15e1abSPedro Giffuni
isComplexAggregate(typelib_TypeDescriptionReference * pTypeRef)72*9c15e1abSPedro Giffuni bool isComplexAggregate( typelib_TypeDescriptionReference *pTypeRef )
73*9c15e1abSPedro Giffuni {
74*9c15e1abSPedro Giffuni typelib_TypeDescription * pTypeDescr = 0;
75*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
76*9c15e1abSPedro Giffuni const typelib_CompoundTypeDescription *pComp =
77*9c15e1abSPedro Giffuni reinterpret_cast<const typelib_CompoundTypeDescription *>( pTypeDescr );
78*9c15e1abSPedro Giffuni bool complex = pComp->pBaseTypeDescription != 0 &&
79*9c15e1abSPedro Giffuni isComplexAggregate( pComp->pBaseTypeDescription->aBase.pWeakRef );
80*9c15e1abSPedro Giffuni for ( sal_Int32 i = 0; !complex && i < pComp->nMembers; ++i )
81*9c15e1abSPedro Giffuni {
82*9c15e1abSPedro Giffuni typelib_TypeClass typeClass = pComp->ppTypeRefs[i]->eTypeClass;
83*9c15e1abSPedro Giffuni if ( typeClass == typelib_TypeClass_STRUCT ||
84*9c15e1abSPedro Giffuni typeClass == typelib_TypeClass_EXCEPTION )
85*9c15e1abSPedro Giffuni complex = isComplexAggregate( pComp->ppTypeRefs[i] );
86*9c15e1abSPedro Giffuni else
87*9c15e1abSPedro Giffuni complex = !bridges::cpp_uno::shared::isSimpleType( typeClass );
88*9c15e1abSPedro Giffuni }
89*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
90*9c15e1abSPedro Giffuni return complex;
91*9c15e1abSPedro Giffuni }
92*9c15e1abSPedro Giffuni
93*9c15e1abSPedro Giffuni // Recursively determine whether pTypeRef is (part of) a homogeneous
94*9c15e1abSPedro Giffuni // floating-point aggregate, accumulating the element kind and member count.
95*9c15e1abSPedro Giffuni //
96*9c15e1abSPedro Giffuni // Returns false the moment homogeneity is violated (a non-FP scalar, or a
97*9c15e1abSPedro Giffuni // second distinct FP type, or > 4 elements). A FLOAT/DOUBLE scalar counts as
98*9c15e1abSPedro Giffuni // a 1-element HFA of itself; a struct flattens its members (and base classes).
collectHfa(typelib_TypeDescriptionReference * pTypeRef,HfaKind & rKind,int & rCount)99*9c15e1abSPedro Giffuni bool collectHfa( typelib_TypeDescriptionReference *pTypeRef, HfaKind &rKind, int &rCount )
100*9c15e1abSPedro Giffuni {
101*9c15e1abSPedro Giffuni switch ( pTypeRef->eTypeClass )
102*9c15e1abSPedro Giffuni {
103*9c15e1abSPedro Giffuni case typelib_TypeClass_FLOAT:
104*9c15e1abSPedro Giffuni rKind = mergeHfa( rKind, HFA_FLOAT );
105*9c15e1abSPedro Giffuni if ( rKind == HFA_NONE ) return false;
106*9c15e1abSPedro Giffuni return ( ++rCount <= 4 );
107*9c15e1abSPedro Giffuni
108*9c15e1abSPedro Giffuni case typelib_TypeClass_DOUBLE:
109*9c15e1abSPedro Giffuni rKind = mergeHfa( rKind, HFA_DOUBLE );
110*9c15e1abSPedro Giffuni if ( rKind == HFA_NONE ) return false;
111*9c15e1abSPedro Giffuni return ( ++rCount <= 4 );
112*9c15e1abSPedro Giffuni
113*9c15e1abSPedro Giffuni case typelib_TypeClass_STRUCT:
114*9c15e1abSPedro Giffuni case typelib_TypeClass_EXCEPTION:
115*9c15e1abSPedro Giffuni {
116*9c15e1abSPedro Giffuni typelib_TypeDescription * pTypeDescr = 0;
117*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
118*9c15e1abSPedro Giffuni
119*9c15e1abSPedro Giffuni const typelib_CompoundTypeDescription *pComp =
120*9c15e1abSPedro Giffuni reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr );
121*9c15e1abSPedro Giffuni
122*9c15e1abSPedro Giffuni // rCount is cumulative over the whole recursion, so remember where
123*9c15e1abSPedro Giffuni // this aggregate started in order to size-check it below.
124*9c15e1abSPedro Giffuni const int nCountAtEntry = rCount;
125*9c15e1abSPedro Giffuni bool bOk = true;
126*9c15e1abSPedro Giffuni
127*9c15e1abSPedro Giffuni // Flatten base class first (its members precede ours in layout).
128*9c15e1abSPedro Giffuni if ( pComp->pBaseTypeDescription )
129*9c15e1abSPedro Giffuni {
130*9c15e1abSPedro Giffuni bOk = collectHfa(
131*9c15e1abSPedro Giffuni pComp->pBaseTypeDescription->aBase.pWeakRef, rKind, rCount );
132*9c15e1abSPedro Giffuni }
133*9c15e1abSPedro Giffuni
134*9c15e1abSPedro Giffuni for ( sal_Int32 i = 0; bOk && i < pComp->nMembers; ++i )
135*9c15e1abSPedro Giffuni bOk = collectHfa( pComp->ppTypeRefs[i], rKind, rCount );
136*9c15e1abSPedro Giffuni
137*9c15e1abSPedro Giffuni if ( bOk )
138*9c15e1abSPedro Giffuni {
139*9c15e1abSPedro Giffuni // Reject anything the elements do not tile exactly: only the
140*9c15e1abSPedro Giffuni // elements contributed by THIS aggregate count towards its size.
141*9c15e1abSPedro Giffuni sal_Int32 elementSize = rKind == HFA_FLOAT ? 4 : 8;
142*9c15e1abSPedro Giffuni bOk = pTypeDescr->nSize ==
143*9c15e1abSPedro Giffuni ( rCount - nCountAtEntry ) * elementSize;
144*9c15e1abSPedro Giffuni for ( sal_Int32 i = 0; bOk && i < pComp->nMembers; ++i )
145*9c15e1abSPedro Giffuni bOk = pComp->pMemberOffsets[i] % elementSize == 0;
146*9c15e1abSPedro Giffuni }
147*9c15e1abSPedro Giffuni
148*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
149*9c15e1abSPedro Giffuni return bOk;
150*9c15e1abSPedro Giffuni }
151*9c15e1abSPedro Giffuni
152*9c15e1abSPedro Giffuni default:
153*9c15e1abSPedro Giffuni // Any non-FP, non-aggregate member breaks homogeneity.
154*9c15e1abSPedro Giffuni rKind = HFA_NONE;
155*9c15e1abSPedro Giffuni return false;
156*9c15e1abSPedro Giffuni }
157*9c15e1abSPedro Giffuni }
158*9c15e1abSPedro Giffuni
159*9c15e1abSPedro Giffuni // Classify an aggregate (STRUCT/EXCEPTION). Sets the GPR/FPR counts and
160*9c15e1abSPedro Giffuni // returns true if it is passed in registers, false if it must be passed
161*9c15e1abSPedro Giffuni // indirectly (in memory).
classifyAggregate(typelib_TypeDescriptionReference * pTypeRef,int & nUsedGPR,int & nUsedFPR)162*9c15e1abSPedro Giffuni bool classifyAggregate( typelib_TypeDescriptionReference *pTypeRef, int &nUsedGPR, int &nUsedFPR )
163*9c15e1abSPedro Giffuni {
164*9c15e1abSPedro Giffuni // First, the HFA test.
165*9c15e1abSPedro Giffuni HfaKind kind = HFA_NONE;
166*9c15e1abSPedro Giffuni int count = 0;
167*9c15e1abSPedro Giffuni if ( collectHfa( pTypeRef, kind, count ) && kind != HFA_NONE )
168*9c15e1abSPedro Giffuni {
169*9c15e1abSPedro Giffuni nUsedFPR = count;
170*9c15e1abSPedro Giffuni nUsedGPR = 0;
171*9c15e1abSPedro Giffuni return true; // HFA passed in consecutive FP regs
172*9c15e1abSPedro Giffuni }
173*9c15e1abSPedro Giffuni
174*9c15e1abSPedro Giffuni // Not HFA: if bigger than 16 bytes, pass indirectly.
175*9c15e1abSPedro Giffuni typelib_TypeDescription * pTypeDescr = 0;
176*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
177*9c15e1abSPedro Giffuni if ( pTypeDescr->nSize > 16 )
178*9c15e1abSPedro Giffuni {
179*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
180*9c15e1abSPedro Giffuni nUsedGPR = nUsedFPR = 0;
181*9c15e1abSPedro Giffuni return false; // indirect
182*9c15e1abSPedro Giffuni }
183*9c15e1abSPedro Giffuni
184*9c15e1abSPedro Giffuni // small aggregate: it occupies 1 or 2 GPRs depending on size
185*9c15e1abSPedro Giffuni nUsedFPR = 0;
186*9c15e1abSPedro Giffuni nUsedGPR = ( pTypeDescr->nSize + 7 ) / 8;
187*9c15e1abSPedro Giffuni if ( nUsedGPR < 1 ) nUsedGPR = 1;
188*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
189*9c15e1abSPedro Giffuni return true;
190*9c15e1abSPedro Giffuni }
191*9c15e1abSPedro Giffuni
192*9c15e1abSPedro Giffuni } // anonymous namespace
193*9c15e1abSPedro Giffuni
194*9c15e1abSPedro Giffuni // Public API implementations.
195*9c15e1abSPedro Giffuni namespace aarch64
196*9c15e1abSPedro Giffuni {
197*9c15e1abSPedro Giffuni
examine_argument(typelib_TypeDescriptionReference * pTypeRef,bool bInReturn,int & nUsedGPR,int & nUsedFPR)198*9c15e1abSPedro Giffuni bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedFPR )
199*9c15e1abSPedro Giffuni {
200*9c15e1abSPedro Giffuni // For returns, the hidden param rule uses >16 bytes for aggregates.
201*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
202*9c15e1abSPedro Giffuni {
203*9c15e1abSPedro Giffuni return classifyAggregate( pTypeRef, nUsedGPR, nUsedFPR );
204*9c15e1abSPedro Giffuni }
205*9c15e1abSPedro Giffuni
206*9c15e1abSPedro Giffuni // Scalars: floats -> FPR, others -> GPR
207*9c15e1abSPedro Giffuni switch ( pTypeRef->eTypeClass )
208*9c15e1abSPedro Giffuni {
209*9c15e1abSPedro Giffuni case typelib_TypeClass_FLOAT:
210*9c15e1abSPedro Giffuni nUsedFPR = 1; nUsedGPR = 0; return true;
211*9c15e1abSPedro Giffuni case typelib_TypeClass_DOUBLE:
212*9c15e1abSPedro Giffuni nUsedFPR = 1; nUsedGPR = 0; return true;
213*9c15e1abSPedro Giffuni default:
214*9c15e1abSPedro Giffuni nUsedFPR = 0; nUsedGPR = 1; return true;
215*9c15e1abSPedro Giffuni }
216*9c15e1abSPedro Giffuni }
217*9c15e1abSPedro Giffuni
return_in_hidden_param(typelib_TypeDescriptionReference * pTypeRef)218*9c15e1abSPedro Giffuni bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
219*9c15e1abSPedro Giffuni {
220*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
221*9c15e1abSPedro Giffuni {
222*9c15e1abSPedro Giffuni typelib_TypeDescription * pTypeDescr = 0;
223*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
224*9c15e1abSPedro Giffuni bool ret = pTypeDescr->nSize > 16;
225*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
226*9c15e1abSPedro Giffuni return ret;
227*9c15e1abSPedro Giffuni }
228*9c15e1abSPedro Giffuni return false; // scalars and small aggregates return in registers
229*9c15e1abSPedro Giffuni }
230*9c15e1abSPedro Giffuni
get_return_kind(typelib_TypeDescriptionReference * pTypeRef)231*9c15e1abSPedro Giffuni sal_uInt32 get_return_kind( typelib_TypeDescriptionReference *pTypeRef )
232*9c15e1abSPedro Giffuni {
233*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_FLOAT )
234*9c15e1abSPedro Giffuni return typelib_TypeClass_FLOAT;
235*9c15e1abSPedro Giffuni
236*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_DOUBLE )
237*9c15e1abSPedro Giffuni return typelib_TypeClass_DOUBLE;
238*9c15e1abSPedro Giffuni
239*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT ||
240*9c15e1abSPedro Giffuni pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
241*9c15e1abSPedro Giffuni {
242*9c15e1abSPedro Giffuni HfaKind kind = HFA_NONE;
243*9c15e1abSPedro Giffuni int count = 0;
244*9c15e1abSPedro Giffuni
245*9c15e1abSPedro Giffuni if ( collectHfa( pTypeRef, kind, count ) )
246*9c15e1abSPedro Giffuni {
247*9c15e1abSPedro Giffuni if ( kind == HFA_FLOAT )
248*9c15e1abSPedro Giffuni return RETURN_KIND_HFA_FLOAT;
249*9c15e1abSPedro Giffuni
250*9c15e1abSPedro Giffuni if ( kind == HFA_DOUBLE )
251*9c15e1abSPedro Giffuni return RETURN_KIND_HFA_DOUBLE;
252*9c15e1abSPedro Giffuni }
253*9c15e1abSPedro Giffuni }
254*9c15e1abSPedro Giffuni
255*9c15e1abSPedro Giffuni return pTypeRef->eTypeClass;
256*9c15e1abSPedro Giffuni }
257*9c15e1abSPedro Giffuni
fill_struct(typelib_TypeDescriptionReference * pTypeRef,const sal_uInt64 * pGPR,const double * pFPR,void * pStruct)258*9c15e1abSPedro Giffuni void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* pGPR, const double* pFPR, void *pStruct )
259*9c15e1abSPedro Giffuni {
260*9c15e1abSPedro Giffuni // For small aggregates, copy from GPR slots; for HFAs, copy from FPR slots.
261*9c15e1abSPedro Giffuni if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
262*9c15e1abSPedro Giffuni {
263*9c15e1abSPedro Giffuni int nGPR=0, nFPR=0;
264*9c15e1abSPedro Giffuni if ( classifyAggregate( pTypeRef, nGPR, nFPR ) )
265*9c15e1abSPedro Giffuni {
266*9c15e1abSPedro Giffuni if ( nFPR > 0 )
267*9c15e1abSPedro Giffuni {
268*9c15e1abSPedro Giffuni // HFA: copy elements from FPR slots. For FLOAT HFAs each element is
269*9c15e1abSPedro Giffuni // 4 bytes but occupies an 8-byte saved slot; copy each float from the
270*9c15e1abSPedro Giffuni // low 4 bytes of the corresponding double-sized slot. DOUBLE HFAs
271*9c15e1abSPedro Giffuni // can be copied directly.
272*9c15e1abSPedro Giffuni HfaKind kind = HFA_NONE;
273*9c15e1abSPedro Giffuni int count = 0;
274*9c15e1abSPedro Giffuni if ( collectHfa( pTypeRef, kind, count ) && kind == HFA_FLOAT )
275*9c15e1abSPedro Giffuni {
276*9c15e1abSPedro Giffuni for ( int i = 0; i < nFPR; ++i )
277*9c15e1abSPedro Giffuni memcpy(
278*9c15e1abSPedro Giffuni static_cast<char *>( pStruct ) + i * sizeof(float),
279*9c15e1abSPedro Giffuni reinterpret_cast<const char *>( pFPR) + i * sizeof(double),
280*9c15e1abSPedro Giffuni sizeof(float) );
281*9c15e1abSPedro Giffuni }
282*9c15e1abSPedro Giffuni else
283*9c15e1abSPedro Giffuni {
284*9c15e1abSPedro Giffuni memcpy( pStruct, pFPR, nFPR * sizeof(double) );
285*9c15e1abSPedro Giffuni }
286*9c15e1abSPedro Giffuni }
287*9c15e1abSPedro Giffuni else
288*9c15e1abSPedro Giffuni {
289*9c15e1abSPedro Giffuni memcpy( pStruct, pGPR, nGPR * sizeof(sal_uInt64) );
290*9c15e1abSPedro Giffuni }
291*9c15e1abSPedro Giffuni }
292*9c15e1abSPedro Giffuni }
293*9c15e1abSPedro Giffuni }
294*9c15e1abSPedro Giffuni
align_stack_offset(sal_uInt32 offset,typelib_TypeDescriptionReference * pTypeRef)295*9c15e1abSPedro Giffuni sal_uInt32 align_stack_offset( sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef )
296*9c15e1abSPedro Giffuni {
297*9c15e1abSPedro Giffuni // AArch64 stack overflow area is packed; align to natural alignment of the type (8)
298*9c15e1abSPedro Giffuni const sal_uInt32 align = 8;
299*9c15e1abSPedro Giffuni return ( offset + align - 1 ) & ~( align - 1 );
300*9c15e1abSPedro Giffuni }
301*9c15e1abSPedro Giffuni
stack_size(typelib_TypeDescriptionReference * pTypeRef)302*9c15e1abSPedro Giffuni sal_uInt32 stack_size( typelib_TypeDescriptionReference *pTypeRef )
303*9c15e1abSPedro Giffuni {
304*9c15e1abSPedro Giffuni // For simple types and small aggregates, size is rounded to 8
305*9c15e1abSPedro Giffuni typelib_TypeDescription * pTypeDescr = 0;
306*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
307*9c15e1abSPedro Giffuni sal_uInt32 size = pTypeDescr->nSize;
308*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTypeDescr );
309*9c15e1abSPedro Giffuni return ( size + 7 ) & ~7u;
310*9c15e1abSPedro Giffuni }
311*9c15e1abSPedro Giffuni
312*9c15e1abSPedro Giffuni } // namespace aarch64
313