xref: /aosp_15_r20/external/mesa3d/src/gfxstream/codegen/scripts/cereal/deepcopy.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1# Copyright 2018 Google LLC
2# SPDX-License-Identifier: MIT
3
4from .common.codegen import CodeGen
5from .common.vulkantypes import \
6        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator
7
8from .wrapperdefs import VulkanWrapperGenerator
9from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE, EXTENSION_SIZE_API_NAME
10
11class DeepcopyCodegen(VulkanTypeIterator):
12    def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False):
13        self.cgen = cgen
14        self.inputVars = inputVars
15        self.prefix = prefix
16        self.poolVarName = poolVarName
17        self.rootVarName = rootVarName
18        self.skipValues = skipValues
19
20        def makeAccess(varName, asPtr = True):
21            return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)
22
23        def makeLengthAccess(varName):
24            return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)
25
26        def makeLengthAccessGuard(varName):
27            return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)
28
29        self.exprAccessorLhs = makeAccess(self.inputVars[0])
30        self.exprAccessorRhs = makeAccess(self.inputVars[1])
31
32        self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
33        self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)
34
35        self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
36        self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])
37
38        self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0])
39        self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1])
40
41        self.checked = False
42
43    def needSkip(self, vulkanType):
44        return False
45
46    def makeCastExpr(self, vulkanType):
47        return "(%s)" % (
48            self.cgen.makeCTypeDecl(vulkanType, useParamName=False))
49
50    def makeNonConstCastForCopy(self, access, vulkanType):
51        if vulkanType.staticArrExpr:
52            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
53        elif vulkanType.accessibleAsPointer():
54            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
55        else:
56            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
57        return casted
58
59    def makeAllocBytesExpr(self, lenAccess, vulkanType):
60        sizeof = self.cgen.sizeofExpr( \
61                     vulkanType.getForValueAccess())
62        if lenAccess:
63            bytesExpr = "%s * %s" % (lenAccess, sizeof)
64        else:
65            bytesExpr = sizeof
66
67        return bytesExpr
68
69    def onCheck(self, vulkanType):
70        pass
71
72    def endCheck(self, vulkanType):
73        pass
74
75    def onCompoundType(self, vulkanType):
76
77        if self.needSkip(vulkanType):
78            self.cgen.line("// TODO: Unsupported : %s" %
79                           self.cgen.makeCTypeDecl(vulkanType))
80            return
81
82        accessLhs = self.exprAccessorLhs(vulkanType)
83        accessRhs = self.exprAccessorRhs(vulkanType)
84
85        lenAccessLhs = self.lenAccessorLhs(vulkanType)
86        lenAccessRhs = self.lenAccessorRhs(vulkanType)
87
88        lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType)
89        lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType)
90
91        isPtr = vulkanType.pointerIndirectionLevels > 0
92
93        if lenAccessorGuardLhs is not None:
94            self.cgen.beginIf(lenAccessorGuardLhs)
95
96        if isPtr:
97            self.cgen.stmt("%s = nullptr" % accessRhs)
98            self.cgen.beginIf(accessLhs)
99
100            self.cgen.stmt( \
101                "%s = %s%s->alloc(%s)" % \
102                (accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()),
103                 self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType)))
104
105        if lenAccessLhs is not None:
106
107            loopVar = "i"
108            accessLhs = "%s + %s" % (accessLhs, loopVar)
109            forInit = "uint32_t %s = 0" % loopVar
110            forCond = "%s < (uint32_t)%s" % (loopVar, lenAccessLhs)
111            forIncr = "++%s" % loopVar
112
113            if isPtr:
114                # Avoid generating a self-assign.
115                if lenAccessRhs != lenAccessLhs:
116                    self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs))
117
118            accessRhs = "%s + %s" % (accessRhs, loopVar)
119            self.cgen.beginFor(forInit, forCond, forIncr)
120
121
122        accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType)
123
124        self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
125                           [self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted])
126
127        if lenAccessLhs is not None:
128            self.cgen.endFor()
129
130        if isPtr:
131            self.cgen.endIf()
132
133        if lenAccessorGuardLhs is not None:
134            self.cgen.endIf()
135
136    def onString(self, vulkanType):
137        accessLhs = self.exprAccessorLhs(vulkanType)
138        accessRhs = self.exprAccessorRhs(vulkanType)
139
140        self.cgen.stmt("%s = nullptr" % accessRhs)
141        self.cgen.beginIf(accessLhs)
142
143        self.cgen.stmt( \
144            "%s = %s->strDup(%s)" % \
145            (accessRhs,
146             self.poolVarName,
147             accessLhs))
148
149        self.cgen.endIf()
150
151    def onStringArray(self, vulkanType):
152        accessLhs = self.exprAccessorLhs(vulkanType)
153        accessRhs = self.exprAccessorRhs(vulkanType)
154
155        lenAccessLhs = self.lenAccessorLhs(vulkanType)
156
157        self.cgen.stmt("%s = nullptr" % accessRhs)
158        self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs))
159
160        self.cgen.stmt( \
161            "%s = %s->strDupArray(%s, %s)" % \
162            (accessRhs,
163             self.poolVarName,
164             accessLhs,
165             lenAccessLhs))
166
167        self.cgen.endIf()
168
169    def onStaticArr(self, vulkanType):
170        accessLhs = self.exprAccessorValueLhs(vulkanType)
171        accessRhs = self.exprAccessorValueRhs(vulkanType)
172
173        lenAccessLhs = self.lenAccessorLhs(vulkanType)
174
175        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
176        self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr))
177
178    def onStructExtension(self, vulkanType):
179
180        lhs = self.exprAccessorLhs(vulkanType)
181        rhs = self.exprAccessorRhs(vulkanType)
182
183        rhsExpr = "(%s)(%s)" % ("void*", rhs)
184
185        nextVar = "from_%s" % vulkanType.paramName
186        sizeVar = "%s_size" % vulkanType.paramName
187
188        self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
189                          self.rootVarName)
190        self.cgen.stmt("%s = from->sType" % self.rootVarName)
191        self.cgen.endIf()
192
193        self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0]))
194        self.cgen.stmt("size_t %s = 0u" % sizeVar)
195        self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar))
196        self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % (
197            nextVar, nextVar, vulkanType.paramName
198        ))
199        self.cgen.stmt("%s = %s(%s, %s)" % (
200            sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar))
201        self.cgen.endWhile()
202
203        self.cgen.stmt("%s = nullptr" % rhs)
204
205        self.cgen.beginIf(sizeVar)
206
207        self.cgen.stmt( \
208            "%s = %s%s->alloc(%s)" % \
209            (rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar))
210
211        self.cgen.funcCall(None, self.prefix + "extension_struct",
212                           [self.poolVarName, self.rootVarName, nextVar, rhsExpr])
213
214        self.cgen.endIf()
215
216    def onPointer(self, vulkanType):
217
218        accessLhs = self.exprAccessorLhs(vulkanType)
219        accessRhs = self.exprAccessorRhs(vulkanType)
220
221        if self.needSkip(vulkanType):
222            self.cgen.stmt("%s = nullptr" % accessRhs)
223            return
224
225        lenAccessLhs = self.lenAccessorLhs(vulkanType)
226
227        self.cgen.stmt("%s = nullptr" % accessRhs)
228        self.cgen.beginIf(accessLhs)
229
230        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
231
232        self.cgen.stmt( \
233            "%s = %s%s->dupArray(%s, %s)" % \
234            (accessRhs,
235             self.makeCastExpr(vulkanType.getForNonConstAccess()),
236             self.poolVarName,
237             accessLhs,
238             bytesExpr))
239
240        self.cgen.endIf()
241
242    def onValue(self, vulkanType):
243        if self.skipValues:
244            return
245
246        accessLhs = self.exprAccessorValueLhs(vulkanType)
247        accessRhs = self.exprAccessorValueRhs(vulkanType)
248
249        self.cgen.stmt("%s = %s" % (accessRhs, accessLhs))
250
251class VulkanDeepcopy(VulkanWrapperGenerator):
252
253    def __init__(self, module, typeInfo):
254        VulkanWrapperGenerator.__init__(self, module, typeInfo)
255
256        self.codegen = CodeGen()
257
258        self.deepcopyPrefix = "deepcopy_"
259        self.deepcopyVars = ["from", "to"]
260        self.deepcopyAllocatorVarName = "alloc"
261        self.deepcopyAllocatorParam = \
262            makeVulkanTypeSimple(False, "Allocator", 1,
263                                 self.deepcopyAllocatorVarName)
264        self.deepcopyRootVarName = "rootType"
265        self.deepcopyRootParam = \
266            makeVulkanTypeSimple(False, "VkStructureType",
267                                 0, self.deepcopyRootVarName)
268        self.voidType = makeVulkanTypeSimple(False, "void", 0)
269
270        self.deepcopyCodegen = \
271            DeepcopyCodegen(
272                None,
273                self.deepcopyVars,
274                self.deepcopyAllocatorVarName,
275                self.deepcopyRootVarName,
276                self.deepcopyPrefix,
277                skipValues=True)
278
279        self.knownDefs = {}
280
281        self.extensionDeepcopyPrototype = \
282            VulkanAPI(self.deepcopyPrefix + "extension_struct",
283                      self.voidType,
284                      [self.deepcopyAllocatorParam,
285                       self.deepcopyRootParam,
286                       STRUCT_EXTENSION_PARAM,
287                       STRUCT_EXTENSION_PARAM_FOR_WRITE])
288
289    def onBegin(self,):
290        VulkanWrapperGenerator.onBegin(self)
291        self.module.appendImpl(self.codegen.makeFuncDecl(
292            self.extensionDeepcopyPrototype))
293
294    def onGenType(self, typeXml, name, alias):
295        VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)
296
297        if name in self.knownDefs:
298            return
299
300        category = self.typeInfo.categoryOf(name)
301
302        if category in ["struct", "union"] and alias:
303            self.module.appendHeader(
304                self.codegen.makeFuncAlias(self.deepcopyPrefix + name,
305                                           self.deepcopyPrefix + alias))
306
307        if category in ["struct", "union"] and not alias:
308
309            structInfo = self.typeInfo.structs[name]
310
311            typeFromName = \
312                lambda varname: \
313                    makeVulkanTypeSimple(varname == "from", name, 1, varname)
314
315            deepcopyParams = \
316                [self.deepcopyAllocatorParam, self.deepcopyRootParam] + \
317                 list(map(typeFromName, self.deepcopyVars))
318
319            deepcopyPrototype = \
320                VulkanAPI(self.deepcopyPrefix + name,
321                          self.voidType,
322                          deepcopyParams)
323
324            def structDeepcopyDef(cgen):
325                self.deepcopyCodegen.cgen = cgen
326                canSimplyAssign = True
327                for member in structInfo.members:
328                    if not member.isSimpleValueType(self.typeInfo):
329                        canSimplyAssign = False
330
331                cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName)
332                cgen.stmt("(void)%s" % self.deepcopyRootVarName)
333                cgen.stmt("*to = *from")
334                if canSimplyAssign:
335                    pass
336                else:
337                    for member in structInfo.members:
338                        iterateVulkanType(self.typeInfo, member,
339                                          self.deepcopyCodegen)
340
341            self.module.appendHeader(
342                self.codegen.makeFuncDecl(deepcopyPrototype))
343            self.module.appendImpl(
344                self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef))
345
346    def onGenCmd(self, cmdinfo, name, alias):
347        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)
348
349    def onEnd(self,):
350        VulkanWrapperGenerator.onEnd(self)
351
352        def deepcopyDstExpr(cgen, typeName):
353            return cgen.makeReinterpretCast( \
354                       STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName,
355                       typeName, const=False)
356
357        def forEachExtensionDeepcopy(ext, castedAccess, cgen):
358            cgen.funcCall(None, self.deepcopyPrefix + ext.name,
359                          [self.deepcopyAllocatorVarName,
360                           self.deepcopyRootVarName,
361                           castedAccess, deepcopyDstExpr(cgen, ext.name)])
362
363        self.module.appendImpl(
364            self.codegen.makeFuncImpl(
365                self.extensionDeepcopyPrototype,
366                lambda cgen: self.emitForEachStructExtension(
367                    cgen,
368                    self.voidType,
369                    STRUCT_EXTENSION_PARAM,
370                    forEachExtensionDeepcopy,
371                    rootTypeVar=self.deepcopyRootParam)))
372