blob: 7a06dbd85c3b9a34ea478b63b9ebd4fb47965864 [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 \
613 and isinstance(arg.type, stdapi.Pointer) \
614 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100615 self.wrapIid(function, riid, arg)
616 return
617
José Fonseca54f304a2012-01-14 19:33:08 +0000618 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000619
José Fonseca54f304a2012-01-14 19:33:08 +0000620 def unwrapArg(self, function, arg):
621 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000622
José Fonseca54f304a2012-01-14 19:33:08 +0000623 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100624 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000625 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100626 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca54f304a2012-01-14 19:33:08 +0000628 def serializeValue(self, type, instance):
629 serializer = self.serializerFactory()
630 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000631
José Fonseca54f304a2012-01-14 19:33:08 +0000632 def wrapRet(self, function, instance):
633 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000634
José Fonseca0075f152012-04-14 20:25:52 +0100635 def needsWrapping(self, type):
636 visitor = WrapDecider()
637 visitor.visit(type)
638 return visitor.needsWrapping
639
José Fonseca54f304a2012-01-14 19:33:08 +0000640 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100641 if self.needsWrapping(type):
642 visitor = ValueWrapper()
643 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000644
645 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100646 if self.needsWrapping(type):
647 visitor = ValueUnwrapper()
648 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000649
José Fonseca143e9252012-04-15 09:31:18 +0100650 def traceInterfaces(self, api):
651 interfaces = api.getAllInterfaces()
652 if not interfaces:
653 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100654
José Fonseca143e9252012-04-15 09:31:18 +0100655 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100656
657 # Helper functions to wrap/unwrap interface pointers
658 print r'static inline bool'
659 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
660 print r' IUnknown *pObj = NULL;'
661 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
662 print r' if (FAILED(hr)) {'
663 print r' return false;'
664 print r' }'
665 print r' assert(pObj);'
666 print r' pObj->Release();'
667 print r' return pUnknown == pObj;'
668 print r'}'
669 print
670 print r'static inline const void *'
671 print r'getVtbl(const void *pvObj) {'
672 print r' return pvObj ? *(const void **)pvObj : NULL;'
673 print r'}'
674 print
675
José Fonseca143e9252012-04-15 09:31:18 +0100676 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100677
José Fonseca143e9252012-04-15 09:31:18 +0100678 map(self.implementWrapperInterface, interfaces)
679 print
680
José Fonseca0423d2c2012-01-20 19:16:17 +0000681 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100682 wrapperInterfaceName = getWrapperInterfaceName(interface)
683 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000684 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000685 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100686 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
687 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000688 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100689 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
690 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
691 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000692 print
José Fonseca01e50592014-08-22 15:35:27 +0100693
694 methods = list(interface.iterMethods())
695 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000696 print " " + method.prototype() + ";"
697 print
José Fonseca01e50592014-08-22 15:35:27 +0100698
José Fonsecaacc90622012-05-02 13:10:07 +0100699 for type, name, value in self.enumWrapperInterfaceVariables(interface):
700 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100701 print
702
703 print r'private:'
704 print r' void _dummy(unsigned i) const {'
705 print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p\n", "%s", i, this, m_pInstance);' % interface.name
706 print r' trace::localWriter.flush();'
707 print r' os::abort();'
708 print r' }'
709 print
710 for i in range(len(methods), 64):
711 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
712 print
713
José Fonseca0423d2c2012-01-20 19:16:17 +0000714 print "};"
715 print
716
José Fonsecaacc90622012-05-02 13:10:07 +0100717 def enumWrapperInterfaceVariables(self, interface):
718 return [
719 ("DWORD", "m_dwMagic", "0xd8365d6c"),
720 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100721 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000722 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100723 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000724
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100725 def implementWrapperInterface(self, iface):
726 self.interface = iface
727
728 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100729
José Fonsecab7a9b182012-11-23 17:02:48 +0000730 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100731 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
732 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100733 if value is not None:
734 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000735 print '}'
736 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000737
738 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100739 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
740 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100741 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100742 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 +0000743 print r' g_WrappedObjects[pInstance] = pWrapper;'
744 print r' return pWrapper;'
745 print '}'
746 print
747
748 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100749 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100750 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100751 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 +0000752 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000753 print '}'
754 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100755
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100756 baseMethods = list(iface.iterBaseMethods())
757 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100758 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100759 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100760
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000761 print
762
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100763 # Wrap pointer
764 ifaces = self.api.getAllInterfaces()
765 print r'void'
766 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
767 print r' if (!ppObj) {'
768 print r' return;'
769 print r' }'
770 print r' %s *pObj = *ppObj;' % (iface.name,)
771 print r' if (!pObj) {'
772 print r' return;'
773 print r' }'
774 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
775 print r' if (it != g_WrappedObjects.end()) {'
776 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
777 print r' assert(pWrapper);'
778 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
779 print r' assert(pWrapper->m_pInstance == pObj);'
780 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
781 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
782 if debug:
783 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
784 print r' *ppObj = pWrapper;'
785 print r' return;'
786 print r' }'
787 print r' }'
788 else_ = ''
789 for childIface in getInterfaceHierarchy(ifaces, iface):
790 print r' %sif (hasChildInterface(IID_%s, pObj)) {' % (else_, childIface.name)
791 print r' pObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
792 print r' }'
793 else_ = 'else '
794 print r' %s{' % else_
795 print r' pObj = Wrap%s::_create(entryName, pObj);' % iface.name
796 print r' }'
797 print r' *ppObj = pObj;'
798 print r'}'
799 print
800
801 # Unwrap pointer
802 print r'void'
803 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
804 print r' if (!ppObj || !*ppObj) {'
805 print r' return;'
806 print r' }'
807 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
808 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
809 print r' *ppObj = pWrapper->m_pInstance;'
810 print r' } else {'
811 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", entryName, "%s");' % iface.name
812 print r' }'
813 print r'}'
814 print
815
José Fonseca4220b1b2012-02-03 19:05:29 +0000816 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100817 wrapperInterfaceName = getWrapperInterfaceName(interface)
818
819 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000820
821 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100822 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000823
José Fonseca0423d2c2012-01-20 19:16:17 +0000824 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100825 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000826
José Fonseca4220b1b2012-02-03 19:05:29 +0000827 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000828
829 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100830 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000831 print '}'
832 print
833
José Fonseca4220b1b2012-02-03 19:05:29 +0000834 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100835 assert not method.internal
836
José Fonseca632a78d2012-04-19 07:18:59 +0100837 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 +0100838 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 +0100839
840 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
841
José Fonseca632a78d2012-04-19 07:18:59 +0100842 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100843 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100844 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100845 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000846 for arg in method.args:
847 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000848 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000849 for arg in method.args:
850 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000851 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100852 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000853
José Fonseca4220b1b2012-02-03 19:05:29 +0000854 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000855
José Fonseca632a78d2012-04-19 07:18:59 +0100856 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000857
858 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000859 for arg in method.args:
860 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000861 self.serializeArg(method, arg)
862 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000863 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000864
José Fonseca87d1cc62010-11-29 15:57:25 +0000865 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100866 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100867 if method.type is not stdapi.Void:
868 self.wrapRet(method, '_result')
869
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000870 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000871 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000872 print r' if (!_result) {'
873 print r' delete this;'
874 print r' }'
875
876 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000877
José Fonseca143e9252012-04-15 09:31:18 +0100878 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100879 ifaces = api.getAllInterfaces()
880
José Fonseca143e9252012-04-15 09:31:18 +0100881 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100882 print r'warnIID(const char *entryName, REFIID riid, const char *reason) {'
José Fonseca143e9252012-04-15 09:31:18 +0100883 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 +0100884 print r' entryName, reason,'
José Fonseca143e9252012-04-15 09:31:18 +0100885 print r' riid.Data1, riid.Data2, riid.Data3,'
886 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]);'
887 print r'}'
888 print
889 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100890 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100891 print r' if (!ppvObj || !*ppvObj) {'
892 print r' return;'
893 print r' }'
894 else_ = ''
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100895 for iface in ifaces:
José Fonseca143e9252012-04-15 09:31:18 +0100896 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100897 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100898 print r' }'
899 else_ = 'else '
900 print r' %s{' % else_
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100901 print r' warnIID(entryName, riid, "unknown");'
José Fonseca143e9252012-04-15 09:31:18 +0100902 print r' }'
903 print r'}'
904 print
905
José Fonsecabcb26b22012-04-15 08:42:25 +0100906 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100907 # Cast output arg to `void **` if necessary
908 out_name = out.name
909 obj_type = out.type.type.type
910 if not obj_type is stdapi.Void:
911 assert isinstance(obj_type, stdapi.Interface)
912 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
913
José Fonsecabcb26b22012-04-15 08:42:25 +0100914 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100915 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100916 else_ = ''
917 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100918 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100919 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100920 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100921 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100922 print r' }'
923 else_ = 'else '
924 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100925 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100926 print r' }'
927 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000928
José Fonseca4220b1b2012-02-03 19:05:29 +0000929 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000930 if method.type is stdapi.Void:
931 result = ''
932 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100933 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100934 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000935
José Fonseca6f0e3032014-06-25 01:00:35 +0100936 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100937 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100938
939 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100940 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100941 for arg, instance in zip(function.args, args):
942 assert not arg.output
943 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
944 self.serializeValue(arg.type, instance)
945 print ' trace::localWriter.endArg();'
946 print ' trace::localWriter.endEnter();'
947 print ' trace::localWriter.beginLeave(_fake_call);'
948 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000949