blob: 6f5dab42c271097416cc5e96db9cb09d1cedfcbb [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):
José Fonseca30fb4c32012-11-04 11:07:45 +000070 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000071 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000072 if name is None:
73 print ' "",'
74 else:
75 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000076 print '};'
77 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000078 if struct.name is None:
79 structName = '""'
80 else:
81 structName = '"%s"' % struct.name
82 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000083 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000084 print
85
José Fonseca54f304a2012-01-14 19:33:08 +000086 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000087 self.visit(array.type)
88
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020089 def visitAttribArray(self, array):
90 pass
91
José Fonseca54f304a2012-01-14 19:33:08 +000092 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000093 pass
94
José Fonseca54f304a2012-01-14 19:33:08 +000095 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010096 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000097 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000098 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +000099 print '};'
100 print
José Fonseca632a78d2012-04-19 07:18:59 +0100101 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000102 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000103 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000104 print
105
José Fonseca54f304a2012-01-14 19:33:08 +0000106 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100107 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000108 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000109 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000110 print '};'
111 print
José Fonseca632a78d2012-04-19 07:18:59 +0100112 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000113 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000114 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000115 print
116
José Fonseca54f304a2012-01-14 19:33:08 +0000117 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000118 self.visit(pointer.type)
119
José Fonseca59ee88e2012-01-15 14:24:10 +0000120 def visitIntPointer(self, pointer):
121 pass
122
José Fonsecafbcf6832012-04-05 07:10:30 +0100123 def visitObjPointer(self, pointer):
124 self.visit(pointer.type)
125
José Fonseca59ee88e2012-01-15 14:24:10 +0000126 def visitLinearPointer(self, pointer):
127 self.visit(pointer.type)
128
José Fonseca54f304a2012-01-14 19:33:08 +0000129 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000130 self.visit(handle.type)
131
José Fonsecab89c5932012-04-01 22:47:11 +0200132 def visitReference(self, reference):
133 self.visit(reference.type)
134
José Fonseca54f304a2012-01-14 19:33:08 +0000135 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000136 self.visit(alias.type)
137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000139 pass
140
José Fonseca54f304a2012-01-14 19:33:08 +0000141 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000142 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000143
José Fonseca54f304a2012-01-14 19:33:08 +0000144 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100145 if not polymorphic.contextLess:
146 return
José Fonsecafbc51922013-04-14 14:45:04 +0100147 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100148 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000149 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100150 for case in cases:
151 print ' %s:' % case
Jose Fonsecae28c4e92015-01-25 09:53:23 +0000152 self.serializer.visit(type, '(%s)(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100153 print ' break;'
154 print ' }'
155 print '}'
156 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100157
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000158
José Fonsecadbf714b2012-11-20 17:03:43 +0000159class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000160 '''Visitor which generates code to serialize any type.
161
162 Simple types are serialized inline here, whereas the serialization of
163 complex types is dispatched to the serialization functions generated by
164 ComplexValueSerializer visitor above.
165 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000166
José Fonseca54f304a2012-01-14 19:33:08 +0000167 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100168 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000169
José Fonseca54f304a2012-01-14 19:33:08 +0000170 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100171 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000172 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100173 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000174 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100175 cast = 'const wchar_t *'
176 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000177 if cast != string.expr:
178 # reinterpret_cast is necessary for GLubyte * <=> char *
179 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
180 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000181 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000182 else:
183 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100184 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000185
José Fonseca54f304a2012-01-14 19:33:08 +0000186 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000187 self.visit(const.type, instance)
188
José Fonseca54f304a2012-01-14 19:33:08 +0000189 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000190 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000191 for member in struct.members:
192 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000193 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000194
José Fonseca54f304a2012-01-14 19:33:08 +0000195 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100196 length = '_c' + array.type.tag
197 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000198 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100199 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000200 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100201 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100202 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100203 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000204 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100205 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000206 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100207 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100208 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100209 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100210 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000211
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200212 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200213 # For each element, decide if it is a key or a value (which depends on the previous key).
214 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
215 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200216
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200217 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100218 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100219 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200220 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200221 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
222 % {'c': count, 'array': instance, 'terminator': array.terminator}
223 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200224 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200225 for key, valueType in array.valueTypes:
226 if valueType is None:
227 print ' case %s:' % key
228 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
229 print ' break;'
230 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200231 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200232 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200233 print ' trace::localWriter.beginArray(%s);' % count
234
235 # for each key / key-value pair write the key and the value, if the key requires one
236
José Fonseca77c10d82013-07-20 15:27:29 +0100237 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200238 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200239 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100240 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200241 print ' trace::localWriter.endElement();'
242 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
243 print ' break;'
244 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200245 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200246 # write generic value the usual way
247 for key, valueType in array.valueTypes:
248 if valueType is not None:
249 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200250 print ' trace::localWriter.beginElement();'
251 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
252 print ' trace::localWriter.endElement();'
253 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200254 # known key with no value, just decrease the index so we treat the next value as a key
255 if array.hasKeysWithoutValues:
256 for key, valueType in array.valueTypes:
257 if valueType is None:
258 print ' case %s:' % key
259 print ' %s--;' % index
260 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200261 # unknown key, write an int value
262 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200263 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200264 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100265 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200266 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200267 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200268 print ' break;'
269 print ' }'
270 print ' }'
271 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100272 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200273
274
José Fonseca54f304a2012-01-14 19:33:08 +0000275 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000276 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000277
José Fonseca54f304a2012-01-14 19:33:08 +0000278 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100279 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000280
José Fonseca54f304a2012-01-14 19:33:08 +0000281 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100282 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000283
José Fonseca54f304a2012-01-14 19:33:08 +0000284 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100285 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100286 print ' trace::localWriter.beginArray(1);'
287 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000288 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100289 print ' trace::localWriter.endElement();'
290 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100291 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100292 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100293 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000294
José Fonseca59ee88e2012-01-15 14:24:10 +0000295 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100296 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000297
José Fonsecafbcf6832012-04-05 07:10:30 +0100298 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100299 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100300
José Fonseca59ee88e2012-01-15 14:24:10 +0000301 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100302 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000303
José Fonsecab89c5932012-04-01 22:47:11 +0200304 def visitReference(self, reference, instance):
305 self.visit(reference.type, instance)
306
José Fonseca54f304a2012-01-14 19:33:08 +0000307 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000308 self.visit(handle.type, instance)
309
José Fonseca54f304a2012-01-14 19:33:08 +0000310 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000311 self.visit(alias.type, instance)
312
José Fonseca54f304a2012-01-14 19:33:08 +0000313 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100314 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000315
José Fonseca54f304a2012-01-14 19:33:08 +0000316 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100317 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000318
José Fonseca54f304a2012-01-14 19:33:08 +0000319 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100320 if polymorphic.contextLess:
321 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
322 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000323 switchExpr = self.expand(polymorphic.switchExpr)
324 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100325 for cases, type in polymorphic.iterSwitch():
326 for case in cases:
327 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000328 caseInstance = instance
329 if type.expr is not None:
330 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
331 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100332 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000333 if polymorphic.defaultType is None:
334 print r' default:'
335 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
336 print r' trace::localWriter.writeNull();'
337 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100338 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100339
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340
José Fonseca0075f152012-04-14 20:25:52 +0100341class WrapDecider(stdapi.Traverser):
342 '''Type visitor which will decide wheter this type will need wrapping or not.
343
344 For complex types (arrays, structures), we need to know this before hand.
345 '''
346
347 def __init__(self):
348 self.needsWrapping = False
349
José Fonseca0075f152012-04-14 20:25:52 +0100350 def visitLinearPointer(self, void):
351 pass
352
353 def visitInterface(self, interface):
354 self.needsWrapping = True
355
356
José Fonsecadbf714b2012-11-20 17:03:43 +0000357class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000358 '''Type visitor which will generate the code to wrap an instance.
359
360 Wrapping is necessary mostly for interfaces, however interface pointers can
361 appear anywhere inside complex types.
362 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000363
José Fonseca54f304a2012-01-14 19:33:08 +0000364 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000365 for member in struct.members:
366 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000367
José Fonseca54f304a2012-01-14 19:33:08 +0000368 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000369 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100370 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000371 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
372 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100373 print " }"
374 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000375
José Fonseca54f304a2012-01-14 19:33:08 +0000376 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100377 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000378 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100379 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000380
José Fonsecafbcf6832012-04-05 07:10:30 +0100381 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100382 elem_type = pointer.type.mutable()
383 if isinstance(elem_type, stdapi.Interface):
384 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100385 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
386 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100387 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100388 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100389
José Fonseca54f304a2012-01-14 19:33:08 +0000390 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100391 raise NotImplementedError
392
393 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100394 print " Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100395
José Fonseca54f304a2012-01-14 19:33:08 +0000396 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100397 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100398 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000399
400
José Fonseca54f304a2012-01-14 19:33:08 +0000401class ValueUnwrapper(ValueWrapper):
402 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000403
José Fonseca0075f152012-04-14 20:25:52 +0100404 allocated = False
405
José Fonsecae7cb2b92012-09-28 08:40:24 +0100406 def visitStruct(self, struct, instance):
407 if not self.allocated:
408 # Argument is constant. We need to create a non const
409 print ' {'
410 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
411 print ' *_t = %s;' % (instance,)
412 assert instance.startswith('*')
413 print ' %s = _t;' % (instance[1:],)
414 instance = '*_t'
415 self.allocated = True
416 try:
417 return ValueWrapper.visitStruct(self, struct, instance)
418 finally:
419 print ' }'
420 else:
421 return ValueWrapper.visitStruct(self, struct, instance)
422
José Fonseca0075f152012-04-14 20:25:52 +0100423 def visitArray(self, array, instance):
424 if self.allocated or isinstance(instance, stdapi.Interface):
425 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000426 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100427 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000428 print " if (%s && %s) {" % (instance, array_length)
429 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
430 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100431 print " _t[_i] = %s[_i];" % instance
432 self.allocated = True
433 self.visit(array.type, "_t[_i]")
434 print " }"
435 print " %s = _t;" % instance
436 print " }"
437
José Fonseca9782b292012-04-14 22:02:42 +0100438 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100439 print r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
440
441
442def _getInterfaceHierarchy(allIfaces, baseIface, result):
443 for iface in allIfaces:
444 if iface.base is baseIface:
445 _getInterfaceHierarchy(allIfaces, iface, result)
446 result.append(iface)
447
448def getInterfaceHierarchy(allIfaces, baseIface):
449 result = []
450 _getInterfaceHierarchy(allIfaces, baseIface, result)
451 return result
José Fonseca87d1cc62010-11-29 15:57:25 +0000452
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000453
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000454class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000455 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000456
José Fonseca4b466a92012-11-26 19:47:26 +0000457 # 0-3 are reserved to memcpy, malloc, free, and realloc
458 __id = 4
459
José Fonsecabb8760b2011-05-25 23:21:18 +0100460 def __init__(self):
461 self.api = None
462
José Fonseca54f304a2012-01-14 19:33:08 +0000463 def serializerFactory(self):
464 '''Create a serializer.
465
466 Can be overriden by derived classes to inject their own serialzer.
467 '''
468
469 return ValueSerializer()
470
José Fonseca1b6c8752012-04-15 14:33:00 +0100471 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100472 self.api = api
473
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000474 self.header(api)
475
476 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000477 for module in api.modules:
478 for header in module.headers:
479 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000480 print
481
José Fonseca54f304a2012-01-14 19:33:08 +0000482 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000483 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000484 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000485 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000486 print
487
488 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100489 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000490
491 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100492 self.interface = None
493 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000494 for function in api.getAllFunctions():
495 self.traceFunctionDecl(function)
496 for function in api.getAllFunctions():
497 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000498 print
499
500 self.footer(api)
501
502 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100503 print '#ifdef _WIN32'
504 print '# include <malloc.h> // alloca'
505 print '# ifndef alloca'
506 print '# define alloca _alloca'
507 print '# endif'
508 print '#else'
509 print '# include <alloca.h> // alloca'
510 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100511 print
José Fonseca537c5072012-07-07 12:54:09 +0100512 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000513 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000514
515 def footer(self, api):
516 pass
517
José Fonseca54f304a2012-01-14 19:33:08 +0000518 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000519 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000520
José Fonseca84cea3b2012-05-09 21:12:30 +0100521 if not function.internal:
522 if function.args:
523 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
524 else:
525 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100526 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 +0100527 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000528
José Fonseca4b466a92012-11-26 19:47:26 +0000529 def getFunctionSigId(self):
530 id = Tracer.__id
531 Tracer.__id += 1
532 return id
533
José Fonseca54f304a2012-01-14 19:33:08 +0000534 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100535 return True
536
José Fonseca54f304a2012-01-14 19:33:08 +0000537 def traceFunctionImpl(self, function):
538 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100539 print 'extern "C" PUBLIC'
540 else:
541 print 'extern "C" PRIVATE'
542 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000543 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100544 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100545
José Fonseca9362a9f2014-10-07 21:34:49 +0100546 for arg in function.args:
547 if not arg.output:
548 self.unwrapArg(function, arg)
549
José Fonseca54f304a2012-01-14 19:33:08 +0000550 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100551
552 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
553
José Fonseca14c21bc2011-02-20 23:32:22 +0000554 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100555 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100556
José Fonseca14c21bc2011-02-20 23:32:22 +0000557 print '}'
558 print
559
José Fonseca54f304a2012-01-14 19:33:08 +0000560 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100561 if not function.internal:
562 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
563 for arg in function.args:
564 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100565 self.serializeArg(function, arg)
566 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000567 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100568 if not function.internal:
569 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000570 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100571 for arg in function.args:
572 if arg.output:
573 self.serializeArg(function, arg)
574 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000575 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100576 if function.type is not stdapi.Void:
577 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100578 if function.type is not stdapi.Void:
579 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000580 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000581
José Fonseca2cfa02c2013-06-10 08:05:29 +0100582 def invokeFunction(self, function):
583 self.doInvokeFunction(function)
584
585 def doInvokeFunction(self, function, prefix='_', suffix=''):
586 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000587 if function.type is stdapi.Void:
588 result = ''
589 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100590 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100591 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000592 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000593
José Fonseca4fb1ab02012-11-08 10:23:40 +0000594 def wasFunctionSuccessful(self, function):
595 if function.type is stdapi.Void:
596 return 'true'
597 if str(function.type) == 'HRESULT':
598 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000599 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000600
José Fonseca54f304a2012-01-14 19:33:08 +0000601 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100602 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000603 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100604 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000605
José Fonseca54f304a2012-01-14 19:33:08 +0000606 def serializeArgValue(self, function, arg):
607 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000608
José Fonseca54f304a2012-01-14 19:33:08 +0000609 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100610 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100611
612 from specs.winapi import REFIID
613 riid = None
614 for other_arg in function.args:
615 if not other_arg.output and other_arg.type is REFIID:
616 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100617 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100618 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100619 and isinstance(arg.type, stdapi.Pointer) \
620 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100621 self.wrapIid(function, riid, arg)
622 return
623
José Fonseca54f304a2012-01-14 19:33:08 +0000624 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000625
José Fonseca54f304a2012-01-14 19:33:08 +0000626 def unwrapArg(self, function, arg):
627 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000628
José Fonseca54f304a2012-01-14 19:33:08 +0000629 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100630 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000631 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100632 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000633
José Fonseca54f304a2012-01-14 19:33:08 +0000634 def serializeValue(self, type, instance):
635 serializer = self.serializerFactory()
636 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000637
José Fonseca54f304a2012-01-14 19:33:08 +0000638 def wrapRet(self, function, instance):
639 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000640
José Fonseca0075f152012-04-14 20:25:52 +0100641 def needsWrapping(self, type):
642 visitor = WrapDecider()
643 visitor.visit(type)
644 return visitor.needsWrapping
645
José Fonseca54f304a2012-01-14 19:33:08 +0000646 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100647 if self.needsWrapping(type):
648 visitor = ValueWrapper()
649 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000650
651 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100652 if self.needsWrapping(type):
653 visitor = ValueUnwrapper()
654 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000655
José Fonseca143e9252012-04-15 09:31:18 +0100656 def traceInterfaces(self, api):
657 interfaces = api.getAllInterfaces()
658 if not interfaces:
659 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100660
José Fonseca143e9252012-04-15 09:31:18 +0100661 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100662
663 # Helper functions to wrap/unwrap interface pointers
664 print r'static inline bool'
665 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
666 print r' IUnknown *pObj = NULL;'
667 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
668 print r' if (FAILED(hr)) {'
669 print r' return false;'
670 print r' }'
671 print r' assert(pObj);'
672 print r' pObj->Release();'
673 print r' return pUnknown == pObj;'
674 print r'}'
675 print
676 print r'static inline const void *'
677 print r'getVtbl(const void *pvObj) {'
678 print r' return pvObj ? *(const void **)pvObj : NULL;'
679 print r'}'
680 print
681
José Fonseca143e9252012-04-15 09:31:18 +0100682 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100683
José Fonseca143e9252012-04-15 09:31:18 +0100684 map(self.implementWrapperInterface, interfaces)
685 print
686
José Fonseca0423d2c2012-01-20 19:16:17 +0000687 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100688 wrapperInterfaceName = getWrapperInterfaceName(interface)
689 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000690 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000691 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100692 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
693 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000694 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100695 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
696 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
697 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000698 print
José Fonseca01e50592014-08-22 15:35:27 +0100699
700 methods = list(interface.iterMethods())
701 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000702 print " " + method.prototype() + ";"
703 print
José Fonseca01e50592014-08-22 15:35:27 +0100704
José Fonsecaacc90622012-05-02 13:10:07 +0100705 for type, name, value in self.enumWrapperInterfaceVariables(interface):
706 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100707 print
708
709 print r'private:'
710 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100711 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 +0100712 print r' trace::localWriter.flush();'
713 print r' os::abort();'
714 print r' }'
715 print
716 for i in range(len(methods), 64):
717 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
718 print
719
José Fonseca0423d2c2012-01-20 19:16:17 +0000720 print "};"
721 print
722
José Fonsecaacc90622012-05-02 13:10:07 +0100723 def enumWrapperInterfaceVariables(self, interface):
724 return [
725 ("DWORD", "m_dwMagic", "0xd8365d6c"),
726 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100727 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000728 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100729 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000730
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100731 def implementWrapperInterface(self, iface):
732 self.interface = iface
733
734 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100735
José Fonsecab7a9b182012-11-23 17:02:48 +0000736 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100737 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
738 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100739 if value is not None:
740 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000741 print '}'
742 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000743
744 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100745 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
746 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100747 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100748 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 +0000749 print r' g_WrappedObjects[pInstance] = pWrapper;'
750 print r' return pWrapper;'
751 print '}'
752 print
753
754 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100755 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100756 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100757 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 +0000758 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000759 print '}'
760 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100761
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100762 baseMethods = list(iface.iterBaseMethods())
763 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100764 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100765 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100766
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000767 print
768
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100769 # Wrap pointer
770 ifaces = self.api.getAllInterfaces()
771 print r'void'
772 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
773 print r' if (!ppObj) {'
774 print r' return;'
775 print r' }'
776 print r' %s *pObj = *ppObj;' % (iface.name,)
777 print r' if (!pObj) {'
778 print r' return;'
779 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100780 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100781 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
782 print r' if (it != g_WrappedObjects.end()) {'
783 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
784 print r' assert(pWrapper);'
785 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
786 print r' assert(pWrapper->m_pInstance == pObj);'
787 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
788 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
789 if debug:
790 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
791 print r' *ppObj = pWrapper;'
792 print r' return;'
793 print r' }'
794 print r' }'
795 else_ = ''
796 for childIface in getInterfaceHierarchy(ifaces, iface):
797 print r' %sif (hasChildInterface(IID_%s, pObj)) {' % (else_, childIface.name)
798 print r' pObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
799 print r' }'
800 else_ = 'else '
801 print r' %s{' % else_
802 print r' pObj = Wrap%s::_create(entryName, pObj);' % iface.name
803 print r' }'
804 print r' *ppObj = pObj;'
805 print r'}'
806 print
807
808 # Unwrap pointer
809 print r'void'
810 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
811 print r' if (!ppObj || !*ppObj) {'
812 print r' return;'
813 print r' }'
814 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
815 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
816 print r' *ppObj = pWrapper->m_pInstance;'
817 print r' } else {'
Jose Fonseca897d0092015-06-19 22:28:42 +0100818 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100819 print r' }'
820 print r'}'
821 print
822
José Fonseca4220b1b2012-02-03 19:05:29 +0000823 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100824 wrapperInterfaceName = getWrapperInterfaceName(interface)
825
826 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000827
828 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100829 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000830
José Fonseca0423d2c2012-01-20 19:16:17 +0000831 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100832 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000833
José Fonseca9362a9f2014-10-07 21:34:49 +0100834 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
835 for arg in method.args:
836 if not arg.output:
837 self.unwrapArg(method, arg)
838
José Fonseca4220b1b2012-02-03 19:05:29 +0000839 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100840
841 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
842
José Fonseca0423d2c2012-01-20 19:16:17 +0000843 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100844 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100845
José Fonseca0423d2c2012-01-20 19:16:17 +0000846 print '}'
847 print
848
José Fonseca4220b1b2012-02-03 19:05:29 +0000849 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100850 assert not method.internal
851
José Fonseca632a78d2012-04-19 07:18:59 +0100852 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 +0100853 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 +0100854
José Fonseca632a78d2012-04-19 07:18:59 +0100855 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100856 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100857 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100858 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000859 for arg in method.args:
860 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000861 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100862 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000863
José Fonseca4220b1b2012-02-03 19:05:29 +0000864 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000865
José Fonseca632a78d2012-04-19 07:18:59 +0100866 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000867
868 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000869 for arg in method.args:
870 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000871 self.serializeArg(method, arg)
872 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000873 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000874
José Fonseca87d1cc62010-11-29 15:57:25 +0000875 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100876 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100877 if method.type is not stdapi.Void:
878 self.wrapRet(method, '_result')
879
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000880 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000881 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000882 print r' if (!_result) {'
883 print r' delete this;'
884 print r' }'
885
886 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000887
José Fonseca143e9252012-04-15 09:31:18 +0100888 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100889 ifaces = api.getAllInterfaces()
890
José Fonseca143e9252012-04-15 09:31:18 +0100891 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000892 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
José Fonseca974189a2015-02-07 23:19:46 +0000893 print r' os::log("apitrace: warning: %s: %s IID %08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100894 print r' entryName, reason,'
José Fonseca143e9252012-04-15 09:31:18 +0100895 print r' riid.Data1, riid.Data2, riid.Data3,'
896 print r' riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
José Fonseca92624532015-02-07 23:20:37 +0000897 print r' void * pVtbl = *(void **)pvObj;'
898 print r' HMODULE hModule = 0;'
899 print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,'
900 print r' (LPCTSTR)pVtbl,'
901 print r' &hModule);'
902 print r' assert(bRet);'
903 print r' if (bRet) {'
904 print r' char szModule[MAX_PATH];'
905 print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
906 print r' assert(dwRet);'
907 print r' if (dwRet) {'
908 print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
909 print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
910 print r' }'
911 print r' }'
José Fonseca143e9252012-04-15 09:31:18 +0100912 print r'}'
913 print
914 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100915 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100916 print r' if (!ppvObj || !*ppvObj) {'
917 print r' return;'
918 print r' }'
919 else_ = ''
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100920 for iface in ifaces:
José Fonseca143e9252012-04-15 09:31:18 +0100921 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100922 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100923 print r' }'
924 else_ = 'else '
925 print r' %s{' % else_
José Fonseca92624532015-02-07 23:20:37 +0000926 print r' warnIID(entryName, riid, *ppvObj, "unknown");'
José Fonseca143e9252012-04-15 09:31:18 +0100927 print r' }'
928 print r'}'
929 print
930
José Fonsecabcb26b22012-04-15 08:42:25 +0100931 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100932 # Cast output arg to `void **` if necessary
933 out_name = out.name
934 obj_type = out.type.type.type
935 if not obj_type is stdapi.Void:
936 assert isinstance(obj_type, stdapi.Interface)
937 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
938
José Fonsecabcb26b22012-04-15 08:42:25 +0100939 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100940 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100941 else_ = ''
942 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100943 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100944 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100945 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100946 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100947 print r' }'
948 else_ = 'else '
949 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100950 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100951 print r' }'
952 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000953
José Fonseca4220b1b2012-02-03 19:05:29 +0000954 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000955 if method.type is stdapi.Void:
956 result = ''
957 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100958 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100959 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000960
José Fonseca6f0e3032014-06-25 01:00:35 +0100961 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100962 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100963
964 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100965 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100966 for arg, instance in zip(function.args, args):
967 assert not arg.output
968 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
969 self.serializeValue(arg.type, instance)
970 print ' trace::localWriter.endArg();'
971 print ' trace::localWriter.endEnter();'
972 print ' trace::localWriter.beginLeave(_fake_call);'
973 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000974