blob: 9788ef32ad75012f2b941b985bdc9519733a3ea6 [file] [log] [blame]
José Fonseca8fbdd3a2010-11-23 20:55:07 +00001##########################################################################
2#
3# Copyright 2008-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
José Fonseca73d0a962010-11-29 14:49:34 +000026"""Common trace code generation."""
José Fonseca8fbdd3a2010-11-23 20:55:07 +000027
28
José Fonseca452d3252012-04-14 15:55:40 +010029# Adjust path
30import os.path
31import sys
32sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
33
34
José Fonsecabd86a222011-09-27 09:21:38 +010035import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000036
37
José Fonseca0423d2c2012-01-20 19:16:17 +000038def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000039 return "Wrap" + interface.expr
40
José Fonseca6fac5ae2010-11-29 16:09:13 +000041
José Fonsecaf6b05132012-11-06 00:16:28 +000042
José Fonseca54f304a2012-01-14 19:33:08 +000043class ComplexValueSerializer(stdapi.OnceVisitor):
44 '''Type visitors which generates serialization functions for
45 complex types.
46
47 Simple types are serialized inline.
48 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000049
José Fonseca54f304a2012-01-14 19:33:08 +000050 def __init__(self, serializer):
51 stdapi.OnceVisitor.__init__(self)
52 self.serializer = serializer
53
54 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000055 pass
56
José Fonseca54f304a2012-01-14 19:33:08 +000057 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000058 pass
59
José Fonseca54f304a2012-01-14 19:33:08 +000060 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000061 pass
62
José Fonseca54f304a2012-01-14 19:33:08 +000063 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000064 self.visit(const.type)
65
José Fonseca54f304a2012-01-14 19:33:08 +000066 def visitStruct(self, struct):
José Fonseca30fb4c32012-11-04 11:07:45 +000067 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000068 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000069 if name is None:
70 print ' "",'
71 else:
72 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000073 print '};'
74 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000075 if struct.name is None:
76 structName = '""'
77 else:
78 structName = '"%s"' % struct.name
79 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000080 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000081 print
82
José Fonseca54f304a2012-01-14 19:33:08 +000083 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000084 self.visit(array.type)
85
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020086 def visitAttribArray(self, array):
87 pass
88
José Fonseca54f304a2012-01-14 19:33:08 +000089 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000090 pass
91
José Fonseca54f304a2012-01-14 19:33:08 +000092 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010093 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000094 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000095 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +000096 print '};'
97 print
José Fonseca632a78d2012-04-19 07:18:59 +010098 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +000099 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000100 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000101 print
102
José Fonseca54f304a2012-01-14 19:33:08 +0000103 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100104 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000105 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000106 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000107 print '};'
108 print
José Fonseca632a78d2012-04-19 07:18:59 +0100109 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000110 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000111 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000112 print
113
José Fonseca54f304a2012-01-14 19:33:08 +0000114 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000115 self.visit(pointer.type)
116
José Fonseca59ee88e2012-01-15 14:24:10 +0000117 def visitIntPointer(self, pointer):
118 pass
119
José Fonsecafbcf6832012-04-05 07:10:30 +0100120 def visitObjPointer(self, pointer):
121 self.visit(pointer.type)
122
José Fonseca59ee88e2012-01-15 14:24:10 +0000123 def visitLinearPointer(self, pointer):
124 self.visit(pointer.type)
125
José Fonseca54f304a2012-01-14 19:33:08 +0000126 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000127 self.visit(handle.type)
128
José Fonsecab89c5932012-04-01 22:47:11 +0200129 def visitReference(self, reference):
130 self.visit(reference.type)
131
José Fonseca54f304a2012-01-14 19:33:08 +0000132 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000133 self.visit(alias.type)
134
José Fonseca54f304a2012-01-14 19:33:08 +0000135 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000136 pass
137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000139 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000140
José Fonseca54f304a2012-01-14 19:33:08 +0000141 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100142 if not polymorphic.contextLess:
143 return
José Fonsecafbc51922013-04-14 14:45:04 +0100144 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100145 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000146 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100147 for case in cases:
148 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000149 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100150 print ' break;'
151 print ' }'
152 print '}'
153 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100154
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000155
José Fonsecadbf714b2012-11-20 17:03:43 +0000156class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000157 '''Visitor which generates code to serialize any type.
158
159 Simple types are serialized inline here, whereas the serialization of
160 complex types is dispatched to the serialization functions generated by
161 ComplexValueSerializer visitor above.
162 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000163
José Fonseca54f304a2012-01-14 19:33:08 +0000164 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100165 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000166
José Fonseca54f304a2012-01-14 19:33:08 +0000167 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100168 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000169 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100170 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000171 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100172 cast = 'const wchar_t *'
173 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000174 if cast != string.expr:
175 # reinterpret_cast is necessary for GLubyte * <=> char *
176 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
177 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000178 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000179 else:
180 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100181 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000182
José Fonseca54f304a2012-01-14 19:33:08 +0000183 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000184 self.visit(const.type, instance)
185
José Fonseca54f304a2012-01-14 19:33:08 +0000186 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000187 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000188 for member in struct.members:
189 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000190 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000191
José Fonseca54f304a2012-01-14 19:33:08 +0000192 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100193 length = '_c' + array.type.tag
194 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000195 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100196 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000197 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100198 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100199 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100200 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000201 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100202 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000203 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100204 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100205 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100206 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100207 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000208
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200209 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200210 # For each element, decide if it is a key or a value (which depends on the previous key).
211 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
212 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200213
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200214 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100215 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100216 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200217 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200218 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
219 % {'c': count, 'array': instance, 'terminator': array.terminator}
220 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200221 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200222 for key, valueType in array.valueTypes:
223 if valueType is None:
224 print ' case %s:' % key
225 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
226 print ' break;'
227 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200228 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200229 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200230 print ' trace::localWriter.beginArray(%s);' % count
231
232 # for each key / key-value pair write the key and the value, if the key requires one
233
José Fonseca77c10d82013-07-20 15:27:29 +0100234 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200235 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200236 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100237 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200238 print ' trace::localWriter.endElement();'
239 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
240 print ' break;'
241 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200242 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200243 # write generic value the usual way
244 for key, valueType in array.valueTypes:
245 if valueType is not None:
246 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200247 print ' trace::localWriter.beginElement();'
248 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
249 print ' trace::localWriter.endElement();'
250 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200251 # known key with no value, just decrease the index so we treat the next value as a key
252 if array.hasKeysWithoutValues:
253 for key, valueType in array.valueTypes:
254 if valueType is None:
255 print ' case %s:' % key
256 print ' %s--;' % index
257 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200258 # unknown key, write an int value
259 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200260 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200261 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100262 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200263 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200264 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200265 print ' break;'
266 print ' }'
267 print ' }'
268 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100269 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200270
271
José Fonseca54f304a2012-01-14 19:33:08 +0000272 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000273 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000274
José Fonseca54f304a2012-01-14 19:33:08 +0000275 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100276 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000277
José Fonseca54f304a2012-01-14 19:33:08 +0000278 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100279 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000280
José Fonseca54f304a2012-01-14 19:33:08 +0000281 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100282 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100283 print ' trace::localWriter.beginArray(1);'
284 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000285 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100286 print ' trace::localWriter.endElement();'
287 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100288 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100289 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100290 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000291
José Fonseca59ee88e2012-01-15 14:24:10 +0000292 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100293 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000294
José Fonsecafbcf6832012-04-05 07:10:30 +0100295 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100296 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100297
José Fonseca59ee88e2012-01-15 14:24:10 +0000298 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100299 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000300
José Fonsecab89c5932012-04-01 22:47:11 +0200301 def visitReference(self, reference, instance):
302 self.visit(reference.type, instance)
303
José Fonseca54f304a2012-01-14 19:33:08 +0000304 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000305 self.visit(handle.type, instance)
306
José Fonseca54f304a2012-01-14 19:33:08 +0000307 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000308 self.visit(alias.type, instance)
309
José Fonseca54f304a2012-01-14 19:33:08 +0000310 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100311 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000312
José Fonseca54f304a2012-01-14 19:33:08 +0000313 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100314 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000315
José Fonseca54f304a2012-01-14 19:33:08 +0000316 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100317 if polymorphic.contextLess:
318 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
319 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000320 switchExpr = self.expand(polymorphic.switchExpr)
321 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100322 for cases, type in polymorphic.iterSwitch():
323 for case in cases:
324 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000325 caseInstance = instance
326 if type.expr is not None:
327 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
328 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100329 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000330 if polymorphic.defaultType is None:
331 print r' default:'
332 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
333 print r' trace::localWriter.writeNull();'
334 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100335 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100336
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000337
José Fonseca0075f152012-04-14 20:25:52 +0100338class WrapDecider(stdapi.Traverser):
339 '''Type visitor which will decide wheter this type will need wrapping or not.
340
341 For complex types (arrays, structures), we need to know this before hand.
342 '''
343
344 def __init__(self):
345 self.needsWrapping = False
346
José Fonseca0075f152012-04-14 20:25:52 +0100347 def visitLinearPointer(self, void):
348 pass
349
350 def visitInterface(self, interface):
351 self.needsWrapping = True
352
353
José Fonsecadbf714b2012-11-20 17:03:43 +0000354class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000355 '''Type visitor which will generate the code to wrap an instance.
356
357 Wrapping is necessary mostly for interfaces, however interface pointers can
358 appear anywhere inside complex types.
359 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000360
José Fonseca54f304a2012-01-14 19:33:08 +0000361 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000362 for member in struct.members:
363 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000364
José Fonseca54f304a2012-01-14 19:33:08 +0000365 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000366 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100367 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000368 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
369 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100370 print " }"
371 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000372
José Fonseca54f304a2012-01-14 19:33:08 +0000373 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100374 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000375 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100376 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000377
José Fonsecafbcf6832012-04-05 07:10:30 +0100378 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100379 elem_type = pointer.type.mutable()
380 if isinstance(elem_type, stdapi.Interface):
381 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100382 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
383 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100384 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100385 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100386
José Fonseca54f304a2012-01-14 19:33:08 +0000387 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100388 raise NotImplementedError
389
390 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100391 print " if (%s) {" % instance
José Fonsecab7a9b182012-11-23 17:02:48 +0000392 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100393 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100394
José Fonseca54f304a2012-01-14 19:33:08 +0000395 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100396 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100397 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000398
399
José Fonseca54f304a2012-01-14 19:33:08 +0000400class ValueUnwrapper(ValueWrapper):
401 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000402
José Fonseca0075f152012-04-14 20:25:52 +0100403 allocated = False
404
José Fonsecae7cb2b92012-09-28 08:40:24 +0100405 def visitStruct(self, struct, instance):
406 if not self.allocated:
407 # Argument is constant. We need to create a non const
408 print ' {'
409 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
410 print ' *_t = %s;' % (instance,)
411 assert instance.startswith('*')
412 print ' %s = _t;' % (instance[1:],)
413 instance = '*_t'
414 self.allocated = True
415 try:
416 return ValueWrapper.visitStruct(self, struct, instance)
417 finally:
418 print ' }'
419 else:
420 return ValueWrapper.visitStruct(self, struct, instance)
421
José Fonseca0075f152012-04-14 20:25:52 +0100422 def visitArray(self, array, instance):
423 if self.allocated or isinstance(instance, stdapi.Interface):
424 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000425 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100426 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000427 print " if (%s && %s) {" % (instance, array_length)
428 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
429 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100430 print " _t[_i] = %s[_i];" % instance
431 self.allocated = True
432 self.visit(array.type, "_t[_i]")
433 print " }"
434 print " %s = _t;" % instance
435 print " }"
436
José Fonseca9782b292012-04-14 22:02:42 +0100437 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000438 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100439 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000440 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
441 print r' %s = pWrapper->m_pInstance;' % (instance,)
442 print r' } else {'
443 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
444 print r' }'
445 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000446
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000447
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000448class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000449 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000450
José Fonseca4b466a92012-11-26 19:47:26 +0000451 # 0-3 are reserved to memcpy, malloc, free, and realloc
452 __id = 4
453
José Fonsecabb8760b2011-05-25 23:21:18 +0100454 def __init__(self):
455 self.api = None
456
José Fonseca54f304a2012-01-14 19:33:08 +0000457 def serializerFactory(self):
458 '''Create a serializer.
459
460 Can be overriden by derived classes to inject their own serialzer.
461 '''
462
463 return ValueSerializer()
464
José Fonseca1b6c8752012-04-15 14:33:00 +0100465 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100466 self.api = api
467
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000468 self.header(api)
469
470 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000471 for module in api.modules:
472 for header in module.headers:
473 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000474 print
475
José Fonseca54f304a2012-01-14 19:33:08 +0000476 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000477 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000478 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000479 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000480 print
481
482 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100483 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000484
485 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100486 self.interface = None
487 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000488 for function in api.getAllFunctions():
489 self.traceFunctionDecl(function)
490 for function in api.getAllFunctions():
491 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000492 print
493
494 self.footer(api)
495
496 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100497 print '#ifdef _WIN32'
498 print '# include <malloc.h> // alloca'
499 print '# ifndef alloca'
500 print '# define alloca _alloca'
501 print '# endif'
502 print '#else'
503 print '# include <alloca.h> // alloca'
504 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100505 print
José Fonseca537c5072012-07-07 12:54:09 +0100506 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000507 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000508
509 def footer(self, api):
510 pass
511
José Fonseca54f304a2012-01-14 19:33:08 +0000512 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000513 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000514
José Fonseca84cea3b2012-05-09 21:12:30 +0100515 if not function.internal:
516 if function.args:
517 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
518 else:
519 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100520 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
José Fonseca84cea3b2012-05-09 21:12:30 +0100521 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000522
José Fonseca4b466a92012-11-26 19:47:26 +0000523 def getFunctionSigId(self):
524 id = Tracer.__id
525 Tracer.__id += 1
526 return id
527
José Fonseca54f304a2012-01-14 19:33:08 +0000528 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100529 return True
530
José Fonseca54f304a2012-01-14 19:33:08 +0000531 def traceFunctionImpl(self, function):
532 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100533 print 'extern "C" PUBLIC'
534 else:
535 print 'extern "C" PRIVATE'
536 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000537 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100538 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100539
José Fonseca54f304a2012-01-14 19:33:08 +0000540 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000541 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100542 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000543 print '}'
544 print
545
José Fonseca54f304a2012-01-14 19:33:08 +0000546 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100547 if not function.internal:
548 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
549 for arg in function.args:
550 if not arg.output:
551 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000552 for arg in function.args:
553 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100554 self.serializeArg(function, arg)
555 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000556 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100557 if not function.internal:
558 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000559 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100560 for arg in function.args:
561 if arg.output:
562 self.serializeArg(function, arg)
563 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000564 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100565 if function.type is not stdapi.Void:
566 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100567 if function.type is not stdapi.Void:
568 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000569 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000570
José Fonseca2cfa02c2013-06-10 08:05:29 +0100571 def invokeFunction(self, function):
572 self.doInvokeFunction(function)
573
574 def doInvokeFunction(self, function, prefix='_', suffix=''):
575 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000576 if function.type is stdapi.Void:
577 result = ''
578 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100579 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100580 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000581 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000582
José Fonseca4fb1ab02012-11-08 10:23:40 +0000583 def wasFunctionSuccessful(self, function):
584 if function.type is stdapi.Void:
585 return 'true'
586 if str(function.type) == 'HRESULT':
587 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000588 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000589
José Fonseca54f304a2012-01-14 19:33:08 +0000590 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100591 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000592 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100593 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000594
José Fonseca54f304a2012-01-14 19:33:08 +0000595 def serializeArgValue(self, function, arg):
596 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000597
José Fonseca54f304a2012-01-14 19:33:08 +0000598 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100599 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100600
601 from specs.winapi import REFIID
602 riid = None
603 for other_arg in function.args:
604 if not other_arg.output and other_arg.type is REFIID:
605 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100606 if riid is not None \
607 and isinstance(arg.type, stdapi.Pointer) \
608 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100609 self.wrapIid(function, riid, arg)
610 return
611
José Fonseca54f304a2012-01-14 19:33:08 +0000612 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000613
José Fonseca54f304a2012-01-14 19:33:08 +0000614 def unwrapArg(self, function, arg):
615 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000616
José Fonseca54f304a2012-01-14 19:33:08 +0000617 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100618 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000619 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100620 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000621
José Fonseca54f304a2012-01-14 19:33:08 +0000622 def serializeValue(self, type, instance):
623 serializer = self.serializerFactory()
624 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000625
José Fonseca54f304a2012-01-14 19:33:08 +0000626 def wrapRet(self, function, instance):
627 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000628
José Fonseca0075f152012-04-14 20:25:52 +0100629 def needsWrapping(self, type):
630 visitor = WrapDecider()
631 visitor.visit(type)
632 return visitor.needsWrapping
633
José Fonseca54f304a2012-01-14 19:33:08 +0000634 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100635 if self.needsWrapping(type):
636 visitor = ValueWrapper()
637 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000638
639 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100640 if self.needsWrapping(type):
641 visitor = ValueUnwrapper()
642 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000643
José Fonseca143e9252012-04-15 09:31:18 +0100644 def traceInterfaces(self, api):
645 interfaces = api.getAllInterfaces()
646 if not interfaces:
647 return
648 map(self.declareWrapperInterface, interfaces)
649 self.implementIidWrapper(api)
650 map(self.implementWrapperInterface, interfaces)
651 print
652
José Fonseca0423d2c2012-01-20 19:16:17 +0000653 def declareWrapperInterface(self, interface):
654 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
655 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000656 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000657 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
658 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000659 print "public:"
660 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000661 print
662 for method in interface.iterMethods():
663 print " " + method.prototype() + ";"
664 print
José Fonsecaacc90622012-05-02 13:10:07 +0100665 #print "private:"
666 for type, name, value in self.enumWrapperInterfaceVariables(interface):
667 print ' %s %s;' % (type, name)
José Fonseca14f9eea2012-11-23 15:33:40 +0000668 for i in range(64):
669 print r' virtual void _dummy%i(void) const {' % i
670 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
671 print r' os::abort();'
672 print r' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000673 print "};"
674 print
675
José Fonsecaacc90622012-05-02 13:10:07 +0100676 def enumWrapperInterfaceVariables(self, interface):
677 return [
678 ("DWORD", "m_dwMagic", "0xd8365d6c"),
679 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000680 ("void *", "m_pVtbl", "*(void **)pInstance"),
681 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100682 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000683
684 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100685 self.interface = interface
686
José Fonsecab7a9b182012-11-23 17:02:48 +0000687 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000688 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100689 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100690 if value is not None:
691 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000692 print '}'
693 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000694
695 # Public constructor
696 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
697 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
698 print r' if (it != g_WrappedObjects.end()) {'
699 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
700 print r' assert(pWrapper);'
701 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
702 print r' assert(pWrapper->m_pInstance == pInstance);'
703 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
704 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonseca4b466a92012-11-26 19:47:26 +0000705 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
José Fonsecab7a9b182012-11-23 17:02:48 +0000706 print r' return pWrapper;'
707 print r' }'
708 print r' }'
709 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonseca4b466a92012-11-26 19:47:26 +0000710 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000711 print r' g_WrappedObjects[pInstance] = pWrapper;'
712 print r' return pWrapper;'
713 print '}'
714 print
715
716 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000717 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca4b466a92012-11-26 19:47:26 +0000718 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000719 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000720 print '}'
721 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100722
José Fonseca4220b1b2012-02-03 19:05:29 +0000723 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100724 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000725 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100726
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000727 print
728
José Fonseca4220b1b2012-02-03 19:05:29 +0000729 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000730 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000731
732 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000733 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000734
José Fonseca0423d2c2012-01-20 19:16:17 +0000735 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100736 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000737
José Fonseca4220b1b2012-02-03 19:05:29 +0000738 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000739
740 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100741 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000742 print '}'
743 print
744
José Fonseca4220b1b2012-02-03 19:05:29 +0000745 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100746 assert not method.internal
747
José Fonseca632a78d2012-04-19 07:18:59 +0100748 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
José Fonseca69909e32013-05-04 11:10:33 +0100749 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
José Fonsecaa0e97862012-04-29 23:22:52 +0100750
751 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
752
José Fonseca632a78d2012-04-19 07:18:59 +0100753 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100754 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100755 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100756 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000757 for arg in method.args:
758 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000759 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000760 for arg in method.args:
761 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000762 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100763 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000764
José Fonseca4220b1b2012-02-03 19:05:29 +0000765 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000766
José Fonseca632a78d2012-04-19 07:18:59 +0100767 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000768
769 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000770 for arg in method.args:
771 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000772 self.serializeArg(method, arg)
773 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000774 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000775
José Fonseca87d1cc62010-11-29 15:57:25 +0000776 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100777 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100778 if method.type is not stdapi.Void:
779 self.wrapRet(method, '_result')
780
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000781 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000782 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000783 print r' if (!_result) {'
784 print r' delete this;'
785 print r' }'
786
787 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000788
José Fonseca143e9252012-04-15 09:31:18 +0100789 def implementIidWrapper(self, api):
790 print r'static void'
791 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
792 print r' os::log("apitrace: warning: %s: %s IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
793 print r' functionName, reason,'
794 print r' riid.Data1, riid.Data2, riid.Data3,'
795 print r' riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
796 print r'}'
797 print
798 print r'static void'
799 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
800 print r' if (!ppvObj || !*ppvObj) {'
801 print r' return;'
802 print r' }'
803 else_ = ''
804 for iface in api.getAllInterfaces():
805 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000806 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100807 print r' }'
808 else_ = 'else '
809 print r' %s{' % else_
810 print r' warnIID(functionName, riid, "unknown");'
811 print r' }'
812 print r'}'
813 print
814
José Fonsecabcb26b22012-04-15 08:42:25 +0100815 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100816 # Cast output arg to `void **` if necessary
817 out_name = out.name
818 obj_type = out.type.type.type
819 if not obj_type is stdapi.Void:
820 assert isinstance(obj_type, stdapi.Interface)
821 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
822
José Fonsecabcb26b22012-04-15 08:42:25 +0100823 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100824 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100825 else_ = ''
826 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100827 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100828 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100829 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100830 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100831 print r' }'
832 else_ = 'else '
833 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100834 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100835 print r' }'
836 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000837
José Fonseca4220b1b2012-02-03 19:05:29 +0000838 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000839 if method.type is stdapi.Void:
840 result = ''
841 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100842 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100843 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000844
José Fonseca6f0e3032014-06-25 01:00:35 +0100845 def emit_memcpy(self, ptr, size):
846 print ' trace::localWriter.fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100847
848 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100849 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100850 for arg, instance in zip(function.args, args):
851 assert not arg.output
852 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
853 self.serializeValue(arg.type, instance)
854 print ' trace::localWriter.endArg();'
855 print ' trace::localWriter.endEnter();'
856 print ' trace::localWriter.beginLeave(_fake_call);'
857 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000858