blob: eac718c42d925aedd496e6be847d80d756c13189 [file] [log] [blame]
José Fonseca8fbdd3a2010-11-23 20:55:07 +00001##########################################################################
2#
3# Copyright 2008-2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
José Fonseca73d0a962010-11-29 14:49:34 +000026"""Common trace code generation."""
José Fonseca8fbdd3a2010-11-23 20:55:07 +000027
28
José Fonseca452d3252012-04-14 15:55:40 +010029# Adjust path
30import os.path
31import sys
32sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
33
José Fonsecaf7e2fb32014-08-22 15:33:28 +010034import itertools
José Fonseca452d3252012-04-14 15:55:40 +010035
José Fonsecabd86a222011-09-27 09:21:38 +010036import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000037
38
José Fonseca0423d2c2012-01-20 19:16:17 +000039def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000040 return "Wrap" + interface.expr
41
José Fonseca6fac5ae2010-11-29 16:09:13 +000042
José Fonsecaab623c52014-07-22 17:05:00 +010043debug = False
44
José Fonsecaf6b05132012-11-06 00:16:28 +000045
José Fonseca54f304a2012-01-14 19:33:08 +000046class ComplexValueSerializer(stdapi.OnceVisitor):
47 '''Type visitors which generates serialization functions for
48 complex types.
49
50 Simple types are serialized inline.
51 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000052
José Fonseca54f304a2012-01-14 19:33:08 +000053 def __init__(self, serializer):
54 stdapi.OnceVisitor.__init__(self)
55 self.serializer = serializer
56
57 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000058 pass
59
José Fonseca54f304a2012-01-14 19:33:08 +000060 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000061 pass
62
José Fonseca54f304a2012-01-14 19:33:08 +000063 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000064 pass
65
José Fonseca54f304a2012-01-14 19:33:08 +000066 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000067 self.visit(const.type)
68
José Fonseca54f304a2012-01-14 19:33:08 +000069 def visitStruct(self, struct):
José Fonseca30fb4c32012-11-04 11:07:45 +000070 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000071 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000072 if name is None:
73 print ' "",'
74 else:
75 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000076 print '};'
77 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000078 if struct.name is None:
79 structName = '""'
80 else:
81 structName = '"%s"' % struct.name
82 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000083 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000084 print
85
José Fonseca54f304a2012-01-14 19:33:08 +000086 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000087 self.visit(array.type)
88
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020089 def visitAttribArray(self, array):
90 pass
91
José Fonseca54f304a2012-01-14 19:33:08 +000092 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000093 pass
94
José Fonseca54f304a2012-01-14 19:33:08 +000095 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010096 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000097 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000098 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +000099 print '};'
100 print
José Fonseca632a78d2012-04-19 07:18:59 +0100101 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000102 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000103 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000104 print
105
José Fonseca54f304a2012-01-14 19:33:08 +0000106 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100107 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000108 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000109 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000110 print '};'
111 print
José Fonseca632a78d2012-04-19 07:18:59 +0100112 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000113 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000114 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000115 print
116
José Fonseca54f304a2012-01-14 19:33:08 +0000117 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000118 self.visit(pointer.type)
119
José Fonseca59ee88e2012-01-15 14:24:10 +0000120 def visitIntPointer(self, pointer):
121 pass
122
José Fonsecafbcf6832012-04-05 07:10:30 +0100123 def visitObjPointer(self, pointer):
124 self.visit(pointer.type)
125
José Fonseca59ee88e2012-01-15 14:24:10 +0000126 def visitLinearPointer(self, pointer):
127 self.visit(pointer.type)
128
José Fonseca54f304a2012-01-14 19:33:08 +0000129 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000130 self.visit(handle.type)
131
José Fonsecab89c5932012-04-01 22:47:11 +0200132 def visitReference(self, reference):
133 self.visit(reference.type)
134
José Fonseca54f304a2012-01-14 19:33:08 +0000135 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000136 self.visit(alias.type)
137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000139 pass
140
José Fonseca54f304a2012-01-14 19:33:08 +0000141 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000142 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000143
José Fonseca54f304a2012-01-14 19:33:08 +0000144 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100145 if not polymorphic.contextLess:
146 return
José Fonsecafbc51922013-04-14 14:45:04 +0100147 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100148 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000149 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100150 for case in cases:
151 print ' %s:' % case
Jose Fonsecae28c4e92015-01-25 09:53:23 +0000152 self.serializer.visit(type, '(%s)(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100153 print ' break;'
154 print ' }'
155 print '}'
156 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100157
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000158
José Fonsecadbf714b2012-11-20 17:03:43 +0000159class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000160 '''Visitor which generates code to serialize any type.
161
162 Simple types are serialized inline here, whereas the serialization of
163 complex types is dispatched to the serialization functions generated by
164 ComplexValueSerializer visitor above.
165 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000166
José Fonseca54f304a2012-01-14 19:33:08 +0000167 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100168 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000169
José Fonseca54f304a2012-01-14 19:33:08 +0000170 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100171 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000172 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100173 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000174 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100175 cast = 'const wchar_t *'
176 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000177 if cast != string.expr:
178 # reinterpret_cast is necessary for GLubyte * <=> char *
179 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
180 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000181 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000182 else:
183 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100184 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000185
José Fonseca54f304a2012-01-14 19:33:08 +0000186 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000187 self.visit(const.type, instance)
188
José Fonseca54f304a2012-01-14 19:33:08 +0000189 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000190 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000191 for member in struct.members:
192 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000193 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000194
José Fonseca54f304a2012-01-14 19:33:08 +0000195 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100196 length = '_c' + array.type.tag
197 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000198 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100199 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000200 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100201 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100202 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100203 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000204 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100205 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000206 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100207 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100208 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100209 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100210 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000211
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200212 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200213 # For each element, decide if it is a key or a value (which depends on the previous key).
214 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
215 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200216
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200217 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100218 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100219 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200220 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200221 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
222 % {'c': count, 'array': instance, 'terminator': array.terminator}
223 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200224 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200225 for key, valueType in array.valueTypes:
226 if valueType is None:
227 print ' case %s:' % key
228 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
229 print ' break;'
230 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200231 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200232 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200233 print ' trace::localWriter.beginArray(%s);' % count
234
235 # for each key / key-value pair write the key and the value, if the key requires one
236
José Fonseca77c10d82013-07-20 15:27:29 +0100237 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200238 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200239 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100240 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200241 print ' trace::localWriter.endElement();'
242 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
243 print ' break;'
244 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200245 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200246 # write generic value the usual way
247 for key, valueType in array.valueTypes:
248 if valueType is not None:
249 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200250 print ' trace::localWriter.beginElement();'
251 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
252 print ' trace::localWriter.endElement();'
253 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200254 # known key with no value, just decrease the index so we treat the next value as a key
255 if array.hasKeysWithoutValues:
256 for key, valueType in array.valueTypes:
257 if valueType is None:
258 print ' case %s:' % key
259 print ' %s--;' % index
260 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200261 # unknown key, write an int value
262 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200263 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200264 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100265 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200266 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200267 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200268 print ' break;'
269 print ' }'
270 print ' }'
271 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100272 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200273
274
José Fonseca54f304a2012-01-14 19:33:08 +0000275 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000276 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000277
José Fonseca54f304a2012-01-14 19:33:08 +0000278 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100279 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000280
José Fonseca54f304a2012-01-14 19:33:08 +0000281 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100282 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000283
José Fonseca54f304a2012-01-14 19:33:08 +0000284 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100285 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100286 print ' trace::localWriter.beginArray(1);'
287 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000288 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100289 print ' trace::localWriter.endElement();'
290 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100291 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100292 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100293 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000294
José Fonseca59ee88e2012-01-15 14:24:10 +0000295 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100296 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000297
José Fonsecafbcf6832012-04-05 07:10:30 +0100298 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100299 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100300
José Fonseca59ee88e2012-01-15 14:24:10 +0000301 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100302 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000303
José Fonsecab89c5932012-04-01 22:47:11 +0200304 def visitReference(self, reference, instance):
305 self.visit(reference.type, instance)
306
José Fonseca54f304a2012-01-14 19:33:08 +0000307 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000308 self.visit(handle.type, instance)
309
José Fonseca54f304a2012-01-14 19:33:08 +0000310 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000311 self.visit(alias.type, instance)
312
José Fonseca54f304a2012-01-14 19:33:08 +0000313 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100314 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000315
José Fonseca54f304a2012-01-14 19:33:08 +0000316 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100317 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000318
José Fonseca54f304a2012-01-14 19:33:08 +0000319 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100320 if polymorphic.contextLess:
321 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
322 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000323 switchExpr = self.expand(polymorphic.switchExpr)
324 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100325 for cases, type in polymorphic.iterSwitch():
326 for case in cases:
327 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000328 caseInstance = instance
329 if type.expr is not None:
330 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
331 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100332 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000333 if polymorphic.defaultType is None:
334 print r' default:'
335 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
336 print r' trace::localWriter.writeNull();'
337 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100338 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100339
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340
José Fonseca0075f152012-04-14 20:25:52 +0100341class WrapDecider(stdapi.Traverser):
342 '''Type visitor which will decide wheter this type will need wrapping or not.
343
344 For complex types (arrays, structures), we need to know this before hand.
345 '''
346
347 def __init__(self):
348 self.needsWrapping = False
349
José Fonseca0075f152012-04-14 20:25:52 +0100350 def visitLinearPointer(self, void):
351 pass
352
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100353 def visitObjPointer(self, interface):
José Fonseca0075f152012-04-14 20:25:52 +0100354 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:
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100388 # All interfaces should at least implement IUnknown
389 print " WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,)
José Fonsecafbcf6832012-04-05 07:10:30 +0100390
José Fonseca54f304a2012-01-14 19:33:08 +0000391 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100392 raise NotImplementedError
393
394 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100395 print " Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100396
José Fonseca54f304a2012-01-14 19:33:08 +0000397 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100398 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100399 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000400
401
José Fonseca54f304a2012-01-14 19:33:08 +0000402class ValueUnwrapper(ValueWrapper):
403 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000404
José Fonseca0075f152012-04-14 20:25:52 +0100405 allocated = False
406
José Fonsecae7cb2b92012-09-28 08:40:24 +0100407 def visitStruct(self, struct, instance):
408 if not self.allocated:
409 # Argument is constant. We need to create a non const
410 print ' {'
411 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
412 print ' *_t = %s;' % (instance,)
413 assert instance.startswith('*')
414 print ' %s = _t;' % (instance[1:],)
415 instance = '*_t'
416 self.allocated = True
417 try:
418 return ValueWrapper.visitStruct(self, struct, instance)
419 finally:
420 print ' }'
421 else:
422 return ValueWrapper.visitStruct(self, struct, instance)
423
José Fonseca0075f152012-04-14 20:25:52 +0100424 def visitArray(self, array, instance):
425 if self.allocated or isinstance(instance, stdapi.Interface):
426 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000427 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100428 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000429 print " if (%s && %s) {" % (instance, array_length)
430 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
431 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100432 print " _t[_i] = %s[_i];" % instance
433 self.allocated = True
434 self.visit(array.type, "_t[_i]")
435 print " }"
436 print " %s = _t;" % instance
437 print " }"
438
José Fonseca9782b292012-04-14 22:02:42 +0100439 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100440 print r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
441
442
443def _getInterfaceHierarchy(allIfaces, baseIface, result):
444 for iface in allIfaces:
445 if iface.base is baseIface:
446 _getInterfaceHierarchy(allIfaces, iface, result)
447 result.append(iface)
448
449def getInterfaceHierarchy(allIfaces, baseIface):
450 result = []
451 _getInterfaceHierarchy(allIfaces, baseIface, result)
452 return result
José Fonseca87d1cc62010-11-29 15:57:25 +0000453
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000454
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000455class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000456 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000457
José Fonseca4b466a92012-11-26 19:47:26 +0000458 # 0-3 are reserved to memcpy, malloc, free, and realloc
459 __id = 4
460
José Fonsecabb8760b2011-05-25 23:21:18 +0100461 def __init__(self):
462 self.api = None
463
José Fonseca54f304a2012-01-14 19:33:08 +0000464 def serializerFactory(self):
465 '''Create a serializer.
466
467 Can be overriden by derived classes to inject their own serialzer.
468 '''
469
470 return ValueSerializer()
471
José Fonseca1b6c8752012-04-15 14:33:00 +0100472 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100473 self.api = api
474
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000475 self.header(api)
476
477 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000478 for module in api.modules:
479 for header in module.headers:
480 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000481 print
482
José Fonseca54f304a2012-01-14 19:33:08 +0000483 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000484 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000485 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000486 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000487 print
488
489 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100490 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000491
492 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100493 self.interface = None
494 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000495 for function in api.getAllFunctions():
496 self.traceFunctionDecl(function)
497 for function in api.getAllFunctions():
498 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000499 print
500
501 self.footer(api)
502
503 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100504 print '#ifdef _WIN32'
505 print '# include <malloc.h> // alloca'
506 print '# ifndef alloca'
507 print '# define alloca _alloca'
508 print '# endif'
509 print '#else'
510 print '# include <alloca.h> // alloca'
511 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100512 print
José Fonseca537c5072012-07-07 12:54:09 +0100513 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000514 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000515
516 def footer(self, api):
517 pass
518
José Fonseca54f304a2012-01-14 19:33:08 +0000519 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000520 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000521
José Fonseca84cea3b2012-05-09 21:12:30 +0100522 if not function.internal:
523 if function.args:
524 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
525 else:
526 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100527 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 +0100528 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000529
José Fonseca4b466a92012-11-26 19:47:26 +0000530 def getFunctionSigId(self):
531 id = Tracer.__id
532 Tracer.__id += 1
533 return id
534
José Fonseca54f304a2012-01-14 19:33:08 +0000535 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100536 return True
537
José Fonseca54f304a2012-01-14 19:33:08 +0000538 def traceFunctionImpl(self, function):
539 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100540 print 'extern "C" PUBLIC'
541 else:
542 print 'extern "C" PRIVATE'
543 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000544 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100545 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100546
José Fonseca9362a9f2014-10-07 21:34:49 +0100547 for arg in function.args:
548 if not arg.output:
549 self.unwrapArg(function, arg)
550
José Fonseca54f304a2012-01-14 19:33:08 +0000551 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100552
553 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
554
José Fonseca14c21bc2011-02-20 23:32:22 +0000555 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100556 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100557
José Fonseca14c21bc2011-02-20 23:32:22 +0000558 print '}'
559 print
560
José Fonseca54f304a2012-01-14 19:33:08 +0000561 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100562 if not function.internal:
563 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
564 for arg in function.args:
565 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100566 self.serializeArg(function, arg)
567 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000568 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100569 if not function.internal:
570 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000571 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100572 for arg in function.args:
573 if arg.output:
574 self.serializeArg(function, arg)
575 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000576 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100577 if function.type is not stdapi.Void:
578 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100579 if function.type is not stdapi.Void:
580 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000581 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000582
José Fonseca2cfa02c2013-06-10 08:05:29 +0100583 def invokeFunction(self, function):
584 self.doInvokeFunction(function)
585
586 def doInvokeFunction(self, function, prefix='_', suffix=''):
587 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000588 if function.type is stdapi.Void:
589 result = ''
590 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100591 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100592 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000593 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000594
José Fonseca4fb1ab02012-11-08 10:23:40 +0000595 def wasFunctionSuccessful(self, function):
596 if function.type is stdapi.Void:
597 return 'true'
598 if str(function.type) == 'HRESULT':
599 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000600 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000601
José Fonseca54f304a2012-01-14 19:33:08 +0000602 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100603 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000604 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100605 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000606
José Fonseca54f304a2012-01-14 19:33:08 +0000607 def serializeArgValue(self, function, arg):
608 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000609
José Fonseca54f304a2012-01-14 19:33:08 +0000610 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100611 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100612
613 from specs.winapi import REFIID
614 riid = None
615 for other_arg in function.args:
616 if not other_arg.output and other_arg.type is REFIID:
617 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100618 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100619 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100620 and isinstance(arg.type, stdapi.Pointer) \
621 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100622 self.wrapIid(function, riid, arg)
623 return
624
José Fonseca54f304a2012-01-14 19:33:08 +0000625 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000626
José Fonseca54f304a2012-01-14 19:33:08 +0000627 def unwrapArg(self, function, arg):
628 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000629
José Fonseca54f304a2012-01-14 19:33:08 +0000630 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100631 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000632 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100633 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000634
José Fonseca54f304a2012-01-14 19:33:08 +0000635 def serializeValue(self, type, instance):
636 serializer = self.serializerFactory()
637 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000638
José Fonseca54f304a2012-01-14 19:33:08 +0000639 def wrapRet(self, function, instance):
640 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000641
José Fonseca0075f152012-04-14 20:25:52 +0100642 def needsWrapping(self, type):
643 visitor = WrapDecider()
644 visitor.visit(type)
645 return visitor.needsWrapping
646
José Fonseca54f304a2012-01-14 19:33:08 +0000647 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100648 if self.needsWrapping(type):
649 visitor = ValueWrapper()
650 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000651
652 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100653 if self.needsWrapping(type):
654 visitor = ValueUnwrapper()
655 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000656
José Fonseca143e9252012-04-15 09:31:18 +0100657 def traceInterfaces(self, api):
658 interfaces = api.getAllInterfaces()
659 if not interfaces:
660 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100661
José Fonseca143e9252012-04-15 09:31:18 +0100662 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100663
664 # Helper functions to wrap/unwrap interface pointers
665 print r'static inline bool'
666 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
667 print r' IUnknown *pObj = NULL;'
668 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
669 print r' if (FAILED(hr)) {'
670 print r' return false;'
671 print r' }'
672 print r' assert(pObj);'
673 print r' pObj->Release();'
674 print r' return pUnknown == pObj;'
675 print r'}'
676 print
677 print r'static inline const void *'
678 print r'getVtbl(const void *pvObj) {'
679 print r' return pvObj ? *(const void **)pvObj : NULL;'
680 print r'}'
681 print
682
José Fonseca143e9252012-04-15 09:31:18 +0100683 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100684
José Fonseca143e9252012-04-15 09:31:18 +0100685 map(self.implementWrapperInterface, interfaces)
686 print
687
José Fonseca0423d2c2012-01-20 19:16:17 +0000688 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100689 wrapperInterfaceName = getWrapperInterfaceName(interface)
690 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000691 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000692 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100693 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
694 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000695 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100696 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
697 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
698 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000699 print
José Fonseca01e50592014-08-22 15:35:27 +0100700
701 methods = list(interface.iterMethods())
702 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000703 print " " + method.prototype() + ";"
704 print
José Fonseca01e50592014-08-22 15:35:27 +0100705
José Fonsecaacc90622012-05-02 13:10:07 +0100706 for type, name, value in self.enumWrapperInterfaceVariables(interface):
707 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100708 print
709
710 print r'private:'
711 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100712 print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p pVtbl=%%p\n", "%s", i, this, m_pInstance, m_pVtbl);' % interface.name
José Fonseca01e50592014-08-22 15:35:27 +0100713 print r' trace::localWriter.flush();'
714 print r' os::abort();'
715 print r' }'
716 print
717 for i in range(len(methods), 64):
718 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
719 print
720
José Fonseca0423d2c2012-01-20 19:16:17 +0000721 print "};"
722 print
723
José Fonsecaacc90622012-05-02 13:10:07 +0100724 def enumWrapperInterfaceVariables(self, interface):
725 return [
726 ("DWORD", "m_dwMagic", "0xd8365d6c"),
727 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100728 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000729 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100730 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000731
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100732 def implementWrapperInterface(self, iface):
733 self.interface = iface
734
735 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100736
José Fonsecab7a9b182012-11-23 17:02:48 +0000737 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100738 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
739 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100740 if value is not None:
741 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000742 print '}'
743 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000744
745 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100746 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
747 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100748 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100749 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 +0000750 print r' g_WrappedObjects[pInstance] = pWrapper;'
751 print r' return pWrapper;'
752 print '}'
753 print
754
755 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100756 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100757 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100758 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 +0000759 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000760 print '}'
761 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100762
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100763 baseMethods = list(iface.iterBaseMethods())
764 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100765 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100766 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100767
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000768 print
769
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100770 # Wrap pointer
771 ifaces = self.api.getAllInterfaces()
772 print r'void'
773 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
774 print r' if (!ppObj) {'
775 print r' return;'
776 print r' }'
777 print r' %s *pObj = *ppObj;' % (iface.name,)
778 print r' if (!pObj) {'
779 print r' return;'
780 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100781 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100782 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
783 print r' if (it != g_WrappedObjects.end()) {'
784 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
785 print r' assert(pWrapper);'
786 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
787 print r' assert(pWrapper->m_pInstance == pObj);'
788 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
789 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
790 if debug:
791 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
792 print r' *ppObj = pWrapper;'
793 print r' return;'
794 print r' }'
795 print r' }'
796 else_ = ''
797 for childIface in getInterfaceHierarchy(ifaces, iface):
798 print r' %sif (hasChildInterface(IID_%s, pObj)) {' % (else_, childIface.name)
799 print r' pObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
800 print r' }'
801 else_ = 'else '
802 print r' %s{' % else_
803 print r' pObj = Wrap%s::_create(entryName, pObj);' % iface.name
804 print r' }'
805 print r' *ppObj = pObj;'
806 print r'}'
807 print
808
809 # Unwrap pointer
810 print r'void'
811 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
812 print r' if (!ppObj || !*ppObj) {'
813 print r' return;'
814 print r' }'
815 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
816 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
817 print r' *ppObj = pWrapper->m_pInstance;'
818 print r' } else {'
Jose Fonseca897d0092015-06-19 22:28:42 +0100819 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100820 print r' }'
821 print r'}'
822 print
823
José Fonseca4220b1b2012-02-03 19:05:29 +0000824 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100825 wrapperInterfaceName = getWrapperInterfaceName(interface)
826
827 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000828
829 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100830 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000831
José Fonseca0423d2c2012-01-20 19:16:17 +0000832 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100833 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000834
José Fonseca9362a9f2014-10-07 21:34:49 +0100835 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
836 for arg in method.args:
837 if not arg.output:
838 self.unwrapArg(method, arg)
839
José Fonseca4220b1b2012-02-03 19:05:29 +0000840 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100841
842 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
843
José Fonseca0423d2c2012-01-20 19:16:17 +0000844 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100845 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100846
José Fonseca0423d2c2012-01-20 19:16:17 +0000847 print '}'
848 print
849
José Fonseca4220b1b2012-02-03 19:05:29 +0000850 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100851 assert not method.internal
852
José Fonseca632a78d2012-04-19 07:18:59 +0100853 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 +0100854 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 +0100855
José Fonseca632a78d2012-04-19 07:18:59 +0100856 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100857 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100858 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100859 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000860 for arg in method.args:
861 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000862 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100863 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000864
José Fonseca4220b1b2012-02-03 19:05:29 +0000865 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000866
José Fonseca632a78d2012-04-19 07:18:59 +0100867 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000868
869 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000870 for arg in method.args:
871 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000872 self.serializeArg(method, arg)
873 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000874 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000875
José Fonseca87d1cc62010-11-29 15:57:25 +0000876 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100877 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100878 if method.type is not stdapi.Void:
879 self.wrapRet(method, '_result')
880
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000881 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000882 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000883 print r' if (!_result) {'
884 print r' delete this;'
885 print r' }'
886
887 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000888
José Fonseca143e9252012-04-15 09:31:18 +0100889 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100890 ifaces = api.getAllInterfaces()
891
José Fonseca143e9252012-04-15 09:31:18 +0100892 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000893 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
José Fonseca974189a2015-02-07 23:19:46 +0000894 print r' os::log("apitrace: warning: %s: %s IID %08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100895 print r' entryName, reason,'
José Fonseca143e9252012-04-15 09:31:18 +0100896 print r' riid.Data1, riid.Data2, riid.Data3,'
897 print r' riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
José Fonseca92624532015-02-07 23:20:37 +0000898 print r' void * pVtbl = *(void **)pvObj;'
899 print r' HMODULE hModule = 0;'
Jose Fonsecaa316c6e2015-07-10 11:07:10 +0100900 print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
901 print r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
José Fonseca92624532015-02-07 23:20:37 +0000902 print r' (LPCTSTR)pVtbl,'
903 print r' &hModule);'
904 print r' assert(bRet);'
905 print r' if (bRet) {'
906 print r' char szModule[MAX_PATH];'
907 print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
908 print r' assert(dwRet);'
909 print r' if (dwRet) {'
910 print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
911 print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
912 print r' }'
913 print r' }'
José Fonseca143e9252012-04-15 09:31:18 +0100914 print r'}'
915 print
916 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100917 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100918 print r' if (!ppvObj || !*ppvObj) {'
919 print r' return;'
920 print r' }'
921 else_ = ''
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100922 for iface in ifaces:
José Fonseca143e9252012-04-15 09:31:18 +0100923 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100924 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100925 print r' }'
926 else_ = 'else '
927 print r' %s{' % else_
José Fonseca92624532015-02-07 23:20:37 +0000928 print r' warnIID(entryName, riid, *ppvObj, "unknown");'
José Fonseca143e9252012-04-15 09:31:18 +0100929 print r' }'
930 print r'}'
931 print
932
José Fonsecabcb26b22012-04-15 08:42:25 +0100933 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100934 # Cast output arg to `void **` if necessary
935 out_name = out.name
936 obj_type = out.type.type.type
937 if not obj_type is stdapi.Void:
938 assert isinstance(obj_type, stdapi.Interface)
939 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
940
José Fonsecabcb26b22012-04-15 08:42:25 +0100941 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100942 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100943 else_ = ''
944 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100945 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100946 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100947 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100948 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100949 print r' }'
950 else_ = 'else '
951 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100952 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100953 print r' }'
954 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000955
José Fonseca4220b1b2012-02-03 19:05:29 +0000956 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000957 if method.type is stdapi.Void:
958 result = ''
959 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100960 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100961 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000962
José Fonseca6f0e3032014-06-25 01:00:35 +0100963 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100964 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100965
966 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100967 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100968 for arg, instance in zip(function.args, args):
969 assert not arg.output
970 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
971 self.serializeValue(arg.type, instance)
972 print ' trace::localWriter.endArg();'
973 print ' trace::localWriter.endEnter();'
974 print ' trace::localWriter.beginLeave(_fake_call);'
975 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000976