blob: adfc764bff3259df9d12cff8783a721e564f0acb [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
216 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200217 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
218 % {'c': count, 'array': instance, 'terminator': array.terminator}
219 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200220 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200221 for key, valueType in array.valueTypes:
222 if valueType is None:
223 print ' case %s:' % key
224 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
225 print ' break;'
226 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200227 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200228 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200229 print ' trace::localWriter.beginArray(%s);' % count
230
231 # for each key / key-value pair write the key and the value, if the key requires one
232
233 index = '_i' + array.keyType.tag
234 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200235 print ' trace::localWriter.beginElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200236 self.visitEnum(array.keyType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200237 print ' trace::localWriter.endElement();'
238 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
239 print ' break;'
240 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200241 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200242 # write generic value the usual way
243 for key, valueType in array.valueTypes:
244 if valueType is not None:
245 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200246 print ' trace::localWriter.beginElement();'
247 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
248 print ' trace::localWriter.endElement();'
249 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200250 # known key with no value, just decrease the index so we treat the next value as a key
251 if array.hasKeysWithoutValues:
252 for key, valueType in array.valueTypes:
253 if valueType is None:
254 print ' case %s:' % key
255 print ' %s--;' % index
256 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200257 # unknown key, write an int value
258 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200259 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200260 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200261 '__FUNCTION__, int(%(array)s[%(i)s]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200262 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200263 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200264 print ' break;'
265 print ' }'
266 print ' }'
267 print ' trace::localWriter.endArray();'
268
269
José Fonseca54f304a2012-01-14 19:33:08 +0000270 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000271 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000272
José Fonseca54f304a2012-01-14 19:33:08 +0000273 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100274 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000275
José Fonseca54f304a2012-01-14 19:33:08 +0000276 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100277 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000278
José Fonseca54f304a2012-01-14 19:33:08 +0000279 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100280 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100281 print ' trace::localWriter.beginArray(1);'
282 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000283 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100284 print ' trace::localWriter.endElement();'
285 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100286 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100287 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100288 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000289
José Fonseca59ee88e2012-01-15 14:24:10 +0000290 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100291 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000292
José Fonsecafbcf6832012-04-05 07:10:30 +0100293 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100294 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100295
José Fonseca59ee88e2012-01-15 14:24:10 +0000296 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100297 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000298
José Fonsecab89c5932012-04-01 22:47:11 +0200299 def visitReference(self, reference, instance):
300 self.visit(reference.type, instance)
301
José Fonseca54f304a2012-01-14 19:33:08 +0000302 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000303 self.visit(handle.type, instance)
304
José Fonseca54f304a2012-01-14 19:33:08 +0000305 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000306 self.visit(alias.type, instance)
307
José Fonseca54f304a2012-01-14 19:33:08 +0000308 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100309 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000310
José Fonseca54f304a2012-01-14 19:33:08 +0000311 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100312 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000313
José Fonseca54f304a2012-01-14 19:33:08 +0000314 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100315 if polymorphic.contextLess:
316 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
317 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000318 switchExpr = self.expand(polymorphic.switchExpr)
319 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100320 for cases, type in polymorphic.iterSwitch():
321 for case in cases:
322 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000323 caseInstance = instance
324 if type.expr is not None:
325 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
326 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100327 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000328 if polymorphic.defaultType is None:
329 print r' default:'
330 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
331 print r' trace::localWriter.writeNull();'
332 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100333 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100334
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000335
José Fonseca0075f152012-04-14 20:25:52 +0100336class WrapDecider(stdapi.Traverser):
337 '''Type visitor which will decide wheter this type will need wrapping or not.
338
339 For complex types (arrays, structures), we need to know this before hand.
340 '''
341
342 def __init__(self):
343 self.needsWrapping = False
344
José Fonseca0075f152012-04-14 20:25:52 +0100345 def visitLinearPointer(self, void):
346 pass
347
348 def visitInterface(self, interface):
349 self.needsWrapping = True
350
351
José Fonsecadbf714b2012-11-20 17:03:43 +0000352class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000353 '''Type visitor which will generate the code to wrap an instance.
354
355 Wrapping is necessary mostly for interfaces, however interface pointers can
356 appear anywhere inside complex types.
357 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000358
José Fonseca54f304a2012-01-14 19:33:08 +0000359 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000360 for member in struct.members:
361 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000362
José Fonseca54f304a2012-01-14 19:33:08 +0000363 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000364 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100365 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000366 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
367 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100368 print " }"
369 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000370
José Fonseca54f304a2012-01-14 19:33:08 +0000371 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100372 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000373 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100374 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000375
José Fonsecafbcf6832012-04-05 07:10:30 +0100376 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100377 elem_type = pointer.type.mutable()
378 if isinstance(elem_type, stdapi.Interface):
379 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100380 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
381 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100382 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100383 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100384
José Fonseca54f304a2012-01-14 19:33:08 +0000385 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100386 raise NotImplementedError
387
388 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100389 print " if (%s) {" % instance
José Fonsecab7a9b182012-11-23 17:02:48 +0000390 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100391 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100392
José Fonseca54f304a2012-01-14 19:33:08 +0000393 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100394 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100395 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000396
397
José Fonseca54f304a2012-01-14 19:33:08 +0000398class ValueUnwrapper(ValueWrapper):
399 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000400
José Fonseca0075f152012-04-14 20:25:52 +0100401 allocated = False
402
José Fonsecae7cb2b92012-09-28 08:40:24 +0100403 def visitStruct(self, struct, instance):
404 if not self.allocated:
405 # Argument is constant. We need to create a non const
406 print ' {'
407 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
408 print ' *_t = %s;' % (instance,)
409 assert instance.startswith('*')
410 print ' %s = _t;' % (instance[1:],)
411 instance = '*_t'
412 self.allocated = True
413 try:
414 return ValueWrapper.visitStruct(self, struct, instance)
415 finally:
416 print ' }'
417 else:
418 return ValueWrapper.visitStruct(self, struct, instance)
419
José Fonseca0075f152012-04-14 20:25:52 +0100420 def visitArray(self, array, instance):
421 if self.allocated or isinstance(instance, stdapi.Interface):
422 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000423 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100424 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000425 print " if (%s && %s) {" % (instance, array_length)
426 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
427 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100428 print " _t[_i] = %s[_i];" % instance
429 self.allocated = True
430 self.visit(array.type, "_t[_i]")
431 print " }"
432 print " %s = _t;" % instance
433 print " }"
434
José Fonseca9782b292012-04-14 22:02:42 +0100435 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000436 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100437 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000438 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
439 print r' %s = pWrapper->m_pInstance;' % (instance,)
440 print r' } else {'
441 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
442 print r' }'
443 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000444
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000445
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000446class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000447 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000448
José Fonseca4b466a92012-11-26 19:47:26 +0000449 # 0-3 are reserved to memcpy, malloc, free, and realloc
450 __id = 4
451
José Fonsecabb8760b2011-05-25 23:21:18 +0100452 def __init__(self):
453 self.api = None
454
José Fonseca54f304a2012-01-14 19:33:08 +0000455 def serializerFactory(self):
456 '''Create a serializer.
457
458 Can be overriden by derived classes to inject their own serialzer.
459 '''
460
461 return ValueSerializer()
462
José Fonseca1b6c8752012-04-15 14:33:00 +0100463 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100464 self.api = api
465
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000466 self.header(api)
467
468 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000469 for module in api.modules:
470 for header in module.headers:
471 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000472 print
473
José Fonseca54f304a2012-01-14 19:33:08 +0000474 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000475 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000476 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000477 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000478 print
479
480 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100481 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000482
483 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100484 self.interface = None
485 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000486 for function in api.getAllFunctions():
487 self.traceFunctionDecl(function)
488 for function in api.getAllFunctions():
489 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000490 print
491
492 self.footer(api)
493
494 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100495 print '#ifdef _WIN32'
496 print '# include <malloc.h> // alloca'
497 print '# ifndef alloca'
498 print '# define alloca _alloca'
499 print '# endif'
500 print '#else'
501 print '# include <alloca.h> // alloca'
502 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100503 print
504 print '#include "trace.hpp"'
505 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000506 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000507
508 def footer(self, api):
509 pass
510
José Fonseca54f304a2012-01-14 19:33:08 +0000511 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000512 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000513
José Fonseca84cea3b2012-05-09 21:12:30 +0100514 if not function.internal:
515 if function.args:
516 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
517 else:
518 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100519 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 +0100520 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000521
José Fonseca4b466a92012-11-26 19:47:26 +0000522 def getFunctionSigId(self):
523 id = Tracer.__id
524 Tracer.__id += 1
525 return id
526
José Fonseca54f304a2012-01-14 19:33:08 +0000527 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100528 return True
529
José Fonseca54f304a2012-01-14 19:33:08 +0000530 def traceFunctionImpl(self, function):
531 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100532 print 'extern "C" PUBLIC'
533 else:
534 print 'extern "C" PRIVATE'
535 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000536 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100537 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100538
539 # No-op if tracing is disabled
540 print ' if (!trace::isTracingEnabled()) {'
José Fonseca2cfa02c2013-06-10 08:05:29 +0100541 self.doInvokeFunction(function)
Imre Deak1242ab52012-03-30 15:46:26 +0300542 if function.type is not stdapi.Void:
543 print ' return _result;'
544 else:
545 print ' return;'
546 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100547
José Fonseca54f304a2012-01-14 19:33:08 +0000548 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000549 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100550 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000551 print '}'
552 print
553
José Fonseca54f304a2012-01-14 19:33:08 +0000554 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100555 if not function.internal:
556 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
557 for arg in function.args:
558 if not arg.output:
559 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000560 for arg in function.args:
561 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100562 self.serializeArg(function, arg)
563 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000564 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100565 if not function.internal:
566 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000567 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100568 for arg in function.args:
569 if arg.output:
570 self.serializeArg(function, arg)
571 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000572 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100573 if function.type is not stdapi.Void:
574 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100575 if function.type is not stdapi.Void:
576 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000577 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000578
José Fonseca2cfa02c2013-06-10 08:05:29 +0100579 def invokeFunction(self, function):
580 self.doInvokeFunction(function)
581
582 def doInvokeFunction(self, function, prefix='_', suffix=''):
583 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000584 if function.type is stdapi.Void:
585 result = ''
586 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100587 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100588 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000589 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000590
José Fonseca4fb1ab02012-11-08 10:23:40 +0000591 def wasFunctionSuccessful(self, function):
592 if function.type is stdapi.Void:
593 return 'true'
594 if str(function.type) == 'HRESULT':
595 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000596 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000597
José Fonseca54f304a2012-01-14 19:33:08 +0000598 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100599 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000600 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100601 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000602
José Fonseca54f304a2012-01-14 19:33:08 +0000603 def serializeArgValue(self, function, arg):
604 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000605
José Fonseca54f304a2012-01-14 19:33:08 +0000606 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100607 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100608
609 from specs.winapi import REFIID
610 riid = None
611 for other_arg in function.args:
612 if not other_arg.output and other_arg.type is REFIID:
613 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100614 if riid is not None \
615 and isinstance(arg.type, stdapi.Pointer) \
616 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100617 self.wrapIid(function, riid, arg)
618 return
619
José Fonseca54f304a2012-01-14 19:33:08 +0000620 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000621
José Fonseca54f304a2012-01-14 19:33:08 +0000622 def unwrapArg(self, function, arg):
623 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000624
José Fonseca54f304a2012-01-14 19:33:08 +0000625 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100626 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000627 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100628 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000629
José Fonseca54f304a2012-01-14 19:33:08 +0000630 def serializeValue(self, type, instance):
631 serializer = self.serializerFactory()
632 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000633
José Fonseca54f304a2012-01-14 19:33:08 +0000634 def wrapRet(self, function, instance):
635 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000636
José Fonseca0075f152012-04-14 20:25:52 +0100637 def needsWrapping(self, type):
638 visitor = WrapDecider()
639 visitor.visit(type)
640 return visitor.needsWrapping
641
José Fonseca54f304a2012-01-14 19:33:08 +0000642 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100643 if self.needsWrapping(type):
644 visitor = ValueWrapper()
645 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000646
647 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100648 if self.needsWrapping(type):
649 visitor = ValueUnwrapper()
650 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000651
José Fonseca143e9252012-04-15 09:31:18 +0100652 def traceInterfaces(self, api):
653 interfaces = api.getAllInterfaces()
654 if not interfaces:
655 return
656 map(self.declareWrapperInterface, interfaces)
657 self.implementIidWrapper(api)
658 map(self.implementWrapperInterface, interfaces)
659 print
660
José Fonseca0423d2c2012-01-20 19:16:17 +0000661 def declareWrapperInterface(self, interface):
662 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
663 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000664 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000665 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
666 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000667 print "public:"
668 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000669 print
670 for method in interface.iterMethods():
671 print " " + method.prototype() + ";"
672 print
José Fonsecaacc90622012-05-02 13:10:07 +0100673 #print "private:"
674 for type, name, value in self.enumWrapperInterfaceVariables(interface):
675 print ' %s %s;' % (type, name)
José Fonseca14f9eea2012-11-23 15:33:40 +0000676 for i in range(64):
677 print r' virtual void _dummy%i(void) const {' % i
678 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
679 print r' os::abort();'
680 print r' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000681 print "};"
682 print
683
José Fonsecaacc90622012-05-02 13:10:07 +0100684 def enumWrapperInterfaceVariables(self, interface):
685 return [
686 ("DWORD", "m_dwMagic", "0xd8365d6c"),
687 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000688 ("void *", "m_pVtbl", "*(void **)pInstance"),
689 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100690 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000691
692 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100693 self.interface = interface
694
José Fonsecab7a9b182012-11-23 17:02:48 +0000695 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000696 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100697 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100698 if value is not None:
699 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000700 print '}'
701 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000702
703 # Public constructor
704 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
705 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
706 print r' if (it != g_WrappedObjects.end()) {'
707 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
708 print r' assert(pWrapper);'
709 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
710 print r' assert(pWrapper->m_pInstance == pInstance);'
711 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
712 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonseca4b466a92012-11-26 19:47:26 +0000713 #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 +0000714 print r' return pWrapper;'
715 print r' }'
716 print r' }'
717 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonseca4b466a92012-11-26 19:47:26 +0000718 #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 +0000719 print r' g_WrappedObjects[pInstance] = pWrapper;'
720 print r' return pWrapper;'
721 print '}'
722 print
723
724 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000725 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca4b466a92012-11-26 19:47:26 +0000726 #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 +0000727 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000728 print '}'
729 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100730
José Fonseca4220b1b2012-02-03 19:05:29 +0000731 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100732 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000733 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100734
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000735 print
736
José Fonseca4220b1b2012-02-03 19:05:29 +0000737 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000738 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000739
740 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000741 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000742
José Fonseca0423d2c2012-01-20 19:16:17 +0000743 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100744 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000745
José Fonseca4220b1b2012-02-03 19:05:29 +0000746 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000747
748 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100749 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000750 print '}'
751 print
752
José Fonseca4220b1b2012-02-03 19:05:29 +0000753 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100754 assert not method.internal
755
José Fonseca632a78d2012-04-19 07:18:59 +0100756 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 +0100757 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 +0100758
759 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
760
José Fonseca632a78d2012-04-19 07:18:59 +0100761 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100762 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100763 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100764 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000765 for arg in method.args:
766 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000767 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000768 for arg in method.args:
769 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000770 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100771 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000772
José Fonseca4220b1b2012-02-03 19:05:29 +0000773 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000774
José Fonseca632a78d2012-04-19 07:18:59 +0100775 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000776
777 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000778 for arg in method.args:
779 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000780 self.serializeArg(method, arg)
781 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000782 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000783
José Fonseca87d1cc62010-11-29 15:57:25 +0000784 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100785 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100786 if method.type is not stdapi.Void:
787 self.wrapRet(method, '_result')
788
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000789 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000790 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000791 print r' if (!_result) {'
792 print r' delete this;'
793 print r' }'
794
795 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000796
José Fonseca143e9252012-04-15 09:31:18 +0100797 def implementIidWrapper(self, api):
798 print r'static void'
799 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
800 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",'
801 print r' functionName, reason,'
802 print r' riid.Data1, riid.Data2, riid.Data3,'
803 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]);'
804 print r'}'
805 print
806 print r'static void'
807 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
808 print r' if (!ppvObj || !*ppvObj) {'
809 print r' return;'
810 print r' }'
811 else_ = ''
812 for iface in api.getAllInterfaces():
813 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000814 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100815 print r' }'
816 else_ = 'else '
817 print r' %s{' % else_
818 print r' warnIID(functionName, riid, "unknown");'
819 print r' }'
820 print r'}'
821 print
822
José Fonsecabcb26b22012-04-15 08:42:25 +0100823 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100824 # Cast output arg to `void **` if necessary
825 out_name = out.name
826 obj_type = out.type.type.type
827 if not obj_type is stdapi.Void:
828 assert isinstance(obj_type, stdapi.Interface)
829 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
830
José Fonsecabcb26b22012-04-15 08:42:25 +0100831 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100832 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100833 else_ = ''
834 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100835 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100836 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100837 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100838 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100839 print r' }'
840 else_ = 'else '
841 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100842 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100843 print r' }'
844 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000845
José Fonseca4220b1b2012-02-03 19:05:29 +0000846 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000847 if method.type is stdapi.Void:
848 result = ''
849 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100850 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100851 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000852
853 def emit_memcpy(self, dest, src, length):
José Fonseca69909e32013-05-04 11:10:33 +0100854 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000855 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100856 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000857 print ' trace::localWriter.endArg();'
858 print ' trace::localWriter.beginArg(1);'
859 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
860 print ' trace::localWriter.endArg();'
861 print ' trace::localWriter.beginArg(2);'
862 print ' trace::localWriter.writeUInt(%s);' % length
863 print ' trace::localWriter.endArg();'
864 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100865 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000866 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100867
868 def fake_call(self, function, args):
869 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
870 for arg, instance in zip(function.args, args):
871 assert not arg.output
872 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
873 self.serializeValue(arg.type, instance)
874 print ' trace::localWriter.endArg();'
875 print ' trace::localWriter.endEnter();'
876 print ' trace::localWriter.beginLeave(_fake_call);'
877 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000878