blob: ab326aa1a780b35ebc626a27c96cf48bc48cdf4f [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,)
José Fonseca69909e32013-05-04 11:10:33 +0100541 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 +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é Fonseca143e9252012-04-15 09:31:18 +0100679 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100680
681 # Helper functions to wrap/unwrap interface pointers
682 print r'static inline bool'
683 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
684 print r' IUnknown *pObj = NULL;'
685 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
686 print r' if (FAILED(hr)) {'
687 print r' return false;'
688 print r' }'
689 print r' assert(pObj);'
690 print r' pObj->Release();'
691 print r' return pUnknown == pObj;'
692 print r'}'
693 print
694 print r'static inline const void *'
695 print r'getVtbl(const void *pvObj) {'
696 print r' return pvObj ? *(const void **)pvObj : NULL;'
697 print r'}'
698 print
699
José Fonseca143e9252012-04-15 09:31:18 +0100700 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100701
José Fonseca143e9252012-04-15 09:31:18 +0100702 map(self.implementWrapperInterface, interfaces)
703 print
704
José Fonseca0423d2c2012-01-20 19:16:17 +0000705 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100706 wrapperInterfaceName = getWrapperInterfaceName(interface)
707 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000708 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000709 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100710 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
711 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000712 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100713 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
714 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
715 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000716 print
José Fonseca01e50592014-08-22 15:35:27 +0100717
718 methods = list(interface.iterMethods())
719 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000720 print " " + method.prototype() + ";"
721 print
José Fonseca01e50592014-08-22 15:35:27 +0100722
José Fonsecaacc90622012-05-02 13:10:07 +0100723 for type, name, value in self.enumWrapperInterfaceVariables(interface):
724 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100725 print
726
727 print r'private:'
728 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100729 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
José Fonseca01e50592014-08-22 15:35:27 +0100730 print r' trace::localWriter.flush();'
731 print r' os::abort();'
732 print r' }'
733 print
734 for i in range(len(methods), 64):
735 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
736 print
737
José Fonseca0423d2c2012-01-20 19:16:17 +0000738 print "};"
739 print
740
José Fonsecaacc90622012-05-02 13:10:07 +0100741 def enumWrapperInterfaceVariables(self, interface):
742 return [
743 ("DWORD", "m_dwMagic", "0xd8365d6c"),
744 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100745 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000746 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100747 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000748
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100749 def implementWrapperInterface(self, iface):
750 self.interface = iface
751
752 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100753
José Fonsecab7a9b182012-11-23 17:02:48 +0000754 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100755 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
756 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100757 if value is not None:
758 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000759 print '}'
760 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000761
762 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100763 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
764 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100765 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100766 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 +0000767 print r' g_WrappedObjects[pInstance] = pWrapper;'
768 print r' return pWrapper;'
769 print '}'
770 print
771
772 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100773 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100774 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100775 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 +0000776 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000777 print '}'
778 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100779
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100780 baseMethods = list(iface.iterBaseMethods())
781 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100782 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100783 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100784
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000785 print
786
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100787 # Wrap pointer
788 ifaces = self.api.getAllInterfaces()
789 print r'void'
790 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
791 print r' if (!ppObj) {'
792 print r' return;'
793 print r' }'
794 print r' %s *pObj = *ppObj;' % (iface.name,)
795 print r' if (!pObj) {'
796 print r' return;'
797 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100798 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100799 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
800 print r' if (it != g_WrappedObjects.end()) {'
801 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
802 print r' assert(pWrapper);'
803 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
804 print r' assert(pWrapper->m_pInstance == pObj);'
805 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
806 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
807 if debug:
808 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
809 print r' *ppObj = pWrapper;'
810 print r' return;'
811 print r' }'
812 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100813 for childIface in getInterfaceHierarchy(ifaces, iface):
Jose Fonseca971c9512015-08-12 11:07:34 +0100814 print r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
815 print r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
816 print r' return;'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100817 print r' }'
Jose Fonseca971c9512015-08-12 11:07:34 +0100818 print r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100819 print r'}'
820 print
821
822 # Unwrap pointer
823 print r'void'
824 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
825 print r' if (!ppObj || !*ppObj) {'
826 print r' return;'
827 print r' }'
828 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
829 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
830 print r' *ppObj = pWrapper->m_pInstance;'
831 print r' } else {'
Jose Fonseca897d0092015-06-19 22:28:42 +0100832 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
Jose Fonseca07b5f132015-07-30 15:12:40 +0100833 print r' trace::localWriter.flush();'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100834 print r' }'
835 print r'}'
836 print
837
José Fonseca4220b1b2012-02-03 19:05:29 +0000838 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100839 wrapperInterfaceName = getWrapperInterfaceName(interface)
840
841 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000842
843 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100844 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000845
José Fonseca0423d2c2012-01-20 19:16:17 +0000846 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100847 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000848
José Fonseca9362a9f2014-10-07 21:34:49 +0100849 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
850 for arg in method.args:
851 if not arg.output:
852 self.unwrapArg(method, arg)
853
José Fonseca4220b1b2012-02-03 19:05:29 +0000854 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100855
856 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
857
José Fonseca0423d2c2012-01-20 19:16:17 +0000858 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100859 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100860
José Fonseca0423d2c2012-01-20 19:16:17 +0000861 print '}'
862 print
863
José Fonseca4220b1b2012-02-03 19:05:29 +0000864 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100865 assert not method.internal
866
José Fonseca632a78d2012-04-19 07:18:59 +0100867 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 +0100868 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 +0100869
José Fonseca632a78d2012-04-19 07:18:59 +0100870 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100871 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100872 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100873 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000874 for arg in method.args:
875 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000876 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100877 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000878
José Fonseca4220b1b2012-02-03 19:05:29 +0000879 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000880
José Fonseca632a78d2012-04-19 07:18:59 +0100881 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000882
883 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000884 for arg in method.args:
885 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000886 self.serializeArg(method, arg)
887 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000888 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000889
José Fonseca87d1cc62010-11-29 15:57:25 +0000890 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100891 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100892 if method.type is not stdapi.Void:
893 self.wrapRet(method, '_result')
894
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000895 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000896 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000897 print r' if (!_result) {'
898 print r' delete this;'
899 print r' }'
900
901 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000902
José Fonseca143e9252012-04-15 09:31:18 +0100903 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100904 ifaces = api.getAllInterfaces()
905
José Fonseca143e9252012-04-15 09:31:18 +0100906 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000907 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100908 print r' os::log("apitrace: warning: %s: %s IID %s\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100909 print r' entryName, reason,'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100910 print r' getGuidName(riid));'
José Fonseca92624532015-02-07 23:20:37 +0000911 print r' void * pVtbl = *(void **)pvObj;'
912 print r' HMODULE hModule = 0;'
Jose Fonsecaa316c6e2015-07-10 11:07:10 +0100913 print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
914 print r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
José Fonseca92624532015-02-07 23:20:37 +0000915 print r' (LPCTSTR)pVtbl,'
916 print r' &hModule);'
917 print r' assert(bRet);'
918 print r' if (bRet) {'
919 print r' char szModule[MAX_PATH];'
920 print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
921 print r' assert(dwRet);'
922 print r' if (dwRet) {'
923 print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
924 print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
925 print r' }'
926 print r' }'
José Fonseca143e9252012-04-15 09:31:18 +0100927 print r'}'
928 print
929 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100930 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100931 print r' if (!ppvObj || !*ppvObj) {'
932 print r' return;'
933 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100934 for iface in ifaces:
Jose Fonseca971c9512015-08-12 11:07:34 +0100935 print r' if (riid == IID_%s) {' % (iface.name,)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100936 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
Jose Fonseca971c9512015-08-12 11:07:34 +0100937 print r' return;'
José Fonseca143e9252012-04-15 09:31:18 +0100938 print r' }'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100939 print r' warnIID(entryName, riid, *ppvObj, "unsupported");'
José Fonseca143e9252012-04-15 09:31:18 +0100940 print r'}'
941 print
942
José Fonsecabcb26b22012-04-15 08:42:25 +0100943 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100944 # Cast output arg to `void **` if necessary
945 out_name = out.name
946 obj_type = out.type.type.type
947 if not obj_type is stdapi.Void:
948 assert isinstance(obj_type, stdapi.Interface)
949 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
950
José Fonsecabcb26b22012-04-15 08:42:25 +0100951 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100952 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100953 else_ = ''
954 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100955 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100956 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100957 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100958 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100959 print r' }'
960 else_ = 'else '
961 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100962 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100963 print r' }'
964 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000965
José Fonseca4220b1b2012-02-03 19:05:29 +0000966 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000967 if method.type is stdapi.Void:
968 result = ''
969 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100970 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100971 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000972
José Fonseca6f0e3032014-06-25 01:00:35 +0100973 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100974 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100975
976 def fake_call(self, function, args):
Jose Fonseca10ab22a2016-01-27 14:10:17 +0000977 print ' {'
José Fonseca7a5f23a2014-06-24 19:20:36 +0100978 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100979 for arg, instance in zip(function.args, args):
980 assert not arg.output
981 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
982 self.serializeValue(arg.type, instance)
983 print ' trace::localWriter.endArg();'
984 print ' trace::localWriter.endEnter();'
985 print ' trace::localWriter.beginLeave(_fake_call);'
986 print ' trace::localWriter.endLeave();'
Jose Fonseca10ab22a2016-01-27 14:10:17 +0000987 print ' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000988