blob: 0d7741eb391e55ef5c6d51ef0429d7b206ef8ae3 [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:
220 print ' switch (%(array)s[%(c)s]) {' % {'array': instance, 'c': count}
221 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 ' }'
241 print ' switch (%(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();'
260 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
261 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200262 print ' break;'
263 print ' }'
264 print ' }'
265 print ' trace::localWriter.endArray();'
266
267
José Fonseca54f304a2012-01-14 19:33:08 +0000268 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000269 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000270
José Fonseca54f304a2012-01-14 19:33:08 +0000271 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100272 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000273
José Fonseca54f304a2012-01-14 19:33:08 +0000274 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100275 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000276
José Fonseca54f304a2012-01-14 19:33:08 +0000277 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100278 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100279 print ' trace::localWriter.beginArray(1);'
280 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000281 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100282 print ' trace::localWriter.endElement();'
283 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100284 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100285 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100286 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000287
José Fonseca59ee88e2012-01-15 14:24:10 +0000288 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100289 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000290
José Fonsecafbcf6832012-04-05 07:10:30 +0100291 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100292 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100293
José Fonseca59ee88e2012-01-15 14:24:10 +0000294 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100295 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000296
José Fonsecab89c5932012-04-01 22:47:11 +0200297 def visitReference(self, reference, instance):
298 self.visit(reference.type, instance)
299
José Fonseca54f304a2012-01-14 19:33:08 +0000300 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000301 self.visit(handle.type, instance)
302
José Fonseca54f304a2012-01-14 19:33:08 +0000303 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000304 self.visit(alias.type, instance)
305
José Fonseca54f304a2012-01-14 19:33:08 +0000306 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100307 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000308
José Fonseca54f304a2012-01-14 19:33:08 +0000309 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100310 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000311
José Fonseca54f304a2012-01-14 19:33:08 +0000312 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100313 if polymorphic.contextLess:
314 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
315 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000316 switchExpr = self.expand(polymorphic.switchExpr)
317 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100318 for cases, type in polymorphic.iterSwitch():
319 for case in cases:
320 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000321 caseInstance = instance
322 if type.expr is not None:
323 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
324 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100325 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000326 if polymorphic.defaultType is None:
327 print r' default:'
328 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
329 print r' trace::localWriter.writeNull();'
330 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100331 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100332
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000333
José Fonseca0075f152012-04-14 20:25:52 +0100334class WrapDecider(stdapi.Traverser):
335 '''Type visitor which will decide wheter this type will need wrapping or not.
336
337 For complex types (arrays, structures), we need to know this before hand.
338 '''
339
340 def __init__(self):
341 self.needsWrapping = False
342
José Fonseca0075f152012-04-14 20:25:52 +0100343 def visitLinearPointer(self, void):
344 pass
345
346 def visitInterface(self, interface):
347 self.needsWrapping = True
348
349
José Fonsecadbf714b2012-11-20 17:03:43 +0000350class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000351 '''Type visitor which will generate the code to wrap an instance.
352
353 Wrapping is necessary mostly for interfaces, however interface pointers can
354 appear anywhere inside complex types.
355 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000356
José Fonseca54f304a2012-01-14 19:33:08 +0000357 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000358 for member in struct.members:
359 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000360
José Fonseca54f304a2012-01-14 19:33:08 +0000361 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000362 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100363 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000364 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
365 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100366 print " }"
367 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000368
José Fonseca54f304a2012-01-14 19:33:08 +0000369 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100370 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000371 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100372 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000373
José Fonsecafbcf6832012-04-05 07:10:30 +0100374 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100375 elem_type = pointer.type.mutable()
376 if isinstance(elem_type, stdapi.Interface):
377 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100378 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
379 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100380 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100381 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100382
José Fonseca54f304a2012-01-14 19:33:08 +0000383 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100384 raise NotImplementedError
385
386 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100387 print " if (%s) {" % instance
José Fonsecab7a9b182012-11-23 17:02:48 +0000388 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100389 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100390
José Fonseca54f304a2012-01-14 19:33:08 +0000391 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100392 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100393 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000394
395
José Fonseca54f304a2012-01-14 19:33:08 +0000396class ValueUnwrapper(ValueWrapper):
397 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000398
José Fonseca0075f152012-04-14 20:25:52 +0100399 allocated = False
400
José Fonsecae7cb2b92012-09-28 08:40:24 +0100401 def visitStruct(self, struct, instance):
402 if not self.allocated:
403 # Argument is constant. We need to create a non const
404 print ' {'
405 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
406 print ' *_t = %s;' % (instance,)
407 assert instance.startswith('*')
408 print ' %s = _t;' % (instance[1:],)
409 instance = '*_t'
410 self.allocated = True
411 try:
412 return ValueWrapper.visitStruct(self, struct, instance)
413 finally:
414 print ' }'
415 else:
416 return ValueWrapper.visitStruct(self, struct, instance)
417
José Fonseca0075f152012-04-14 20:25:52 +0100418 def visitArray(self, array, instance):
419 if self.allocated or isinstance(instance, stdapi.Interface):
420 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000421 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100422 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000423 print " if (%s && %s) {" % (instance, array_length)
424 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
425 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100426 print " _t[_i] = %s[_i];" % instance
427 self.allocated = True
428 self.visit(array.type, "_t[_i]")
429 print " }"
430 print " %s = _t;" % instance
431 print " }"
432
José Fonseca9782b292012-04-14 22:02:42 +0100433 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000434 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100435 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000436 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
437 print r' %s = pWrapper->m_pInstance;' % (instance,)
438 print r' } else {'
439 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
440 print r' }'
441 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000442
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000443
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000444class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000445 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000446
José Fonseca4b466a92012-11-26 19:47:26 +0000447 # 0-3 are reserved to memcpy, malloc, free, and realloc
448 __id = 4
449
José Fonsecabb8760b2011-05-25 23:21:18 +0100450 def __init__(self):
451 self.api = None
452
José Fonseca54f304a2012-01-14 19:33:08 +0000453 def serializerFactory(self):
454 '''Create a serializer.
455
456 Can be overriden by derived classes to inject their own serialzer.
457 '''
458
459 return ValueSerializer()
460
José Fonseca1b6c8752012-04-15 14:33:00 +0100461 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100462 self.api = api
463
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000464 self.header(api)
465
466 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000467 for module in api.modules:
468 for header in module.headers:
469 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000470 print
471
José Fonseca54f304a2012-01-14 19:33:08 +0000472 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000473 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000474 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000475 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000476 print
477
478 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100479 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000480
481 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100482 self.interface = None
483 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000484 for function in api.getAllFunctions():
485 self.traceFunctionDecl(function)
486 for function in api.getAllFunctions():
487 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000488 print
489
490 self.footer(api)
491
492 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100493 print '#ifdef _WIN32'
494 print '# include <malloc.h> // alloca'
495 print '# ifndef alloca'
496 print '# define alloca _alloca'
497 print '# endif'
498 print '#else'
499 print '# include <alloca.h> // alloca'
500 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100501 print
502 print '#include "trace.hpp"'
503 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000504 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000505
506 def footer(self, api):
507 pass
508
José Fonseca54f304a2012-01-14 19:33:08 +0000509 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000510 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000511
José Fonseca84cea3b2012-05-09 21:12:30 +0100512 if not function.internal:
513 if function.args:
514 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
515 else:
516 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100517 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 +0100518 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000519
José Fonseca4b466a92012-11-26 19:47:26 +0000520 def getFunctionSigId(self):
521 id = Tracer.__id
522 Tracer.__id += 1
523 return id
524
José Fonseca54f304a2012-01-14 19:33:08 +0000525 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100526 return True
527
José Fonseca54f304a2012-01-14 19:33:08 +0000528 def traceFunctionImpl(self, function):
529 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100530 print 'extern "C" PUBLIC'
531 else:
532 print 'extern "C" PRIVATE'
533 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000534 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100535 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100536
537 # No-op if tracing is disabled
538 print ' if (!trace::isTracingEnabled()) {'
José Fonseca2cfa02c2013-06-10 08:05:29 +0100539 self.doInvokeFunction(function)
Imre Deak1242ab52012-03-30 15:46:26 +0300540 if function.type is not stdapi.Void:
541 print ' return _result;'
542 else:
543 print ' return;'
544 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100545
José Fonseca54f304a2012-01-14 19:33:08 +0000546 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000547 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100548 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000549 print '}'
550 print
551
José Fonseca54f304a2012-01-14 19:33:08 +0000552 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100553 if not function.internal:
554 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
555 for arg in function.args:
556 if not arg.output:
557 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000558 for arg in function.args:
559 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100560 self.serializeArg(function, arg)
561 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000562 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100563 if not function.internal:
564 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000565 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100566 for arg in function.args:
567 if arg.output:
568 self.serializeArg(function, arg)
569 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000570 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100571 if function.type is not stdapi.Void:
572 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100573 if function.type is not stdapi.Void:
574 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000575 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000576
José Fonseca2cfa02c2013-06-10 08:05:29 +0100577 def invokeFunction(self, function):
578 self.doInvokeFunction(function)
579
580 def doInvokeFunction(self, function, prefix='_', suffix=''):
581 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000582 if function.type is stdapi.Void:
583 result = ''
584 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100585 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100586 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000587 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000588
José Fonseca4fb1ab02012-11-08 10:23:40 +0000589 def wasFunctionSuccessful(self, function):
590 if function.type is stdapi.Void:
591 return 'true'
592 if str(function.type) == 'HRESULT':
593 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000594 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000595
José Fonseca54f304a2012-01-14 19:33:08 +0000596 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100597 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000598 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100599 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000600
José Fonseca54f304a2012-01-14 19:33:08 +0000601 def serializeArgValue(self, function, arg):
602 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000603
José Fonseca54f304a2012-01-14 19:33:08 +0000604 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100605 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100606
607 from specs.winapi import REFIID
608 riid = None
609 for other_arg in function.args:
610 if not other_arg.output and other_arg.type is REFIID:
611 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100612 if riid is not None \
613 and isinstance(arg.type, stdapi.Pointer) \
614 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100615 self.wrapIid(function, riid, arg)
616 return
617
José Fonseca54f304a2012-01-14 19:33:08 +0000618 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000619
José Fonseca54f304a2012-01-14 19:33:08 +0000620 def unwrapArg(self, function, arg):
621 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000622
José Fonseca54f304a2012-01-14 19:33:08 +0000623 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100624 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000625 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100626 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca54f304a2012-01-14 19:33:08 +0000628 def serializeValue(self, type, instance):
629 serializer = self.serializerFactory()
630 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000631
José Fonseca54f304a2012-01-14 19:33:08 +0000632 def wrapRet(self, function, instance):
633 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000634
José Fonseca0075f152012-04-14 20:25:52 +0100635 def needsWrapping(self, type):
636 visitor = WrapDecider()
637 visitor.visit(type)
638 return visitor.needsWrapping
639
José Fonseca54f304a2012-01-14 19:33:08 +0000640 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100641 if self.needsWrapping(type):
642 visitor = ValueWrapper()
643 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000644
645 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100646 if self.needsWrapping(type):
647 visitor = ValueUnwrapper()
648 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000649
José Fonseca143e9252012-04-15 09:31:18 +0100650 def traceInterfaces(self, api):
651 interfaces = api.getAllInterfaces()
652 if not interfaces:
653 return
654 map(self.declareWrapperInterface, interfaces)
655 self.implementIidWrapper(api)
656 map(self.implementWrapperInterface, interfaces)
657 print
658
José Fonseca0423d2c2012-01-20 19:16:17 +0000659 def declareWrapperInterface(self, interface):
660 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
661 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000662 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000663 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
664 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000665 print "public:"
666 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000667 print
668 for method in interface.iterMethods():
669 print " " + method.prototype() + ";"
670 print
José Fonsecaacc90622012-05-02 13:10:07 +0100671 #print "private:"
672 for type, name, value in self.enumWrapperInterfaceVariables(interface):
673 print ' %s %s;' % (type, name)
José Fonseca14f9eea2012-11-23 15:33:40 +0000674 for i in range(64):
675 print r' virtual void _dummy%i(void) const {' % i
676 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
677 print r' os::abort();'
678 print r' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000679 print "};"
680 print
681
José Fonsecaacc90622012-05-02 13:10:07 +0100682 def enumWrapperInterfaceVariables(self, interface):
683 return [
684 ("DWORD", "m_dwMagic", "0xd8365d6c"),
685 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000686 ("void *", "m_pVtbl", "*(void **)pInstance"),
687 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100688 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000689
690 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100691 self.interface = interface
692
José Fonsecab7a9b182012-11-23 17:02:48 +0000693 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000694 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100695 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100696 if value is not None:
697 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000698 print '}'
699 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000700
701 # Public constructor
702 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
703 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
704 print r' if (it != g_WrappedObjects.end()) {'
705 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
706 print r' assert(pWrapper);'
707 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
708 print r' assert(pWrapper->m_pInstance == pInstance);'
709 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
710 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonseca4b466a92012-11-26 19:47:26 +0000711 #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 +0000712 print r' return pWrapper;'
713 print r' }'
714 print r' }'
715 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonseca4b466a92012-11-26 19:47:26 +0000716 #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 +0000717 print r' g_WrappedObjects[pInstance] = pWrapper;'
718 print r' return pWrapper;'
719 print '}'
720 print
721
722 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000723 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca4b466a92012-11-26 19:47:26 +0000724 #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 +0000725 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000726 print '}'
727 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100728
José Fonseca4220b1b2012-02-03 19:05:29 +0000729 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100730 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000731 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100732
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000733 print
734
José Fonseca4220b1b2012-02-03 19:05:29 +0000735 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000736 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000737
738 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000739 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000740
José Fonseca0423d2c2012-01-20 19:16:17 +0000741 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100742 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000743
José Fonseca4220b1b2012-02-03 19:05:29 +0000744 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000745
746 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100747 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000748 print '}'
749 print
750
José Fonseca4220b1b2012-02-03 19:05:29 +0000751 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100752 assert not method.internal
753
José Fonseca632a78d2012-04-19 07:18:59 +0100754 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 +0100755 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 +0100756
757 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
758
José Fonseca632a78d2012-04-19 07:18:59 +0100759 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100760 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100761 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100762 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000763 for arg in method.args:
764 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000765 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000766 for arg in method.args:
767 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000768 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100769 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000770
José Fonseca4220b1b2012-02-03 19:05:29 +0000771 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000772
José Fonseca632a78d2012-04-19 07:18:59 +0100773 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000774
775 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000776 for arg in method.args:
777 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000778 self.serializeArg(method, arg)
779 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000780 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000781
José Fonseca87d1cc62010-11-29 15:57:25 +0000782 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100783 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100784 if method.type is not stdapi.Void:
785 self.wrapRet(method, '_result')
786
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000787 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000788 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000789 print r' if (!_result) {'
790 print r' delete this;'
791 print r' }'
792
793 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000794
José Fonseca143e9252012-04-15 09:31:18 +0100795 def implementIidWrapper(self, api):
796 print r'static void'
797 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
798 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",'
799 print r' functionName, reason,'
800 print r' riid.Data1, riid.Data2, riid.Data3,'
801 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]);'
802 print r'}'
803 print
804 print r'static void'
805 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
806 print r' if (!ppvObj || !*ppvObj) {'
807 print r' return;'
808 print r' }'
809 else_ = ''
810 for iface in api.getAllInterfaces():
811 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000812 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100813 print r' }'
814 else_ = 'else '
815 print r' %s{' % else_
816 print r' warnIID(functionName, riid, "unknown");'
817 print r' }'
818 print r'}'
819 print
820
José Fonsecabcb26b22012-04-15 08:42:25 +0100821 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100822 # Cast output arg to `void **` if necessary
823 out_name = out.name
824 obj_type = out.type.type.type
825 if not obj_type is stdapi.Void:
826 assert isinstance(obj_type, stdapi.Interface)
827 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
828
José Fonsecabcb26b22012-04-15 08:42:25 +0100829 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100830 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100831 else_ = ''
832 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100833 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100834 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100835 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100836 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100837 print r' }'
838 else_ = 'else '
839 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100840 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100841 print r' }'
842 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000843
José Fonseca4220b1b2012-02-03 19:05:29 +0000844 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000845 if method.type is stdapi.Void:
846 result = ''
847 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100848 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100849 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000850
851 def emit_memcpy(self, dest, src, length):
José Fonseca69909e32013-05-04 11:10:33 +0100852 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000853 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100854 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000855 print ' trace::localWriter.endArg();'
856 print ' trace::localWriter.beginArg(1);'
857 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
858 print ' trace::localWriter.endArg();'
859 print ' trace::localWriter.beginArg(2);'
860 print ' trace::localWriter.writeUInt(%s);' % length
861 print ' trace::localWriter.endArg();'
862 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100863 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000864 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100865
866 def fake_call(self, function, args):
867 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
868 for arg, instance in zip(function.args, args):
869 assert not arg.output
870 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
871 self.serializeValue(arg.type, instance)
872 print ' trace::localWriter.endArg();'
873 print ' trace::localWriter.endEnter();'
874 print ' trace::localWriter.beginLeave(_fake_call);'
875 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000876