blob: 860c00a98a6ce07336cdad08ad6f896b16eba3f5 [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
José Fonseca54f304a2012-01-14 19:33:08 +0000152 self.serializer.visit(type, 'static_cast<%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é Fonseca54f304a2012-01-14 19:33:08 +0000546 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000547 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100548 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000549 print '}'
550 print
551
José Fonseca54f304a2012-01-14 19:33:08 +0000552 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100553 if not function.internal:
554 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
555 for arg in function.args:
556 if not arg.output:
557 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000558 for arg in function.args:
559 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100560 self.serializeArg(function, arg)
561 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000562 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100563 if not function.internal:
564 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000565 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100566 for arg in function.args:
567 if arg.output:
568 self.serializeArg(function, arg)
569 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000570 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100571 if function.type is not stdapi.Void:
572 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100573 if function.type is not stdapi.Void:
574 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000575 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000576
José Fonseca2cfa02c2013-06-10 08:05:29 +0100577 def invokeFunction(self, function):
578 self.doInvokeFunction(function)
579
580 def doInvokeFunction(self, function, prefix='_', suffix=''):
581 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000582 if function.type is stdapi.Void:
583 result = ''
584 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100585 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100586 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000587 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000588
José Fonseca4fb1ab02012-11-08 10:23:40 +0000589 def wasFunctionSuccessful(self, function):
590 if function.type is stdapi.Void:
591 return 'true'
592 if str(function.type) == 'HRESULT':
593 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000594 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000595
José Fonseca54f304a2012-01-14 19:33:08 +0000596 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100597 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000598 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100599 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000600
José Fonseca54f304a2012-01-14 19:33:08 +0000601 def serializeArgValue(self, function, arg):
602 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000603
José Fonseca54f304a2012-01-14 19:33:08 +0000604 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100605 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100606
607 from specs.winapi import REFIID
608 riid = None
609 for other_arg in function.args:
610 if not other_arg.output and other_arg.type is REFIID:
611 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100612 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100613 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100614 and isinstance(arg.type, stdapi.Pointer) \
615 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100616 self.wrapIid(function, riid, arg)
617 return
618
José Fonseca54f304a2012-01-14 19:33:08 +0000619 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000620
José Fonseca54f304a2012-01-14 19:33:08 +0000621 def unwrapArg(self, function, arg):
622 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000623
José Fonseca54f304a2012-01-14 19:33:08 +0000624 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100625 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000626 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100627 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000628
José Fonseca54f304a2012-01-14 19:33:08 +0000629 def serializeValue(self, type, instance):
630 serializer = self.serializerFactory()
631 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000632
José Fonseca54f304a2012-01-14 19:33:08 +0000633 def wrapRet(self, function, instance):
634 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000635
José Fonseca0075f152012-04-14 20:25:52 +0100636 def needsWrapping(self, type):
637 visitor = WrapDecider()
638 visitor.visit(type)
639 return visitor.needsWrapping
640
José Fonseca54f304a2012-01-14 19:33:08 +0000641 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100642 if self.needsWrapping(type):
643 visitor = ValueWrapper()
644 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000645
646 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100647 if self.needsWrapping(type):
648 visitor = ValueUnwrapper()
649 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000650
José Fonseca143e9252012-04-15 09:31:18 +0100651 def traceInterfaces(self, api):
652 interfaces = api.getAllInterfaces()
653 if not interfaces:
654 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100655
José Fonseca143e9252012-04-15 09:31:18 +0100656 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100657
658 # Helper functions to wrap/unwrap interface pointers
659 print r'static inline bool'
660 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
661 print r' IUnknown *pObj = NULL;'
662 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
663 print r' if (FAILED(hr)) {'
664 print r' return false;'
665 print r' }'
666 print r' assert(pObj);'
667 print r' pObj->Release();'
668 print r' return pUnknown == pObj;'
669 print r'}'
670 print
671 print r'static inline const void *'
672 print r'getVtbl(const void *pvObj) {'
673 print r' return pvObj ? *(const void **)pvObj : NULL;'
674 print r'}'
675 print
676
José Fonseca143e9252012-04-15 09:31:18 +0100677 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100678
José Fonseca143e9252012-04-15 09:31:18 +0100679 map(self.implementWrapperInterface, interfaces)
680 print
681
José Fonseca0423d2c2012-01-20 19:16:17 +0000682 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100683 wrapperInterfaceName = getWrapperInterfaceName(interface)
684 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000685 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000686 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100687 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
688 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000689 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100690 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
691 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
692 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000693 print
José Fonseca01e50592014-08-22 15:35:27 +0100694
695 methods = list(interface.iterMethods())
696 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000697 print " " + method.prototype() + ";"
698 print
José Fonseca01e50592014-08-22 15:35:27 +0100699
José Fonsecaacc90622012-05-02 13:10:07 +0100700 for type, name, value in self.enumWrapperInterfaceVariables(interface):
701 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100702 print
703
704 print r'private:'
705 print r' void _dummy(unsigned i) const {'
706 print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p\n", "%s", i, this, m_pInstance);' % interface.name
707 print r' trace::localWriter.flush();'
708 print r' os::abort();'
709 print r' }'
710 print
711 for i in range(len(methods), 64):
712 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
713 print
714
José Fonseca0423d2c2012-01-20 19:16:17 +0000715 print "};"
716 print
717
José Fonsecaacc90622012-05-02 13:10:07 +0100718 def enumWrapperInterfaceVariables(self, interface):
719 return [
720 ("DWORD", "m_dwMagic", "0xd8365d6c"),
721 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100722 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000723 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100724 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000725
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100726 def implementWrapperInterface(self, iface):
727 self.interface = iface
728
729 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100730
José Fonsecab7a9b182012-11-23 17:02:48 +0000731 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100732 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
733 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100734 if value is not None:
735 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000736 print '}'
737 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000738
739 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100740 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
741 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100742 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100743 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 +0000744 print r' g_WrappedObjects[pInstance] = pWrapper;'
745 print r' return pWrapper;'
746 print '}'
747 print
748
749 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100750 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100751 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100752 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 +0000753 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000754 print '}'
755 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100756
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100757 baseMethods = list(iface.iterBaseMethods())
758 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100759 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100760 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100761
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000762 print
763
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100764 # Wrap pointer
765 ifaces = self.api.getAllInterfaces()
766 print r'void'
767 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
768 print r' if (!ppObj) {'
769 print r' return;'
770 print r' }'
771 print r' %s *pObj = *ppObj;' % (iface.name,)
772 print r' if (!pObj) {'
773 print r' return;'
774 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100775 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100776 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
777 print r' if (it != g_WrappedObjects.end()) {'
778 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
779 print r' assert(pWrapper);'
780 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
781 print r' assert(pWrapper->m_pInstance == pObj);'
782 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
783 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
784 if debug:
785 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
786 print r' *ppObj = pWrapper;'
787 print r' return;'
788 print r' }'
789 print r' }'
790 else_ = ''
791 for childIface in getInterfaceHierarchy(ifaces, iface):
792 print r' %sif (hasChildInterface(IID_%s, pObj)) {' % (else_, childIface.name)
793 print r' pObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
794 print r' }'
795 else_ = 'else '
796 print r' %s{' % else_
797 print r' pObj = Wrap%s::_create(entryName, pObj);' % iface.name
798 print r' }'
799 print r' *ppObj = pObj;'
800 print r'}'
801 print
802
803 # Unwrap pointer
804 print r'void'
805 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
806 print r' if (!ppObj || !*ppObj) {'
807 print r' return;'
808 print r' }'
809 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
810 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
811 print r' *ppObj = pWrapper->m_pInstance;'
812 print r' } else {'
813 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", entryName, "%s");' % iface.name
814 print r' }'
815 print r'}'
816 print
817
José Fonseca4220b1b2012-02-03 19:05:29 +0000818 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100819 wrapperInterfaceName = getWrapperInterfaceName(interface)
820
821 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000822
823 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100824 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000825
José Fonseca0423d2c2012-01-20 19:16:17 +0000826 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100827 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000828
José Fonseca4220b1b2012-02-03 19:05:29 +0000829 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000830
831 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100832 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000833 print '}'
834 print
835
José Fonseca4220b1b2012-02-03 19:05:29 +0000836 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100837 assert not method.internal
838
José Fonseca632a78d2012-04-19 07:18:59 +0100839 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 +0100840 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 +0100841
842 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
843
José Fonseca632a78d2012-04-19 07:18:59 +0100844 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100845 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100846 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100847 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000848 for arg in method.args:
849 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000850 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000851 for arg in method.args:
852 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000853 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100854 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000855
José Fonseca4220b1b2012-02-03 19:05:29 +0000856 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000857
José Fonseca632a78d2012-04-19 07:18:59 +0100858 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000859
860 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000861 for arg in method.args:
862 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000863 self.serializeArg(method, arg)
864 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000865 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000866
José Fonseca87d1cc62010-11-29 15:57:25 +0000867 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100868 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100869 if method.type is not stdapi.Void:
870 self.wrapRet(method, '_result')
871
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000872 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000873 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000874 print r' if (!_result) {'
875 print r' delete this;'
876 print r' }'
877
878 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000879
José Fonseca143e9252012-04-15 09:31:18 +0100880 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100881 ifaces = api.getAllInterfaces()
882
José Fonseca143e9252012-04-15 09:31:18 +0100883 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100884 print r'warnIID(const char *entryName, REFIID riid, const char *reason) {'
José Fonseca143e9252012-04-15 09:31:18 +0100885 print r' os::log("apitrace: warning: %s: %s IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100886 print r' entryName, reason,'
José Fonseca143e9252012-04-15 09:31:18 +0100887 print r' riid.Data1, riid.Data2, riid.Data3,'
888 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]);'
889 print r'}'
890 print
891 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100892 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100893 print r' if (!ppvObj || !*ppvObj) {'
894 print r' return;'
895 print r' }'
896 else_ = ''
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100897 for iface in ifaces:
José Fonseca143e9252012-04-15 09:31:18 +0100898 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100899 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100900 print r' }'
901 else_ = 'else '
902 print r' %s{' % else_
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100903 print r' warnIID(entryName, riid, "unknown");'
José Fonseca143e9252012-04-15 09:31:18 +0100904 print r' }'
905 print r'}'
906 print
907
José Fonsecabcb26b22012-04-15 08:42:25 +0100908 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100909 # Cast output arg to `void **` if necessary
910 out_name = out.name
911 obj_type = out.type.type.type
912 if not obj_type is stdapi.Void:
913 assert isinstance(obj_type, stdapi.Interface)
914 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
915
José Fonsecabcb26b22012-04-15 08:42:25 +0100916 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100917 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100918 else_ = ''
919 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100920 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100921 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100922 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100923 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100924 print r' }'
925 else_ = 'else '
926 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100927 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100928 print r' }'
929 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000930
José Fonseca4220b1b2012-02-03 19:05:29 +0000931 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000932 if method.type is stdapi.Void:
933 result = ''
934 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100935 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100936 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000937
José Fonseca6f0e3032014-06-25 01:00:35 +0100938 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100939 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100940
941 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100942 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100943 for arg, instance in zip(function.args, args):
944 assert not arg.output
945 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
946 self.serializeValue(arg.type, instance)
947 print ' trace::localWriter.endArg();'
948 print ' trace::localWriter.endEnter();'
949 print ' trace::localWriter.beginLeave(_fake_call);'
950 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000951