blob: d572646aff092faf182ef784cc1117c95e4f1fe9 [file] [log] [blame]
José Fonsecae0e61402010-11-25 15:03:23 +00001##########################################################################
2#
3# Copyright 2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
José Fonseca4a826ed2010-11-30 16:58:22 +000027"""Generic retracing code generator."""
28
José Fonseca0a37edf2011-10-09 09:45:22 +010029
José Fonseca9d27a542012-04-14 17:22:57 +010030# Adjust path
31import os.path
José Fonseca0a37edf2011-10-09 09:45:22 +010032import sys
José Fonseca9d27a542012-04-14 17:22:57 +010033sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
34
José Fonseca0a37edf2011-10-09 09:45:22 +010035
José Fonsecabd86a222011-09-27 09:21:38 +010036import specs.stdapi as stdapi
José Fonsecae0e61402010-11-25 15:03:23 +000037
38
José Fonseca2672a7d2012-04-14 15:17:12 +010039class UnsupportedType(Exception):
40 pass
41
42
Cass Everitt3b595cb2013-06-19 19:30:32 -050043def lookupHandle(handle, value, lval=False):
José Fonseca8a844ae2010-12-06 18:50:52 +000044 if handle.key is None:
José Fonseca632a78d2012-04-19 07:18:59 +010045 return "_%s_map[%s]" % (handle.name, value)
José Fonseca8a844ae2010-12-06 18:50:52 +000046 else:
47 key_name, key_type = handle.key
Cass Everitt3b595cb2013-06-19 19:30:32 -050048 if handle.name == "location" and lval == False:
49 return "_location_map[%s].lookupUniformLocation(%s)" % (key_name, value)
50 else:
51 return "_%s_map[%s][%s]" % (handle.name, key_name, value)
José Fonseca8a844ae2010-12-06 18:50:52 +000052
53
José Fonseca4a2c57b2012-04-07 10:50:53 +010054class ValueAllocator(stdapi.Visitor):
55
56 def visitLiteral(self, literal, lvalue, rvalue):
57 pass
58
59 def visitConst(self, const, lvalue, rvalue):
60 self.visit(const.type, lvalue, rvalue)
61
62 def visitAlias(self, alias, lvalue, rvalue):
63 self.visit(alias.type, lvalue, rvalue)
64
65 def visitEnum(self, enum, lvalue, rvalue):
66 pass
67
68 def visitBitmask(self, bitmask, lvalue, rvalue):
69 pass
70
71 def visitArray(self, array, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010072 print(' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue))
José Fonseca4a2c57b2012-04-07 10:50:53 +010073
74 def visitPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010075 print(' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, pointer.type, rvalue))
José Fonseca4a2c57b2012-04-07 10:50:53 +010076
77 def visitIntPointer(self, pointer, lvalue, rvalue):
78 pass
79
80 def visitObjPointer(self, pointer, lvalue, rvalue):
81 pass
82
83 def visitLinearPointer(self, pointer, lvalue, rvalue):
84 pass
85
86 def visitReference(self, reference, lvalue, rvalue):
87 self.visit(reference.type, lvalue, rvalue);
88
89 def visitHandle(self, handle, lvalue, rvalue):
90 pass
91
92 def visitBlob(self, blob, lvalue, rvalue):
93 pass
94
95 def visitString(self, string, lvalue, rvalue):
96 pass
97
98 def visitStruct(self, struct, lvalue, rvalue):
99 pass
100
101 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecadbf714b2012-11-20 17:03:43 +0000102 assert polymorphic.defaultType is not None
José Fonseca4a2c57b2012-04-07 10:50:53 +0100103 self.visit(polymorphic.defaultType, lvalue, rvalue)
104
José Fonseca2672a7d2012-04-14 15:17:12 +0100105 def visitOpaque(self, opaque, lvalue, rvalue):
106 pass
107
José Fonseca4a2c57b2012-04-07 10:50:53 +0100108
José Fonsecadbf714b2012-11-20 17:03:43 +0000109class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonsecae0e61402010-11-25 15:03:23 +0000110
José Fonseca54f304a2012-01-14 19:33:08 +0000111 def visitLiteral(self, literal, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100112 print(' %s = (%s).to%s();' % (lvalue, rvalue, literal.kind))
José Fonsecae0e61402010-11-25 15:03:23 +0000113
José Fonseca54f304a2012-01-14 19:33:08 +0000114 def visitConst(self, const, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000115 self.visit(const.type, lvalue, rvalue)
116
José Fonseca54f304a2012-01-14 19:33:08 +0000117 def visitAlias(self, alias, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000118 self.visit(alias.type, lvalue, rvalue)
119
José Fonseca54f304a2012-01-14 19:33:08 +0000120 def visitEnum(self, enum, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100121 print(' %s = static_cast<%s>((%s).toSInt());' % (lvalue, enum, rvalue))
José Fonsecae0e61402010-11-25 15:03:23 +0000122
José Fonseca54f304a2012-01-14 19:33:08 +0000123 def visitBitmask(self, bitmask, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100124 print(' %s = static_cast<%s>((%s).toUInt());' % (lvalue, bitmask, rvalue))
José Fonsecae0e61402010-11-25 15:03:23 +0000125
José Fonseca54f304a2012-01-14 19:33:08 +0000126 def visitArray(self, array, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100127 tmp = '_a_' + array.tag + '_' + str(self.seq)
José Fonseca68013c92012-04-05 19:58:38 +0100128 self.seq += 1
129
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100130 print(' const trace::Array *%s = (%s).toArray();' % (tmp, rvalue))
131 print(' if (%s) {' % (tmp,))
Jose Fonseca41efd942015-06-10 22:54:18 +0100132
Jose Fonsecaf48264d2015-07-17 17:00:23 +0100133 length = '%s->values.size()' % (tmp,)
Jose Fonseca41efd942015-06-10 22:54:18 +0100134 if self.insideStruct:
135 if isinstance(array.length, int):
136 # Member is an array
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100137 print(r' static_assert( std::is_array< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be an array" );' % lvalue)
138 print(r' static_assert( std::extent< std::remove_reference< decltype( %s ) >::type >::value == %s, "array size mismatch" );' % (lvalue, array.length))
139 print(r' assert( %s );' % (tmp,))
140 print(r' assert( %s->size() == %s );' % (tmp, array.length))
Jose Fonsecaf48264d2015-07-17 17:00:23 +0100141 length = str(array.length)
Jose Fonseca41efd942015-06-10 22:54:18 +0100142 else:
143 # Member is a pointer to an array, hence must be allocated
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100144 print(r' static_assert( std::is_pointer< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be a pointer" );' % lvalue)
145 print(r' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue))
Jose Fonseca41efd942015-06-10 22:54:18 +0100146
José Fonseca632a78d2012-04-19 07:18:59 +0100147 index = '_j' + array.tag
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100148 print(' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length))
José Fonsecae0e61402010-11-25 15:03:23 +0000149 try:
José Fonseca68013c92012-04-05 19:58:38 +0100150 self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
José Fonsecae0e61402010-11-25 15:03:23 +0000151 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100152 print(' }')
153 print(' }')
José Fonsecae0e61402010-11-25 15:03:23 +0000154
José Fonseca54f304a2012-01-14 19:33:08 +0000155 def visitPointer(self, pointer, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100156 tmp = '_a_' + pointer.tag + '_' + str(self.seq)
José Fonseca68013c92012-04-05 19:58:38 +0100157 self.seq += 1
158
Jose Fonseca2e295882016-05-16 14:20:39 +0100159 if self.insideStruct:
160 # Member is a pointer to an object, hence must be allocated
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100161 print(r' static_assert( std::is_pointer< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be a pointer" );' % lvalue)
162 print(r' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, pointer.type, rvalue))
Jose Fonseca2e295882016-05-16 14:20:39 +0100163
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100164 print(' if (%s) {' % (lvalue,))
165 print(' const trace::Array *%s = (%s).toArray();' % (tmp, rvalue))
José Fonsecae0e61402010-11-25 15:03:23 +0000166 try:
José Fonseca68013c92012-04-05 19:58:38 +0100167 self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
José Fonsecae0e61402010-11-25 15:03:23 +0000168 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100169 print(' }')
José Fonsecae0e61402010-11-25 15:03:23 +0000170
José Fonseca59ee88e2012-01-15 14:24:10 +0000171 def visitIntPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100172 print(' %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue))
José Fonseca59ee88e2012-01-15 14:24:10 +0000173
José Fonsecafbcf6832012-04-05 07:10:30 +0100174 def visitObjPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100175 print(' %s = retrace::asObjPointer<%s>(call, %s);' % (lvalue, pointer.type, rvalue))
José Fonsecafbcf6832012-04-05 07:10:30 +0100176
José Fonseca59ee88e2012-01-15 14:24:10 +0000177 def visitLinearPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100178 print(' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue))
José Fonseca59ee88e2012-01-15 14:24:10 +0000179
José Fonsecab89c5932012-04-01 22:47:11 +0200180 def visitReference(self, reference, lvalue, rvalue):
181 self.visit(reference.type, lvalue, rvalue);
182
José Fonseca54f304a2012-01-14 19:33:08 +0000183 def visitHandle(self, handle, lvalue, rvalue):
José Fonseca59ee88e2012-01-15 14:24:10 +0000184 #OpaqueValueDeserializer().visit(handle.type, lvalue, rvalue);
185 self.visit(handle.type, lvalue, rvalue);
José Fonseca54f304a2012-01-14 19:33:08 +0000186 new_lvalue = lookupHandle(handle, lvalue)
Jose Fonseca28e29ee2017-07-30 14:21:48 +0100187 shaderObject = new_lvalue.startswith('_program_map') or new_lvalue.startswith('_shader_map')
188 if shaderObject:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100189 print('if (glretrace::supportsARBShaderObjects) {')
190 print(' if (retrace::verbosity >= 2) {')
191 print(' std::cout << "%s " << size_t(%s) << " <- " << size_t(_handleARB_map[%s]) << "\\n";' % (handle.name, lvalue, lvalue))
192 print(' }')
193 print(' %s = _handleARB_map[%s];' % (lvalue, lvalue))
194 print('} else {')
195 print(' if (retrace::verbosity >= 2) {')
196 print(' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue))
197 print(' }')
198 print(' %s = %s;' % (lvalue, new_lvalue))
Jose Fonseca28e29ee2017-07-30 14:21:48 +0100199 if shaderObject:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100200 print('}')
José Fonsecae0e61402010-11-25 15:03:23 +0000201
José Fonseca54f304a2012-01-14 19:33:08 +0000202 def visitBlob(self, blob, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100203 print(' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue))
José Fonsecae0e61402010-11-25 15:03:23 +0000204
José Fonseca54f304a2012-01-14 19:33:08 +0000205 def visitString(self, string, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100206 print(' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue))
José Fonsecae0e61402010-11-25 15:03:23 +0000207
José Fonsecaa65a23a2012-04-02 08:10:06 +0200208 seq = 0
209
Jose Fonseca41efd942015-06-10 22:54:18 +0100210 insideStruct = 0
211
José Fonsecaa65a23a2012-04-02 08:10:06 +0200212 def visitStruct(self, struct, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100213 tmp = '_s_' + struct.tag + '_' + str(self.seq)
José Fonsecaa65a23a2012-04-02 08:10:06 +0200214 self.seq += 1
215
Jose Fonseca41efd942015-06-10 22:54:18 +0100216 self.insideStruct += 1
217
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100218 print(' const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue))
219 print(' assert(%s);' % (tmp))
José Fonsecaa65a23a2012-04-02 08:10:06 +0200220 for i in range(len(struct.members)):
José Fonsecadbf714b2012-11-20 17:03:43 +0000221 member = struct.members[i]
222 self.visitMember(member, lvalue, '*%s->members[%s]' % (tmp, i))
José Fonsecaa65a23a2012-04-02 08:10:06 +0200223
Jose Fonseca41efd942015-06-10 22:54:18 +0100224 self.insideStruct -= 1
225
José Fonseca4a2c57b2012-04-07 10:50:53 +0100226 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecaeb216e62012-11-20 11:08:08 +0000227 if polymorphic.defaultType is None:
José Fonsecadbf714b2012-11-20 17:03:43 +0000228 switchExpr = self.expand(polymorphic.switchExpr)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100229 print(r' switch (%s) {' % switchExpr)
José Fonsecadbf714b2012-11-20 17:03:43 +0000230 for cases, type in polymorphic.iterSwitch():
231 for case in cases:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100232 print(r' %s:' % case)
José Fonsecadbf714b2012-11-20 17:03:43 +0000233 caseLvalue = lvalue
234 if type.expr is not None:
235 caseLvalue = 'static_cast<%s>(%s)' % (type, caseLvalue)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100236 print(r' {')
José Fonsecadbf714b2012-11-20 17:03:43 +0000237 try:
238 self.visit(type, caseLvalue, rvalue)
239 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100240 print(r' }')
241 print(r' break;')
José Fonsecadbf714b2012-11-20 17:03:43 +0000242 if polymorphic.defaultType is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100243 print(r' default:')
244 print(r' retrace::warning(call) << "unexpected polymorphic case" << %s << "\n";' % (switchExpr,))
245 print(r' break;')
246 print(r' }')
José Fonsecadbf714b2012-11-20 17:03:43 +0000247 else:
248 self.visit(polymorphic.defaultType, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100249
250 def visitOpaque(self, opaque, lvalue, rvalue):
251 raise UnsupportedType
José Fonseca4a2c57b2012-04-07 10:50:53 +0100252
José Fonsecae0e61402010-11-25 15:03:23 +0000253
José Fonseca54f304a2012-01-14 19:33:08 +0000254class OpaqueValueDeserializer(ValueDeserializer):
José Fonsecaa10af892011-04-11 09:10:55 +0100255 '''Value extractor that also understands opaque values.
256
257 Normally opaque values can't be retraced, unless they are being extracted
258 in the context of handles.'''
259
José Fonseca54f304a2012-01-14 19:33:08 +0000260 def visitOpaque(self, opaque, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100261 print(' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue))
José Fonsecaa10af892011-04-11 09:10:55 +0100262
José Fonsecae0e61402010-11-25 15:03:23 +0000263
José Fonsecadbf714b2012-11-20 17:03:43 +0000264class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000265 '''Type visitor which will register (un)swizzled value pairs, to later be
266 swizzled.'''
José Fonsecae0e61402010-11-25 15:03:23 +0000267
José Fonseca54f304a2012-01-14 19:33:08 +0000268 def visitLiteral(self, literal, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000269 pass
270
José Fonseca54f304a2012-01-14 19:33:08 +0000271 def visitAlias(self, alias, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000272 self.visit(alias.type, lvalue, rvalue)
273
José Fonseca54f304a2012-01-14 19:33:08 +0000274 def visitEnum(self, enum, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000275 pass
276
José Fonseca54f304a2012-01-14 19:33:08 +0000277 def visitBitmask(self, bitmask, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000278 pass
279
José Fonseca54f304a2012-01-14 19:33:08 +0000280 def visitArray(self, array, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100281 print(' const trace::Array *_a%s = (%s).toArray();' % (array.tag, rvalue))
282 print(' if (_a%s) {' % (array.tag))
José Fonseca632a78d2012-04-19 07:18:59 +0100283 length = '_a%s->values.size()' % array.tag
284 index = '_j' + array.tag
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100285 print(' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length))
José Fonsecae0e61402010-11-25 15:03:23 +0000286 try:
José Fonseca632a78d2012-04-19 07:18:59 +0100287 self.visit(array.type, '%s[%s]' % (lvalue, index), '*_a%s->values[%s]' % (array.tag, index))
José Fonsecae0e61402010-11-25 15:03:23 +0000288 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100289 print(' }')
290 print(' }')
José Fonsecae0e61402010-11-25 15:03:23 +0000291
José Fonseca54f304a2012-01-14 19:33:08 +0000292 def visitPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100293 print(' const trace::Array *_a%s = (%s).toArray();' % (pointer.tag, rvalue))
294 print(' if (_a%s) {' % (pointer.tag))
José Fonsecae0e61402010-11-25 15:03:23 +0000295 try:
José Fonseca632a78d2012-04-19 07:18:59 +0100296 self.visit(pointer.type, '%s[0]' % (lvalue,), '*_a%s->values[0]' % (pointer.tag,))
José Fonsecae0e61402010-11-25 15:03:23 +0000297 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100298 print(' }')
José Fonsecae0e61402010-11-25 15:03:23 +0000299
José Fonseca59ee88e2012-01-15 14:24:10 +0000300 def visitIntPointer(self, pointer, lvalue, rvalue):
301 pass
302
José Fonsecafbcf6832012-04-05 07:10:30 +0100303 def visitObjPointer(self, pointer, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100304 print(r' retrace::addObj(call, %s, %s);' % (rvalue, lvalue))
José Fonsecafbcf6832012-04-05 07:10:30 +0100305
José Fonseca59ee88e2012-01-15 14:24:10 +0000306 def visitLinearPointer(self, pointer, lvalue, rvalue):
307 assert pointer.size is not None
308 if pointer.size is not None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100309 print(r' retrace::addRegion(call, (%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size))
José Fonseca59ee88e2012-01-15 14:24:10 +0000310
José Fonsecab89c5932012-04-01 22:47:11 +0200311 def visitReference(self, reference, lvalue, rvalue):
312 pass
313
José Fonseca54f304a2012-01-14 19:33:08 +0000314 def visitHandle(self, handle, lvalue, rvalue):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100315 print(' %s _origResult;' % handle.type)
José Fonseca632a78d2012-04-19 07:18:59 +0100316 OpaqueValueDeserializer().visit(handle.type, '_origResult', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000317 if handle.range is None:
José Fonseca632a78d2012-04-19 07:18:59 +0100318 rvalue = "_origResult"
Cass Everitt3b595cb2013-06-19 19:30:32 -0500319 entry = lookupHandle(handle, rvalue, True)
Carl Worth37007772012-08-28 11:45:52 -0700320 if (entry.startswith('_program_map') or entry.startswith('_shader_map')):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100321 print('if (glretrace::supportsARBShaderObjects) {')
322 print(' _handleARB_map[%s] = %s;' % (rvalue, lvalue))
323 print('} else {')
324 print(' %s = %s;' % (entry, lvalue))
325 print('}')
Carl Worth37007772012-08-28 11:45:52 -0700326 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100327 print(" %s = %s;" % (entry, lvalue))
Ilia Mirkin8db03b72017-11-26 14:23:35 -0500328 if entry.startswith('_textureHandle_map') or entry.startswith('_imageHandle_map'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100329 print(' if (%s != %s) {' % (rvalue, lvalue))
330 print(' std::cout << "Bindless handle doesn\'t match, GPU failures ahead.\\n";')
331 print(' }')
Ilia Mirkin8db03b72017-11-26 14:23:35 -0500332
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100333 print(' if (retrace::verbosity >= 2) {')
334 print(' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals()))
335 print(' }')
José Fonsecad922e1d2010-11-25 17:14:02 +0000336 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100337 i = '_h' + handle.tag
José Fonseca8a844ae2010-12-06 18:50:52 +0000338 lvalue = "%s + %s" % (lvalue, i)
José Fonseca632a78d2012-04-19 07:18:59 +0100339 rvalue = "_origResult + %s" % (i,)
José Fonseca54f304a2012-01-14 19:33:08 +0000340 entry = lookupHandle(handle, rvalue)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100341 print(' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals()))
342 print(' {entry} = {lvalue};'.format(**locals()))
343 print(' if (retrace::verbosity >= 2) {')
344 print(' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals()))
345 print(' }')
346 print(' }')
José Fonsecae0e61402010-11-25 15:03:23 +0000347
José Fonseca54f304a2012-01-14 19:33:08 +0000348 def visitBlob(self, blob, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000349 pass
350
José Fonseca54f304a2012-01-14 19:33:08 +0000351 def visitString(self, string, lvalue, rvalue):
José Fonsecae0e61402010-11-25 15:03:23 +0000352 pass
353
José Fonseca4a2c57b2012-04-07 10:50:53 +0100354 seq = 0
355
356 def visitStruct(self, struct, lvalue, rvalue):
José Fonseca632a78d2012-04-19 07:18:59 +0100357 tmp = '_s_' + struct.tag + '_' + str(self.seq)
José Fonseca4a2c57b2012-04-07 10:50:53 +0100358 self.seq += 1
359
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100360 print(' const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue))
361 print(' assert(%s);' % (tmp,))
362 print(' (void)%s;' % (tmp,))
José Fonseca4a2c57b2012-04-07 10:50:53 +0100363 for i in range(len(struct.members)):
José Fonsecadbf714b2012-11-20 17:03:43 +0000364 member = struct.members[i]
365 self.visitMember(member, lvalue, '*%s->members[%s]' % (tmp, i))
José Fonseca4a2c57b2012-04-07 10:50:53 +0100366
367 def visitPolymorphic(self, polymorphic, lvalue, rvalue):
José Fonsecadbf714b2012-11-20 17:03:43 +0000368 assert polymorphic.defaultType is not None
José Fonseca4a2c57b2012-04-07 10:50:53 +0100369 self.visit(polymorphic.defaultType, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100370
371 def visitOpaque(self, opaque, lvalue, rvalue):
372 pass
José Fonseca4a2c57b2012-04-07 10:50:53 +0100373
José Fonsecae0e61402010-11-25 15:03:23 +0000374
José Fonsecae0e61402010-11-25 15:03:23 +0000375class Retracer:
376
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000377 def makeFunctionId(self, function):
378 name = function.name
379 if function.overloaded:
380 # TODO: Use a sequence number
381 name += '__%08x' % (hash(function) & 0xffffffff)
382 return name
383
José Fonseca54f304a2012-01-14 19:33:08 +0000384 def retraceFunction(self, function):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100385 print('static void retrace_%s(trace::Call &call) {' % self.makeFunctionId(function))
José Fonseca54f304a2012-01-14 19:33:08 +0000386 self.retraceFunctionBody(function)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100387 print('}')
388 print()
José Fonseca62212972011-03-23 13:22:55 +0000389
José Fonseca8e3c2c02012-01-23 00:30:35 +0000390 def retraceInterfaceMethod(self, interface, method):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100391 print('static void retrace_%s__%s(trace::Call &call) {' % (interface.name, self.makeFunctionId(method)))
José Fonseca8e3c2c02012-01-23 00:30:35 +0000392 self.retraceInterfaceMethodBody(interface, method)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100393 print('}')
394 print()
José Fonseca8e3c2c02012-01-23 00:30:35 +0000395
José Fonseca54f304a2012-01-14 19:33:08 +0000396 def retraceFunctionBody(self, function):
José Fonsecadd27f9f2012-04-13 13:57:23 +0100397 assert function.sideeffects
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100398
José Fonseca7c7c9062012-04-27 13:02:08 +0100399 if function.type is not stdapi.Void:
400 self.checkOrigResult(function)
401
José Fonseca8e3c2c02012-01-23 00:30:35 +0000402 self.deserializeArgs(function)
403
José Fonseca3db3b2f2012-05-11 14:55:50 +0100404 self.declareRet(function)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000405 self.invokeFunction(function)
406
407 self.swizzleValues(function)
408
409 def retraceInterfaceMethodBody(self, interface, method):
José Fonseca1da480d2012-04-13 17:36:19 +0100410 assert method.sideeffects
José Fonseca8e3c2c02012-01-23 00:30:35 +0000411
José Fonseca7c7c9062012-04-27 13:02:08 +0100412 if method.type is not stdapi.Void:
413 self.checkOrigResult(method)
414
José Fonseca8e3c2c02012-01-23 00:30:35 +0000415 self.deserializeThisPointer(interface)
416
417 self.deserializeArgs(method)
418
José Fonseca3db3b2f2012-05-11 14:55:50 +0100419 self.declareRet(method)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000420 self.invokeInterfaceMethod(interface, method)
421
422 self.swizzleValues(method)
423
José Fonseca7c7c9062012-04-27 13:02:08 +0100424 def checkOrigResult(self, function):
425 '''Hook for checking the original result, to prevent succeeding now
426 where the original did not, which would cause diversion and potentially
427 unpredictable results.'''
428
429 assert function.type is not stdapi.Void
430
431 if str(function.type) == 'HRESULT':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100432 print(r' if (call.ret && FAILED(call.ret->toSInt())) {')
433 print(r' return;')
434 print(r' }')
José Fonseca7c7c9062012-04-27 13:02:08 +0100435
José Fonseca8e3c2c02012-01-23 00:30:35 +0000436 def deserializeThisPointer(self, interface):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100437 print(r' %s *_this;' % (interface.name,))
438 print(r' _this = retrace::asObjPointer<%s>(call, call.arg(0));' % (interface.name,))
439 print(r' if (!_this) {')
440 print(r' return;')
441 print(r' }')
José Fonseca8e3c2c02012-01-23 00:30:35 +0000442
443 def deserializeArgs(self, function):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100444 print(' retrace::ScopedAllocator _allocator;')
445 print(' (void)_allocator;')
José Fonsecae0e61402010-11-25 15:03:23 +0000446 success = True
447 for arg in function.args:
José Fonseca0075f152012-04-14 20:25:52 +0100448 arg_type = arg.type.mutable()
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100449 print(' %s %s;' % (arg_type, arg.name))
José Fonsecae0e61402010-11-25 15:03:23 +0000450 rvalue = 'call.arg(%u)' % (arg.index,)
451 lvalue = arg.name
452 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000453 self.extractArg(function, arg, arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100454 except UnsupportedType:
José Fonseca8e3c2c02012-01-23 00:30:35 +0000455 success = False
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100456 print(' memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name))
457 print()
José Fonseca8e3c2c02012-01-23 00:30:35 +0000458
José Fonsecae0e61402010-11-25 15:03:23 +0000459 if not success:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100460 print(' if (1) {')
José Fonseca54f304a2012-01-14 19:33:08 +0000461 self.failFunction(function)
José Fonsecaeb216e62012-11-20 11:08:08 +0000462 sys.stderr.write('warning: unsupported %s call\n' % function.name)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100463 print(' }')
José Fonseca8e3c2c02012-01-23 00:30:35 +0000464
465 def swizzleValues(self, function):
José Fonsecae0e61402010-11-25 15:03:23 +0000466 for arg in function.args:
467 if arg.output:
José Fonseca0075f152012-04-14 20:25:52 +0100468 arg_type = arg.type.mutable()
José Fonsecae0e61402010-11-25 15:03:23 +0000469 rvalue = 'call.arg(%u)' % (arg.index,)
470 lvalue = arg.name
471 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000472 self.regiterSwizzledValue(arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100473 except UnsupportedType:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100474 print(' // XXX: %s' % arg.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000475 if function.type is not stdapi.Void:
476 rvalue = '*call.ret'
José Fonseca632a78d2012-04-19 07:18:59 +0100477 lvalue = '_result'
José Fonsecae0e61402010-11-25 15:03:23 +0000478 try:
José Fonseca54f304a2012-01-14 19:33:08 +0000479 self.regiterSwizzledValue(function.type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100480 except UnsupportedType:
José Fonsecafbcf6832012-04-05 07:10:30 +0100481 raise
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100482 print(' // XXX: result')
José Fonsecae0e61402010-11-25 15:03:23 +0000483
José Fonseca54f304a2012-01-14 19:33:08 +0000484 def failFunction(self, function):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100485 print(' if (retrace::verbosity >= 0) {')
486 print(' retrace::unsupported(call);')
487 print(' }')
488 print(' return;')
José Fonsecafa15d332010-11-25 20:22:39 +0000489
José Fonseca54f304a2012-01-14 19:33:08 +0000490 def extractArg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca4a2c57b2012-04-07 10:50:53 +0100491 ValueAllocator().visit(arg_type, lvalue, rvalue)
492 if arg.input:
493 ValueDeserializer().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100494
José Fonseca54f304a2012-01-14 19:33:08 +0000495 def extractOpaqueArg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca4a2c57b2012-04-07 10:50:53 +0100496 try:
497 ValueAllocator().visit(arg_type, lvalue, rvalue)
José Fonseca2672a7d2012-04-14 15:17:12 +0100498 except UnsupportedType:
José Fonseca4a2c57b2012-04-07 10:50:53 +0100499 pass
José Fonseca54f304a2012-01-14 19:33:08 +0000500 OpaqueValueDeserializer().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000501
José Fonseca54f304a2012-01-14 19:33:08 +0000502 def regiterSwizzledValue(self, type, lvalue, rvalue):
503 visitor = SwizzledValueRegistrator()
504 visitor.visit(type, lvalue, rvalue)
505
José Fonseca3db3b2f2012-05-11 14:55:50 +0100506 def declareRet(self, function):
507 if function.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100508 print(' %s _result;' % (function.type))
José Fonseca3db3b2f2012-05-11 14:55:50 +0100509
José Fonseca54f304a2012-01-14 19:33:08 +0000510 def invokeFunction(self, function):
Jose Fonsecaf39fd602017-08-23 15:13:39 +0100511 # Same as invokeFunction, but without error checking
512 #
513 # XXX: Find a better name
514 self.doInvokeFunction(function)
515 if function.type is not stdapi.Void:
516 self.checkResult(None, function)
517
518 def doInvokeFunction(self, function):
José Fonseca59ee88e2012-01-15 14:24:10 +0000519 arg_names = ", ".join(function.argNames())
José Fonsecafa15d332010-11-25 20:22:39 +0000520 if function.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100521 print(' _result = %s(%s);' % (function.name, arg_names))
José Fonsecafa15d332010-11-25 20:22:39 +0000522 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100523 print(' %s(%s);' % (function.name, arg_names))
José Fonsecafa15d332010-11-25 20:22:39 +0000524
Jose Fonsecad9ff09f2016-05-16 14:04:36 +0100525 def doInvokeInterfaceMethod(self, interface, method):
526 # Same as invokeInterfaceMethod, but without error checking
527 #
528 # XXX: Find a better name
529
José Fonseca8e3c2c02012-01-23 00:30:35 +0000530 arg_names = ", ".join(method.argNames())
531 if method.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100532 print(' _result = _this->%s(%s);' % (method.name, arg_names))
José Fonseca8e3c2c02012-01-23 00:30:35 +0000533 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100534 print(' _this->%s(%s);' % (method.name, arg_names))
José Fonseca8e3c2c02012-01-23 00:30:35 +0000535
José Fonsecada777082015-02-09 11:18:36 +0000536 # Adjust reference count when QueryInterface fails. This is
537 # particularly useful when replaying traces on older Direct3D runtimes
538 # which might miss newer versions of interfaces, yet none of those
539 # methods are actually used.
540 #
541 # TODO: Generalize to other methods that return interfaces
542 if method.name == 'QueryInterface':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100543 print(r' if (FAILED(_result)) {')
544 print(r' IUnknown *pObj = retrace::asObjPointer<IUnknown>(call, *call.arg(2).toArray()->values[0]);')
545 print(r' if (pObj) {')
546 print(r' pObj->AddRef();')
547 print(r' }')
548 print(r' }')
José Fonsecada777082015-02-09 11:18:36 +0000549
José Fonseca8a4462e2014-09-23 14:39:01 +0100550 # Debug COM reference counting. Disabled by default as reported
551 # reference counts depend on internal implementation details.
552 if method.name in ('AddRef', 'Release'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100553 print(r' if (0) retrace::checkMismatch(call, "cRef", call.ret, _result);')
José Fonseca8a4462e2014-09-23 14:39:01 +0100554
555 # On release our reference when we reach Release() == 0 call in the
556 # trace.
557 if method.name == 'Release':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100558 print(r' ULONG _orig_result = call.ret->toUInt();')
559 print(r' if (_orig_result == 0 || _result == 0) {')
560 print(r' if (_orig_result != 0) {')
561 print(r' retrace::warning(call) << "unexpected object destruction\n";')
562 print(r' }')
563 print(r' // NOTE: Must not delete the object mapping here. See')
564 print(r' // https://github.com/apitrace/apitrace/issues/462')
565 print(r' }')
José Fonseca8a4462e2014-09-23 14:39:01 +0100566
Jose Fonsecad9ff09f2016-05-16 14:04:36 +0100567 def invokeInterfaceMethod(self, interface, method):
568 self.doInvokeInterfaceMethod(interface, method)
569
570 if method.type is not stdapi.Void:
571 self.checkResult(interface, method)
572
Jose Fonseca5c487ec2015-06-02 22:16:52 +0100573 def checkResult(self, interface, methodOrFunction):
574 assert methodOrFunction.type is not stdapi.Void
575 if str(methodOrFunction.type) == 'HRESULT':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100576 print(r' if (FAILED(_result)) {')
577 print(r' retrace::failed(call, _result);')
Jose Fonsecad0094a22017-05-30 12:31:37 +0100578 self.handleFailure(interface, methodOrFunction)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100579 print(r' }')
José Fonseca31983872015-02-09 11:16:20 +0000580 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100581 print(r' (void)_result;')
José Fonseca4f49d212012-11-14 14:02:35 +0000582
Jose Fonsecad0094a22017-05-30 12:31:37 +0100583 def handleFailure(self, interface, methodOrFunction):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100584 print(r' return;')
Jose Fonsecad0094a22017-05-30 12:31:37 +0100585
José Fonsecafacdb352014-09-05 13:22:01 +0100586 def checkPitchMismatch(self, method):
José Fonseca9a3abc72014-09-23 14:39:18 +0100587 # Warn for mismatches in 2D/3D mappings.
588 # FIXME: We should try to swizzle them. It's a bit of work, but possible.
589 for outArg in method.args:
590 if outArg.output \
591 and isinstance(outArg.type, stdapi.Pointer) \
592 and isinstance(outArg.type.type, stdapi.Struct):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100593 print(r' const trace::Array *_%s = call.arg(%u).toArray();' % (outArg.name, outArg.index))
594 print(r' if (%s) {' % outArg.name)
595 print(r' const trace::Struct *_struct = _%s->values[0]->toStruct();' % (outArg.name))
596 print(r' if (_struct) {')
José Fonseca9a3abc72014-09-23 14:39:18 +0100597 struct = outArg.type.type
598 for memberIndex in range(len(struct.members)):
599 memberType, memberName = struct.members[memberIndex]
600 if memberName.endswith('Pitch'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100601 print(r' if (%s->%s) {' % (outArg.name, memberName))
602 print(r' retrace::checkMismatch(call, "%s", _struct->members[%u], %s->%s);' % (memberName, memberIndex, outArg.name, memberName))
603 print(r' }')
604 print(r' }')
605 print(r' }')
José Fonsecafacdb352014-09-05 13:22:01 +0100606
José Fonseca54f304a2012-01-14 19:33:08 +0000607 def filterFunction(self, function):
José Fonseca4441baf2010-11-25 19:55:27 +0000608 return True
609
José Fonseca2741ed82011-10-07 23:36:39 +0100610 table_name = 'retrace::callbacks'
611
José Fonseca54f304a2012-01-14 19:33:08 +0000612 def retraceApi(self, api):
José Fonsecae0e61402010-11-25 15:03:23 +0000613
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100614 print('#include "os_time.hpp"')
615 print('#include "trace_parser.hpp"')
616 print('#include "retrace.hpp"')
617 print('#include "retrace_swizzle.hpp"')
618 print()
José Fonsecae0e61402010-11-25 15:03:23 +0000619
José Fonseca44703822012-01-31 10:48:58 +0000620 types = api.getAllTypes()
José Fonsecae0e61402010-11-25 15:03:23 +0000621 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000622 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000623 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000624 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000625 if handle.key is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100626 print('static retrace::map<%s> _%s_map;' % (handle.type, handle.name))
José Fonseca8a844ae2010-12-06 18:50:52 +0000627 else:
628 key_name, key_type = handle.key
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100629 print('static std::map<%s, retrace::map<%s> > _%s_map;' % (key_type, handle.type, handle.name))
José Fonsecad922e1d2010-11-25 17:14:02 +0000630 handle_names.add(handle.name)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100631 print()
José Fonsecae0e61402010-11-25 15:03:23 +0000632
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100633 functions = list(filter(self.filterFunction, api.getAllFunctions()))
José Fonseca8e3c2c02012-01-23 00:30:35 +0000634 for function in functions:
José Fonseca84cea3b2012-05-09 21:12:30 +0100635 if function.sideeffects and not function.internal:
José Fonseca1da480d2012-04-13 17:36:19 +0100636 self.retraceFunction(function)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000637 interfaces = api.getAllInterfaces()
638 for interface in interfaces:
José Fonseca14aa1712014-08-22 15:36:55 +0100639 for method in interface.methods:
José Fonseca84cea3b2012-05-09 21:12:30 +0100640 if method.sideeffects and not method.internal:
José Fonseca1da480d2012-04-13 17:36:19 +0100641 self.retraceInterfaceMethod(interface, method)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000642
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100643 print('const retrace::Entry %s[] = {' % self.table_name)
José Fonseca8e3c2c02012-01-23 00:30:35 +0000644 for function in functions:
José Fonseca84cea3b2012-05-09 21:12:30 +0100645 if not function.internal:
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000646 sigName = function.sigName()
José Fonseca84cea3b2012-05-09 21:12:30 +0100647 if function.sideeffects:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100648 print(' {"%s", &retrace_%s},' % (sigName, self.makeFunctionId(function)))
José Fonseca84cea3b2012-05-09 21:12:30 +0100649 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100650 print(' {"%s", &retrace::ignore},' % (sigName,))
José Fonseca8e3c2c02012-01-23 00:30:35 +0000651 for interface in interfaces:
José Fonseca14aa1712014-08-22 15:36:55 +0100652 for base, method in interface.iterBaseMethods():
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000653 sigName = method.sigName()
José Fonseca1da480d2012-04-13 17:36:19 +0100654 if method.sideeffects:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100655 print(' {"%s::%s", &retrace_%s__%s},' % (interface.name, sigName, base.name, self.makeFunctionId(method)))
José Fonseca1da480d2012-04-13 17:36:19 +0100656 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100657 print(' {"%s::%s", &retrace::ignore},' % (interface.name, sigName))
658 print(' {NULL, NULL}')
659 print('};')
660 print()
José Fonsecae0e61402010-11-25 15:03:23 +0000661