blob: 10f71a4dc7a32362dfafe3d96d68705ed3578db8 [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
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200215 count = '_c' + array.keyType.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
234 index = '_i' + array.keyType.tag
235 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();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200237 self.visitEnum(array.keyType, "%(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", ' + \
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200262 '__FUNCTION__, int(%(array)s[%(i)s]));' % {'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
506 print '#include "trace.hpp"'
507 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000508 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000509
510 def footer(self, api):
511 pass
512
José Fonseca54f304a2012-01-14 19:33:08 +0000513 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000514 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000515
José Fonseca84cea3b2012-05-09 21:12:30 +0100516 if not function.internal:
517 if function.args:
518 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
519 else:
520 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100521 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 +0100522 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000523
José Fonseca4b466a92012-11-26 19:47:26 +0000524 def getFunctionSigId(self):
525 id = Tracer.__id
526 Tracer.__id += 1
527 return id
528
José Fonseca54f304a2012-01-14 19:33:08 +0000529 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100530 return True
531
José Fonseca54f304a2012-01-14 19:33:08 +0000532 def traceFunctionImpl(self, function):
533 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100534 print 'extern "C" PUBLIC'
535 else:
536 print 'extern "C" PRIVATE'
537 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000538 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100539 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100540
541 # No-op if tracing is disabled
542 print ' if (!trace::isTracingEnabled()) {'
José Fonseca2cfa02c2013-06-10 08:05:29 +0100543 self.doInvokeFunction(function)
Imre Deak1242ab52012-03-30 15:46:26 +0300544 if function.type is not stdapi.Void:
545 print ' return _result;'
546 else:
547 print ' return;'
548 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100549
José Fonseca54f304a2012-01-14 19:33:08 +0000550 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000551 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100552 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000553 print '}'
554 print
555
José Fonseca54f304a2012-01-14 19:33:08 +0000556 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100557 if not function.internal:
558 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
559 for arg in function.args:
560 if not arg.output:
561 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000562 for arg in function.args:
563 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100564 self.serializeArg(function, arg)
565 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000566 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100567 if not function.internal:
568 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000569 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100570 for arg in function.args:
571 if arg.output:
572 self.serializeArg(function, arg)
573 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000574 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100575 if function.type is not stdapi.Void:
576 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100577 if function.type is not stdapi.Void:
578 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000579 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000580
José Fonseca2cfa02c2013-06-10 08:05:29 +0100581 def invokeFunction(self, function):
582 self.doInvokeFunction(function)
583
584 def doInvokeFunction(self, function, prefix='_', suffix=''):
585 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000586 if function.type is stdapi.Void:
587 result = ''
588 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100589 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100590 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000591 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000592
José Fonseca4fb1ab02012-11-08 10:23:40 +0000593 def wasFunctionSuccessful(self, function):
594 if function.type is stdapi.Void:
595 return 'true'
596 if str(function.type) == 'HRESULT':
597 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000598 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000599
José Fonseca54f304a2012-01-14 19:33:08 +0000600 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100601 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000602 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100603 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000604
José Fonseca54f304a2012-01-14 19:33:08 +0000605 def serializeArgValue(self, function, arg):
606 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000607
José Fonseca54f304a2012-01-14 19:33:08 +0000608 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100609 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100610
611 from specs.winapi import REFIID
612 riid = None
613 for other_arg in function.args:
614 if not other_arg.output and other_arg.type is REFIID:
615 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100616 if riid is not None \
617 and isinstance(arg.type, stdapi.Pointer) \
618 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100619 self.wrapIid(function, riid, arg)
620 return
621
José Fonseca54f304a2012-01-14 19:33:08 +0000622 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000623
José Fonseca54f304a2012-01-14 19:33:08 +0000624 def unwrapArg(self, function, arg):
625 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000626
José Fonseca54f304a2012-01-14 19:33:08 +0000627 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100628 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000629 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100630 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000631
José Fonseca54f304a2012-01-14 19:33:08 +0000632 def serializeValue(self, type, instance):
633 serializer = self.serializerFactory()
634 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000635
José Fonseca54f304a2012-01-14 19:33:08 +0000636 def wrapRet(self, function, instance):
637 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000638
José Fonseca0075f152012-04-14 20:25:52 +0100639 def needsWrapping(self, type):
640 visitor = WrapDecider()
641 visitor.visit(type)
642 return visitor.needsWrapping
643
José Fonseca54f304a2012-01-14 19:33:08 +0000644 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100645 if self.needsWrapping(type):
646 visitor = ValueWrapper()
647 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000648
649 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100650 if self.needsWrapping(type):
651 visitor = ValueUnwrapper()
652 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000653
José Fonseca143e9252012-04-15 09:31:18 +0100654 def traceInterfaces(self, api):
655 interfaces = api.getAllInterfaces()
656 if not interfaces:
657 return
658 map(self.declareWrapperInterface, interfaces)
659 self.implementIidWrapper(api)
660 map(self.implementWrapperInterface, interfaces)
661 print
662
José Fonseca0423d2c2012-01-20 19:16:17 +0000663 def declareWrapperInterface(self, interface):
664 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
665 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000666 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000667 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
668 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000669 print "public:"
670 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000671 print
672 for method in interface.iterMethods():
673 print " " + method.prototype() + ";"
674 print
José Fonsecaacc90622012-05-02 13:10:07 +0100675 #print "private:"
676 for type, name, value in self.enumWrapperInterfaceVariables(interface):
677 print ' %s %s;' % (type, name)
José Fonseca14f9eea2012-11-23 15:33:40 +0000678 for i in range(64):
679 print r' virtual void _dummy%i(void) const {' % i
680 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
681 print r' os::abort();'
682 print r' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000683 print "};"
684 print
685
José Fonsecaacc90622012-05-02 13:10:07 +0100686 def enumWrapperInterfaceVariables(self, interface):
687 return [
688 ("DWORD", "m_dwMagic", "0xd8365d6c"),
689 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000690 ("void *", "m_pVtbl", "*(void **)pInstance"),
691 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100692 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000693
694 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100695 self.interface = interface
696
José Fonsecab7a9b182012-11-23 17:02:48 +0000697 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000698 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100699 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100700 if value is not None:
701 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000702 print '}'
703 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000704
705 # Public constructor
706 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
707 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
708 print r' if (it != g_WrappedObjects.end()) {'
709 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
710 print r' assert(pWrapper);'
711 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
712 print r' assert(pWrapper->m_pInstance == pInstance);'
713 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
714 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonseca4b466a92012-11-26 19:47:26 +0000715 #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 +0000716 print r' return pWrapper;'
717 print r' }'
718 print r' }'
719 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonseca4b466a92012-11-26 19:47:26 +0000720 #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 +0000721 print r' g_WrappedObjects[pInstance] = pWrapper;'
722 print r' return pWrapper;'
723 print '}'
724 print
725
726 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000727 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca4b466a92012-11-26 19:47:26 +0000728 #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 +0000729 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000730 print '}'
731 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100732
José Fonseca4220b1b2012-02-03 19:05:29 +0000733 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100734 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000735 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100736
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000737 print
738
José Fonseca4220b1b2012-02-03 19:05:29 +0000739 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000740 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000741
742 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000743 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000744
José Fonseca0423d2c2012-01-20 19:16:17 +0000745 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100746 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000747
José Fonseca4220b1b2012-02-03 19:05:29 +0000748 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000749
750 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100751 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000752 print '}'
753 print
754
José Fonseca4220b1b2012-02-03 19:05:29 +0000755 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100756 assert not method.internal
757
José Fonseca632a78d2012-04-19 07:18:59 +0100758 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 +0100759 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 +0100760
761 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
762
José Fonseca632a78d2012-04-19 07:18:59 +0100763 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100764 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100765 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100766 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000767 for arg in method.args:
768 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000769 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000770 for arg in method.args:
771 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000772 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100773 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000774
José Fonseca4220b1b2012-02-03 19:05:29 +0000775 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000776
José Fonseca632a78d2012-04-19 07:18:59 +0100777 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000778
779 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000780 for arg in method.args:
781 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000782 self.serializeArg(method, arg)
783 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000784 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000785
José Fonseca87d1cc62010-11-29 15:57:25 +0000786 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100787 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100788 if method.type is not stdapi.Void:
789 self.wrapRet(method, '_result')
790
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000791 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000792 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000793 print r' if (!_result) {'
794 print r' delete this;'
795 print r' }'
796
797 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000798
José Fonseca143e9252012-04-15 09:31:18 +0100799 def implementIidWrapper(self, api):
800 print r'static void'
801 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
802 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",'
803 print r' functionName, reason,'
804 print r' riid.Data1, riid.Data2, riid.Data3,'
805 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]);'
806 print r'}'
807 print
808 print r'static void'
809 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
810 print r' if (!ppvObj || !*ppvObj) {'
811 print r' return;'
812 print r' }'
813 else_ = ''
814 for iface in api.getAllInterfaces():
815 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000816 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100817 print r' }'
818 else_ = 'else '
819 print r' %s{' % else_
820 print r' warnIID(functionName, riid, "unknown");'
821 print r' }'
822 print r'}'
823 print
824
José Fonsecabcb26b22012-04-15 08:42:25 +0100825 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100826 # Cast output arg to `void **` if necessary
827 out_name = out.name
828 obj_type = out.type.type.type
829 if not obj_type is stdapi.Void:
830 assert isinstance(obj_type, stdapi.Interface)
831 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
832
José Fonsecabcb26b22012-04-15 08:42:25 +0100833 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100834 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100835 else_ = ''
836 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100837 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100838 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100839 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100840 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100841 print r' }'
842 else_ = 'else '
843 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100844 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100845 print r' }'
846 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000847
José Fonseca4220b1b2012-02-03 19:05:29 +0000848 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000849 if method.type is stdapi.Void:
850 result = ''
851 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100852 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100853 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000854
855 def emit_memcpy(self, dest, src, length):
José Fonseca69909e32013-05-04 11:10:33 +0100856 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000857 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100858 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000859 print ' trace::localWriter.endArg();'
860 print ' trace::localWriter.beginArg(1);'
861 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
862 print ' trace::localWriter.endArg();'
863 print ' trace::localWriter.beginArg(2);'
864 print ' trace::localWriter.writeUInt(%s);' % length
865 print ' trace::localWriter.endArg();'
866 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100867 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000868 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100869
870 def fake_call(self, function, args):
871 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
872 for arg, instance in zip(function.args, args):
873 assert not arg.output
874 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
875 self.serializeValue(arg.type, instance)
876 print ' trace::localWriter.endArg();'
877 print ' trace::localWriter.endEnter();'
878 print ' trace::localWriter.beginLeave(_fake_call);'
879 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000880