blob: 41a99cfc5f6824ff31a4da8365c91fbefbaee8ab [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
José Fonsecaf7e2fb32014-08-22 15:33:28 +010034import itertools
José Fonseca452d3252012-04-14 15:55:40 +010035
José Fonsecabd86a222011-09-27 09:21:38 +010036import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000037
38
José Fonseca0423d2c2012-01-20 19:16:17 +000039def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000040 return "Wrap" + interface.expr
41
José Fonseca6fac5ae2010-11-29 16:09:13 +000042
José Fonsecaab623c52014-07-22 17:05:00 +010043debug = False
44
José Fonsecaf6b05132012-11-06 00:16:28 +000045
José Fonseca54f304a2012-01-14 19:33:08 +000046class ComplexValueSerializer(stdapi.OnceVisitor):
47 '''Type visitors which generates serialization functions for
48 complex types.
49
50 Simple types are serialized inline.
51 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000052
José Fonseca54f304a2012-01-14 19:33:08 +000053 def __init__(self, serializer):
54 stdapi.OnceVisitor.__init__(self)
55 self.serializer = serializer
56
57 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000058 pass
59
José Fonseca54f304a2012-01-14 19:33:08 +000060 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000061 pass
62
José Fonseca54f304a2012-01-14 19:33:08 +000063 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000064 pass
65
José Fonseca54f304a2012-01-14 19:33:08 +000066 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000067 self.visit(const.type)
68
José Fonseca54f304a2012-01-14 19:33:08 +000069 def visitStruct(self, struct):
Jose Fonseca83e6ddf2016-02-01 13:29:50 +000070 # Write array with structure's member names
71 numMembers = len(struct.members)
72 if numMembers:
73 # Ensure member array has nonzero length to avoid MSVC error C2466
74 memberNames = '_struct%s_members' % (struct.tag,)
75 print 'static const char * %s[%u] = {' % (memberNames, numMembers)
76 for type, name, in struct.members:
77 if name is None:
78 print ' "",'
79 else:
80 print ' "%s",' % (name,)
81 print '};'
82 else:
83 sys.stderr.write('warning: %s has no members\n' % struct.name)
84 memberNames = 'nullptr'
85
86 # Write structure's signature
José Fonseca30fb4c32012-11-04 11:07:45 +000087 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000088 if struct.name is None:
89 structName = '""'
90 else:
91 structName = '"%s"' % struct.name
Jose Fonseca83e6ddf2016-02-01 13:29:50 +000092 print ' %u, %s, %u, %s' % (struct.id, structName, numMembers, memberNames)
José Fonseca30fb4c32012-11-04 11:07:45 +000093 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000094 print
95
José Fonseca54f304a2012-01-14 19:33:08 +000096 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000097 self.visit(array.type)
98
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020099 def visitAttribArray(self, array):
100 pass
101
José Fonseca54f304a2012-01-14 19:33:08 +0000102 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000103 pass
104
José Fonseca54f304a2012-01-14 19:33:08 +0000105 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +0100106 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000107 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000108 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +0000109 print '};'
110 print
José Fonseca632a78d2012-04-19 07:18:59 +0100111 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000112 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000113 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000114 print
115
José Fonseca54f304a2012-01-14 19:33:08 +0000116 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100117 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000118 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000119 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000120 print '};'
121 print
José Fonseca632a78d2012-04-19 07:18:59 +0100122 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000123 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000124 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000125 print
126
José Fonseca54f304a2012-01-14 19:33:08 +0000127 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000128 self.visit(pointer.type)
129
José Fonseca59ee88e2012-01-15 14:24:10 +0000130 def visitIntPointer(self, pointer):
131 pass
132
José Fonsecafbcf6832012-04-05 07:10:30 +0100133 def visitObjPointer(self, pointer):
134 self.visit(pointer.type)
135
José Fonseca59ee88e2012-01-15 14:24:10 +0000136 def visitLinearPointer(self, pointer):
137 self.visit(pointer.type)
138
José Fonseca54f304a2012-01-14 19:33:08 +0000139 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000140 self.visit(handle.type)
141
José Fonsecab89c5932012-04-01 22:47:11 +0200142 def visitReference(self, reference):
143 self.visit(reference.type)
144
José Fonseca54f304a2012-01-14 19:33:08 +0000145 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000146 self.visit(alias.type)
147
José Fonseca54f304a2012-01-14 19:33:08 +0000148 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000149 pass
150
José Fonseca54f304a2012-01-14 19:33:08 +0000151 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000152 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000153
José Fonseca54f304a2012-01-14 19:33:08 +0000154 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100155 if not polymorphic.contextLess:
156 return
José Fonsecafbc51922013-04-14 14:45:04 +0100157 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100158 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000159 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100160 for case in cases:
161 print ' %s:' % case
Jose Fonsecae28c4e92015-01-25 09:53:23 +0000162 self.serializer.visit(type, '(%s)(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100163 print ' break;'
164 print ' }'
165 print '}'
166 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100167
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000168
José Fonsecadbf714b2012-11-20 17:03:43 +0000169class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000170 '''Visitor which generates code to serialize any type.
171
172 Simple types are serialized inline here, whereas the serialization of
173 complex types is dispatched to the serialization functions generated by
174 ComplexValueSerializer visitor above.
175 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000176
José Fonseca54f304a2012-01-14 19:33:08 +0000177 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100178 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000179
José Fonseca54f304a2012-01-14 19:33:08 +0000180 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100181 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000182 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100183 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000184 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100185 cast = 'const wchar_t *'
186 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000187 if cast != string.expr:
188 # reinterpret_cast is necessary for GLubyte * <=> char *
189 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
190 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000191 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000192 else:
193 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100194 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000195
José Fonseca54f304a2012-01-14 19:33:08 +0000196 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000197 self.visit(const.type, instance)
198
José Fonseca54f304a2012-01-14 19:33:08 +0000199 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000200 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000201 for member in struct.members:
202 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000203 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000204
José Fonseca54f304a2012-01-14 19:33:08 +0000205 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100206 length = '_c' + array.type.tag
207 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000208 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100209 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000210 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100211 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100212 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100213 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000214 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100215 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000216 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100217 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100218 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100219 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100220 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000221
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200222 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200223 # For each element, decide if it is a key or a value (which depends on the previous key).
224 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
225 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200226
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200227 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100228 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100229 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200230 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200231 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
232 % {'c': count, 'array': instance, 'terminator': array.terminator}
233 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200234 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200235 for key, valueType in array.valueTypes:
236 if valueType is None:
237 print ' case %s:' % key
238 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
239 print ' break;'
240 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200241 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200242 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200243 print ' trace::localWriter.beginArray(%s);' % count
244
245 # for each key / key-value pair write the key and the value, if the key requires one
246
José Fonseca77c10d82013-07-20 15:27:29 +0100247 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200248 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200249 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100250 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200251 print ' trace::localWriter.endElement();'
252 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
253 print ' break;'
254 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200255 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200256 # write generic value the usual way
257 for key, valueType in array.valueTypes:
258 if valueType is not None:
259 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200260 print ' trace::localWriter.beginElement();'
261 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
262 print ' trace::localWriter.endElement();'
263 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200264 # known key with no value, just decrease the index so we treat the next value as a key
265 if array.hasKeysWithoutValues:
266 for key, valueType in array.valueTypes:
267 if valueType is None:
268 print ' case %s:' % key
269 print ' %s--;' % index
270 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200271 # unknown key, write an int value
272 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200273 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200274 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100275 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200276 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200277 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200278 print ' break;'
279 print ' }'
280 print ' }'
281 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100282 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200283
284
José Fonseca54f304a2012-01-14 19:33:08 +0000285 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000286 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000287
José Fonseca54f304a2012-01-14 19:33:08 +0000288 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100289 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000290
José Fonseca54f304a2012-01-14 19:33:08 +0000291 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100292 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000293
José Fonseca54f304a2012-01-14 19:33:08 +0000294 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100295 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100296 print ' trace::localWriter.beginArray(1);'
297 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000298 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100299 print ' trace::localWriter.endElement();'
300 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100301 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100302 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100303 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000304
José Fonseca59ee88e2012-01-15 14:24:10 +0000305 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100306 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000307
José Fonsecafbcf6832012-04-05 07:10:30 +0100308 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100309 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100310
José Fonseca59ee88e2012-01-15 14:24:10 +0000311 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100312 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000313
José Fonsecab89c5932012-04-01 22:47:11 +0200314 def visitReference(self, reference, instance):
315 self.visit(reference.type, instance)
316
José Fonseca54f304a2012-01-14 19:33:08 +0000317 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000318 self.visit(handle.type, instance)
319
José Fonseca54f304a2012-01-14 19:33:08 +0000320 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000321 self.visit(alias.type, instance)
322
José Fonseca54f304a2012-01-14 19:33:08 +0000323 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100324 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000325
José Fonseca54f304a2012-01-14 19:33:08 +0000326 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100327 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000328
José Fonseca54f304a2012-01-14 19:33:08 +0000329 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100330 if polymorphic.contextLess:
331 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
332 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000333 switchExpr = self.expand(polymorphic.switchExpr)
334 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100335 for cases, type in polymorphic.iterSwitch():
336 for case in cases:
337 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000338 caseInstance = instance
339 if type.expr is not None:
340 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
341 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100342 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000343 if polymorphic.defaultType is None:
344 print r' default:'
345 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
346 print r' trace::localWriter.writeNull();'
347 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100348 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100349
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000350
José Fonseca0075f152012-04-14 20:25:52 +0100351class WrapDecider(stdapi.Traverser):
352 '''Type visitor which will decide wheter this type will need wrapping or not.
353
354 For complex types (arrays, structures), we need to know this before hand.
355 '''
356
357 def __init__(self):
358 self.needsWrapping = False
359
José Fonseca0075f152012-04-14 20:25:52 +0100360 def visitLinearPointer(self, void):
361 pass
362
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100363 def visitObjPointer(self, interface):
José Fonseca0075f152012-04-14 20:25:52 +0100364 self.needsWrapping = True
365
366
José Fonsecadbf714b2012-11-20 17:03:43 +0000367class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000368 '''Type visitor which will generate the code to wrap an instance.
369
370 Wrapping is necessary mostly for interfaces, however interface pointers can
371 appear anywhere inside complex types.
372 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000373
José Fonseca54f304a2012-01-14 19:33:08 +0000374 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000375 for member in struct.members:
376 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000377
José Fonseca54f304a2012-01-14 19:33:08 +0000378 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000379 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100380 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000381 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
382 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100383 print " }"
384 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000385
José Fonseca54f304a2012-01-14 19:33:08 +0000386 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100387 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000388 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100389 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000390
José Fonsecafbcf6832012-04-05 07:10:30 +0100391 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100392 elem_type = pointer.type.mutable()
393 if isinstance(elem_type, stdapi.Interface):
394 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100395 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
396 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100397 else:
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100398 # All interfaces should at least implement IUnknown
399 print " WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,)
José Fonsecafbcf6832012-04-05 07:10:30 +0100400
José Fonseca54f304a2012-01-14 19:33:08 +0000401 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100402 raise NotImplementedError
403
404 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100405 print " Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100406
José Fonseca54f304a2012-01-14 19:33:08 +0000407 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100408 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100409 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000410
411
José Fonseca54f304a2012-01-14 19:33:08 +0000412class ValueUnwrapper(ValueWrapper):
413 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000414
José Fonseca0075f152012-04-14 20:25:52 +0100415 allocated = False
416
José Fonsecae7cb2b92012-09-28 08:40:24 +0100417 def visitStruct(self, struct, instance):
418 if not self.allocated:
419 # Argument is constant. We need to create a non const
420 print ' {'
421 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
422 print ' *_t = %s;' % (instance,)
423 assert instance.startswith('*')
424 print ' %s = _t;' % (instance[1:],)
425 instance = '*_t'
426 self.allocated = True
427 try:
428 return ValueWrapper.visitStruct(self, struct, instance)
429 finally:
430 print ' }'
431 else:
432 return ValueWrapper.visitStruct(self, struct, instance)
433
José Fonseca0075f152012-04-14 20:25:52 +0100434 def visitArray(self, array, instance):
435 if self.allocated or isinstance(instance, stdapi.Interface):
436 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000437 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100438 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000439 print " if (%s && %s) {" % (instance, array_length)
440 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
441 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100442 print " _t[_i] = %s[_i];" % instance
443 self.allocated = True
444 self.visit(array.type, "_t[_i]")
445 print " }"
446 print " %s = _t;" % instance
447 print " }"
448
José Fonseca9782b292012-04-14 22:02:42 +0100449 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100450 print r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
451
452
453def _getInterfaceHierarchy(allIfaces, baseIface, result):
454 for iface in allIfaces:
455 if iface.base is baseIface:
456 _getInterfaceHierarchy(allIfaces, iface, result)
457 result.append(iface)
458
459def getInterfaceHierarchy(allIfaces, baseIface):
460 result = []
461 _getInterfaceHierarchy(allIfaces, baseIface, result)
462 return result
José Fonseca87d1cc62010-11-29 15:57:25 +0000463
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000464
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000465class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000466 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000467
José Fonseca4b466a92012-11-26 19:47:26 +0000468 # 0-3 are reserved to memcpy, malloc, free, and realloc
469 __id = 4
470
José Fonsecabb8760b2011-05-25 23:21:18 +0100471 def __init__(self):
472 self.api = None
473
José Fonseca54f304a2012-01-14 19:33:08 +0000474 def serializerFactory(self):
475 '''Create a serializer.
476
477 Can be overriden by derived classes to inject their own serialzer.
478 '''
479
480 return ValueSerializer()
481
José Fonseca1b6c8752012-04-15 14:33:00 +0100482 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100483 self.api = api
484
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000485 self.header(api)
486
487 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000488 for module in api.modules:
489 for header in module.headers:
490 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000491 print
492
José Fonseca54f304a2012-01-14 19:33:08 +0000493 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000494 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000495 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000496 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000497 print
498
499 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100500 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000501
502 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100503 self.interface = None
504 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000505 for function in api.getAllFunctions():
506 self.traceFunctionDecl(function)
507 for function in api.getAllFunctions():
Jose Fonseca00eba862016-01-26 12:30:54 +0000508 try:
509 self.traceFunctionImpl(function)
510 except:
511 sys.stderr.write("error: %s: exception\n" % function.name)
512 raise
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000513 print
514
515 self.footer(api)
516
517 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100518 print '#ifdef _WIN32'
519 print '# include <malloc.h> // alloca'
520 print '# ifndef alloca'
521 print '# define alloca _alloca'
522 print '# endif'
523 print '#else'
524 print '# include <alloca.h> // alloca'
525 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100526 print
José Fonseca537c5072012-07-07 12:54:09 +0100527 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000528 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000529
530 def footer(self, api):
531 pass
532
José Fonseca54f304a2012-01-14 19:33:08 +0000533 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000534 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000535
José Fonseca84cea3b2012-05-09 21:12:30 +0100536 if not function.internal:
537 if function.args:
538 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
539 else:
540 print 'static const char ** _%s_args = NULL;' % (function.name,)
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000541 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.sigName(), len(function.args), function.name)
José Fonseca84cea3b2012-05-09 21:12:30 +0100542 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000543
José Fonseca4b466a92012-11-26 19:47:26 +0000544 def getFunctionSigId(self):
545 id = Tracer.__id
546 Tracer.__id += 1
547 return id
548
José Fonseca54f304a2012-01-14 19:33:08 +0000549 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100550 return True
551
José Fonseca54f304a2012-01-14 19:33:08 +0000552 def traceFunctionImpl(self, function):
553 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100554 print 'extern "C" PUBLIC'
555 else:
556 print 'extern "C" PRIVATE'
557 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000558 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100559 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100560
José Fonseca9362a9f2014-10-07 21:34:49 +0100561 for arg in function.args:
562 if not arg.output:
563 self.unwrapArg(function, arg)
564
José Fonseca54f304a2012-01-14 19:33:08 +0000565 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100566
567 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
568
José Fonseca14c21bc2011-02-20 23:32:22 +0000569 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100570 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100571
José Fonseca14c21bc2011-02-20 23:32:22 +0000572 print '}'
573 print
574
José Fonseca54f304a2012-01-14 19:33:08 +0000575 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100576 if not function.internal:
577 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
578 for arg in function.args:
579 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100580 self.serializeArg(function, arg)
581 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000582 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100583 if not function.internal:
584 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000585 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100586 for arg in function.args:
587 if arg.output:
588 self.serializeArg(function, arg)
589 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000590 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100591 if function.type is not stdapi.Void:
592 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100593 if function.type is not stdapi.Void:
594 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000595 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000596
José Fonseca2cfa02c2013-06-10 08:05:29 +0100597 def invokeFunction(self, function):
598 self.doInvokeFunction(function)
599
600 def doInvokeFunction(self, function, prefix='_', suffix=''):
601 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000602 if function.type is stdapi.Void:
603 result = ''
604 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100605 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100606 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000607 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000608
José Fonseca4fb1ab02012-11-08 10:23:40 +0000609 def wasFunctionSuccessful(self, function):
610 if function.type is stdapi.Void:
611 return 'true'
612 if str(function.type) == 'HRESULT':
613 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000614 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000615
José Fonseca54f304a2012-01-14 19:33:08 +0000616 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100617 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000618 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100619 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000620
José Fonseca54f304a2012-01-14 19:33:08 +0000621 def serializeArgValue(self, function, arg):
622 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000623
José Fonseca54f304a2012-01-14 19:33:08 +0000624 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100625 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100626
627 from specs.winapi import REFIID
628 riid = None
629 for other_arg in function.args:
630 if not other_arg.output and other_arg.type is REFIID:
631 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100632 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100633 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100634 and isinstance(arg.type, stdapi.Pointer) \
635 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100636 self.wrapIid(function, riid, arg)
637 return
638
José Fonseca54f304a2012-01-14 19:33:08 +0000639 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000640
José Fonseca54f304a2012-01-14 19:33:08 +0000641 def unwrapArg(self, function, arg):
642 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000643
José Fonseca54f304a2012-01-14 19:33:08 +0000644 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100645 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000646 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100647 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000648
José Fonseca54f304a2012-01-14 19:33:08 +0000649 def serializeValue(self, type, instance):
650 serializer = self.serializerFactory()
651 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000652
José Fonseca54f304a2012-01-14 19:33:08 +0000653 def wrapRet(self, function, instance):
654 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000655
José Fonseca0075f152012-04-14 20:25:52 +0100656 def needsWrapping(self, type):
657 visitor = WrapDecider()
658 visitor.visit(type)
659 return visitor.needsWrapping
660
José Fonseca54f304a2012-01-14 19:33:08 +0000661 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100662 if self.needsWrapping(type):
663 visitor = ValueWrapper()
664 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000665
666 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100667 if self.needsWrapping(type):
668 visitor = ValueUnwrapper()
669 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000670
José Fonseca143e9252012-04-15 09:31:18 +0100671 def traceInterfaces(self, api):
672 interfaces = api.getAllInterfaces()
673 if not interfaces:
674 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100675
Jose Fonseca82dbc602015-08-13 12:22:07 +0100676 print r'#include "guids.hpp"'
677 print
678
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100679 # Helper functions to wrap/unwrap interface pointers
680 print r'static inline bool'
681 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
682 print r' IUnknown *pObj = NULL;'
683 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
684 print r' if (FAILED(hr)) {'
685 print r' return false;'
686 print r' }'
687 print r' assert(pObj);'
688 print r' pObj->Release();'
689 print r' return pUnknown == pObj;'
690 print r'}'
691 print
692 print r'static inline const void *'
693 print r'getVtbl(const void *pvObj) {'
694 print r' return pvObj ? *(const void **)pvObj : NULL;'
695 print r'}'
696 print
Jose Fonseca3615c342016-06-30 10:37:19 +0100697 print r'static void'
698 print r'warnVtbl(const void *pVtbl) {'
699 print r' HMODULE hModule = 0;'
700 print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
701 print r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
702 print r' (LPCTSTR)pVtbl,'
703 print r' &hModule);'
704 print r' assert(bRet);'
705 print r' if (bRet) {'
706 print r' char szModule[MAX_PATH];'
707 print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
708 print r' assert(dwRet);'
709 print r' if (dwRet) {'
710 print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
711 print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
712 print r' }'
713 print r' }'
714 print r'}'
715 print
716
717 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100718
José Fonseca143e9252012-04-15 09:31:18 +0100719 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100720
José Fonseca143e9252012-04-15 09:31:18 +0100721 map(self.implementWrapperInterface, interfaces)
722 print
723
José Fonseca0423d2c2012-01-20 19:16:17 +0000724 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100725 wrapperInterfaceName = getWrapperInterfaceName(interface)
726 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000727 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000728 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100729 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
730 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000731 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100732 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
733 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
734 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000735 print
José Fonseca01e50592014-08-22 15:35:27 +0100736
737 methods = list(interface.iterMethods())
738 for method in methods:
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000739 print " " + method.prototype() + " override;"
José Fonseca0423d2c2012-01-20 19:16:17 +0000740 print
José Fonseca01e50592014-08-22 15:35:27 +0100741
José Fonsecaacc90622012-05-02 13:10:07 +0100742 for type, name, value in self.enumWrapperInterfaceVariables(interface):
743 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100744 print
745
746 print r'private:'
747 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100748 print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p pVtbl=%%p\n", "%s", i, this, m_pInstance, m_pVtbl);' % interface.name
Jose Fonseca3615c342016-06-30 10:37:19 +0100749 print r' warnVtbl(m_pVtbl);'
750 print r' warnVtbl(getVtbl(m_pInstance));'
José Fonseca01e50592014-08-22 15:35:27 +0100751 print r' trace::localWriter.flush();'
752 print r' os::abort();'
753 print r' }'
754 print
755 for i in range(len(methods), 64):
756 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
757 print
758
José Fonseca0423d2c2012-01-20 19:16:17 +0000759 print "};"
760 print
761
José Fonsecaacc90622012-05-02 13:10:07 +0100762 def enumWrapperInterfaceVariables(self, interface):
763 return [
764 ("DWORD", "m_dwMagic", "0xd8365d6c"),
765 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100766 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000767 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100768 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000769
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100770 def implementWrapperInterface(self, iface):
771 self.interface = iface
772
773 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100774
José Fonsecab7a9b182012-11-23 17:02:48 +0000775 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100776 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
777 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100778 if value is not None:
779 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000780 print '}'
781 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000782
783 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100784 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
785 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100786 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100787 print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", entryName, pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000788 print r' g_WrappedObjects[pInstance] = pWrapper;'
789 print r' return pWrapper;'
790 print '}'
791 print
792
793 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100794 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100795 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100796 print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % iface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000797 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000798 print '}'
799 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100800
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100801 baseMethods = list(iface.iterBaseMethods())
802 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100803 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100804 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100805
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000806 print
807
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100808 # Wrap pointer
809 ifaces = self.api.getAllInterfaces()
810 print r'void'
811 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
812 print r' if (!ppObj) {'
813 print r' return;'
814 print r' }'
815 print r' %s *pObj = *ppObj;' % (iface.name,)
816 print r' if (!pObj) {'
817 print r' return;'
818 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100819 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100820 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
821 print r' if (it != g_WrappedObjects.end()) {'
822 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
823 print r' assert(pWrapper);'
824 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
Jose Fonsecac04e1892016-06-28 22:25:43 +0100825 print r' if (pWrapper->m_pInstance == pObj &&'
826 print r' pWrapper->m_pVtbl == getVtbl(pObj) &&'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100827 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
828 if debug:
829 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
Jose Fonsecac04e1892016-06-28 22:25:43 +0100830 print r' assert(hasChildInterface(IID_%s, pWrapper->m_pInstance));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100831 print r' *ppObj = pWrapper;'
832 print r' return;'
Jose Fonsecac04e1892016-06-28 22:25:43 +0100833 print r' } else {'
834 print r' delete pWrapper;'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100835 print r' }'
836 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100837 for childIface in getInterfaceHierarchy(ifaces, iface):
Jose Fonseca971c9512015-08-12 11:07:34 +0100838 print r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
839 print r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
840 print r' return;'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100841 print r' }'
Jose Fonseca971c9512015-08-12 11:07:34 +0100842 print r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100843 print r'}'
844 print
845
846 # Unwrap pointer
847 print r'void'
848 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
849 print r' if (!ppObj || !*ppObj) {'
850 print r' return;'
851 print r' }'
852 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
853 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
854 print r' *ppObj = pWrapper->m_pInstance;'
855 print r' } else {'
Jose Fonseca897d0092015-06-19 22:28:42 +0100856 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
Jose Fonseca07b5f132015-07-30 15:12:40 +0100857 print r' trace::localWriter.flush();'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100858 print r' }'
859 print r'}'
860 print
861
José Fonseca4220b1b2012-02-03 19:05:29 +0000862 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100863 wrapperInterfaceName = getWrapperInterfaceName(interface)
864
865 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000866
867 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100868 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000869
José Fonseca0423d2c2012-01-20 19:16:17 +0000870 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100871 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000872
José Fonseca9362a9f2014-10-07 21:34:49 +0100873 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
874 for arg in method.args:
875 if not arg.output:
876 self.unwrapArg(method, arg)
877
José Fonseca4220b1b2012-02-03 19:05:29 +0000878 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100879
880 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
881
José Fonseca0423d2c2012-01-20 19:16:17 +0000882 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100883 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100884
José Fonseca0423d2c2012-01-20 19:16:17 +0000885 print '}'
886 print
887
José Fonseca4220b1b2012-02-03 19:05:29 +0000888 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100889 assert not method.internal
890
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000891 sigName = interface.name + '::' + method.sigName()
892 if method.overloaded:
893 # Once the method signature name goes into a trace, we'll need to
894 # support it indefinetely, so log them so one can make sure nothing
895 # weird gets baked in
896 sys.stderr.write('note: overloaded method %s\n' % (sigName,))
897
898 numArgs = len(method.args) + 1
899 print ' static const char * _args[%u] = {%s};' % (numArgs, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
900 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), sigName, numArgs)
José Fonsecaa0e97862012-04-29 23:22:52 +0100901
José Fonseca632a78d2012-04-19 07:18:59 +0100902 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100903 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100904 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100905 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000906 for arg in method.args:
907 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000908 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100909 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000910
José Fonseca4220b1b2012-02-03 19:05:29 +0000911 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000912
José Fonseca632a78d2012-04-19 07:18:59 +0100913 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000914
915 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000916 for arg in method.args:
917 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000918 self.serializeArg(method, arg)
919 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000920 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000921
José Fonseca87d1cc62010-11-29 15:57:25 +0000922 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100923 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100924 if method.type is not stdapi.Void:
925 self.wrapRet(method, '_result')
926
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000927 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000928 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000929 print r' if (!_result) {'
Jose Fonsecac04e1892016-06-28 22:25:43 +0100930 print r' // NOTE: Must not delete the wrapper here. See'
931 print r' // https://github.com/apitrace/apitrace/issues/462'
José Fonsecab7a9b182012-11-23 17:02:48 +0000932 print r' }'
933
934 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000935
José Fonseca143e9252012-04-15 09:31:18 +0100936 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100937 ifaces = api.getAllInterfaces()
938
José Fonseca143e9252012-04-15 09:31:18 +0100939 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000940 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100941 print r' os::log("apitrace: warning: %s: %s IID %s\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100942 print r' entryName, reason,'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100943 print r' getGuidName(riid));'
Jose Fonseca3615c342016-06-30 10:37:19 +0100944 print r' const void * pVtbl = getVtbl(pvObj);'
945 print r' warnVtbl(pVtbl);'
José Fonseca143e9252012-04-15 09:31:18 +0100946 print r'}'
947 print
948 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100949 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100950 print r' if (!ppvObj || !*ppvObj) {'
951 print r' return;'
952 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100953 for iface in ifaces:
Jose Fonseca971c9512015-08-12 11:07:34 +0100954 print r' if (riid == IID_%s) {' % (iface.name,)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100955 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
Jose Fonseca971c9512015-08-12 11:07:34 +0100956 print r' return;'
José Fonseca143e9252012-04-15 09:31:18 +0100957 print r' }'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100958 print r' warnIID(entryName, riid, *ppvObj, "unsupported");'
José Fonseca143e9252012-04-15 09:31:18 +0100959 print r'}'
960 print
961
José Fonsecabcb26b22012-04-15 08:42:25 +0100962 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100963 # Cast output arg to `void **` if necessary
964 out_name = out.name
965 obj_type = out.type.type.type
966 if not obj_type is stdapi.Void:
967 assert isinstance(obj_type, stdapi.Interface)
968 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
969
José Fonsecabcb26b22012-04-15 08:42:25 +0100970 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100971 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100972 else_ = ''
973 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100974 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100975 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100976 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100977 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100978 print r' }'
979 else_ = 'else '
980 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100981 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100982 print r' }'
983 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000984
José Fonseca4220b1b2012-02-03 19:05:29 +0000985 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000986 if method.type is stdapi.Void:
987 result = ''
988 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100989 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100990 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000991
José Fonseca6f0e3032014-06-25 01:00:35 +0100992 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100993 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100994
995 def fake_call(self, function, args):
Jose Fonseca10ab22a2016-01-27 14:10:17 +0000996 print ' {'
José Fonseca7a5f23a2014-06-24 19:20:36 +0100997 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100998 for arg, instance in zip(function.args, args):
999 assert not arg.output
1000 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
1001 self.serializeValue(arg.type, instance)
1002 print ' trace::localWriter.endArg();'
1003 print ' trace::localWriter.endEnter();'
1004 print ' trace::localWriter.beginLeave(_fake_call);'
1005 print ' trace::localWriter.endLeave();'
Jose Fonseca10ab22a2016-01-27 14:10:17 +00001006 print ' }'
José Fonseca0423d2c2012-01-20 19:16:17 +00001007