blob: cb510246fe1d2e61a9d70ce66bf8c8abe07e139a [file] [log] [blame]
José Fonseca8fbdd3a2010-11-23 20:55:07 +00001##########################################################################
2#
3# Copyright 2008-2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
José Fonseca73d0a962010-11-29 14:49:34 +000026"""Common trace code generation."""
José Fonseca8fbdd3a2010-11-23 20:55:07 +000027
28
José Fonseca452d3252012-04-14 15:55:40 +010029# Adjust path
30import os.path
31import sys
32sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
33
José Fonsecaf7e2fb32014-08-22 15:33:28 +010034import itertools
José Fonseca452d3252012-04-14 15:55:40 +010035
José Fonsecabd86a222011-09-27 09:21:38 +010036import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000037
38
José Fonseca0423d2c2012-01-20 19:16:17 +000039def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000040 return "Wrap" + interface.expr
41
José Fonseca6fac5ae2010-11-29 16:09:13 +000042
José Fonsecaab623c52014-07-22 17:05:00 +010043debug = False
44
José Fonsecaf6b05132012-11-06 00:16:28 +000045
José Fonseca54f304a2012-01-14 19:33:08 +000046class ComplexValueSerializer(stdapi.OnceVisitor):
47 '''Type visitors which generates serialization functions for
48 complex types.
49
50 Simple types are serialized inline.
51 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000052
José Fonseca54f304a2012-01-14 19:33:08 +000053 def __init__(self, serializer):
54 stdapi.OnceVisitor.__init__(self)
55 self.serializer = serializer
56
57 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000058 pass
59
José Fonseca54f304a2012-01-14 19:33:08 +000060 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000061 pass
62
José Fonseca54f304a2012-01-14 19:33:08 +000063 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000064 pass
65
José Fonseca54f304a2012-01-14 19:33:08 +000066 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000067 self.visit(const.type)
68
José Fonseca54f304a2012-01-14 19:33:08 +000069 def visitStruct(self, struct):
Jose Fonsecada621b52015-08-13 15:50:46 +010070 # Ensure member array has nonzero length to avoid MSVC error C2466
71 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, max(len(struct.members), 1))
José Fonseca7eef8ce2010-11-26 15:46:36 +000072 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000073 if name is None:
74 print ' "",'
75 else:
76 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000077 print '};'
78 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000079 if struct.name is None:
80 structName = '""'
81 else:
82 structName = '"%s"' % struct.name
83 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000084 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000085 print
86
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000088 self.visit(array.type)
89
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020090 def visitAttribArray(self, array):
91 pass
92
José Fonseca54f304a2012-01-14 19:33:08 +000093 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000094 pass
95
José Fonseca54f304a2012-01-14 19:33:08 +000096 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010097 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000098 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000099 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +0000100 print '};'
101 print
José Fonseca632a78d2012-04-19 07:18:59 +0100102 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000103 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000104 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000105 print
106
José Fonseca54f304a2012-01-14 19:33:08 +0000107 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100108 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000109 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000110 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000111 print '};'
112 print
José Fonseca632a78d2012-04-19 07:18:59 +0100113 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000114 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000115 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000116 print
117
José Fonseca54f304a2012-01-14 19:33:08 +0000118 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000119 self.visit(pointer.type)
120
José Fonseca59ee88e2012-01-15 14:24:10 +0000121 def visitIntPointer(self, pointer):
122 pass
123
José Fonsecafbcf6832012-04-05 07:10:30 +0100124 def visitObjPointer(self, pointer):
125 self.visit(pointer.type)
126
José Fonseca59ee88e2012-01-15 14:24:10 +0000127 def visitLinearPointer(self, pointer):
128 self.visit(pointer.type)
129
José Fonseca54f304a2012-01-14 19:33:08 +0000130 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000131 self.visit(handle.type)
132
José Fonsecab89c5932012-04-01 22:47:11 +0200133 def visitReference(self, reference):
134 self.visit(reference.type)
135
José Fonseca54f304a2012-01-14 19:33:08 +0000136 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000137 self.visit(alias.type)
138
José Fonseca54f304a2012-01-14 19:33:08 +0000139 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000140 pass
141
José Fonseca54f304a2012-01-14 19:33:08 +0000142 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000143 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000144
José Fonseca54f304a2012-01-14 19:33:08 +0000145 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100146 if not polymorphic.contextLess:
147 return
José Fonsecafbc51922013-04-14 14:45:04 +0100148 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100149 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000150 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100151 for case in cases:
152 print ' %s:' % case
Jose Fonsecae28c4e92015-01-25 09:53:23 +0000153 self.serializer.visit(type, '(%s)(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100154 print ' break;'
155 print ' }'
156 print '}'
157 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100158
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000159
José Fonsecadbf714b2012-11-20 17:03:43 +0000160class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000161 '''Visitor which generates code to serialize any type.
162
163 Simple types are serialized inline here, whereas the serialization of
164 complex types is dispatched to the serialization functions generated by
165 ComplexValueSerializer visitor above.
166 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000167
José Fonseca54f304a2012-01-14 19:33:08 +0000168 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100169 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000170
José Fonseca54f304a2012-01-14 19:33:08 +0000171 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100172 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000173 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100174 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000175 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100176 cast = 'const wchar_t *'
177 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000178 if cast != string.expr:
179 # reinterpret_cast is necessary for GLubyte * <=> char *
180 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
181 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000182 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000183 else:
184 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100185 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000186
José Fonseca54f304a2012-01-14 19:33:08 +0000187 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000188 self.visit(const.type, instance)
189
José Fonseca54f304a2012-01-14 19:33:08 +0000190 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000191 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000192 for member in struct.members:
193 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000194 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000195
José Fonseca54f304a2012-01-14 19:33:08 +0000196 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100197 length = '_c' + array.type.tag
198 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000199 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100200 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000201 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100202 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100203 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100204 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000205 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100206 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000207 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100208 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100209 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100210 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100211 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000212
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200213 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200214 # For each element, decide if it is a key or a value (which depends on the previous key).
215 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
216 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200217
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200218 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100219 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100220 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200221 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200222 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
223 % {'c': count, 'array': instance, 'terminator': array.terminator}
224 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200225 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200226 for key, valueType in array.valueTypes:
227 if valueType is None:
228 print ' case %s:' % key
229 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
230 print ' break;'
231 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200232 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200233 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200234 print ' trace::localWriter.beginArray(%s);' % count
235
236 # for each key / key-value pair write the key and the value, if the key requires one
237
José Fonseca77c10d82013-07-20 15:27:29 +0100238 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200239 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200240 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100241 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200242 print ' trace::localWriter.endElement();'
243 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
244 print ' break;'
245 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200246 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200247 # write generic value the usual way
248 for key, valueType in array.valueTypes:
249 if valueType is not None:
250 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200251 print ' trace::localWriter.beginElement();'
252 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
253 print ' trace::localWriter.endElement();'
254 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200255 # known key with no value, just decrease the index so we treat the next value as a key
256 if array.hasKeysWithoutValues:
257 for key, valueType in array.valueTypes:
258 if valueType is None:
259 print ' case %s:' % key
260 print ' %s--;' % index
261 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200262 # unknown key, write an int value
263 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200264 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200265 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100266 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200267 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200268 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200269 print ' break;'
270 print ' }'
271 print ' }'
272 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100273 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200274
275
José Fonseca54f304a2012-01-14 19:33:08 +0000276 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000277 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000278
José Fonseca54f304a2012-01-14 19:33:08 +0000279 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100280 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000281
José Fonseca54f304a2012-01-14 19:33:08 +0000282 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100283 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000284
José Fonseca54f304a2012-01-14 19:33:08 +0000285 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100286 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100287 print ' trace::localWriter.beginArray(1);'
288 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000289 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100290 print ' trace::localWriter.endElement();'
291 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100292 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100293 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100294 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000295
José Fonseca59ee88e2012-01-15 14:24:10 +0000296 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100297 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000298
José Fonsecafbcf6832012-04-05 07:10:30 +0100299 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100300 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100301
José Fonseca59ee88e2012-01-15 14:24:10 +0000302 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100303 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000304
José Fonsecab89c5932012-04-01 22:47:11 +0200305 def visitReference(self, reference, instance):
306 self.visit(reference.type, instance)
307
José Fonseca54f304a2012-01-14 19:33:08 +0000308 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000309 self.visit(handle.type, instance)
310
José Fonseca54f304a2012-01-14 19:33:08 +0000311 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000312 self.visit(alias.type, instance)
313
José Fonseca54f304a2012-01-14 19:33:08 +0000314 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100315 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000316
José Fonseca54f304a2012-01-14 19:33:08 +0000317 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100318 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000319
José Fonseca54f304a2012-01-14 19:33:08 +0000320 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100321 if polymorphic.contextLess:
322 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
323 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000324 switchExpr = self.expand(polymorphic.switchExpr)
325 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100326 for cases, type in polymorphic.iterSwitch():
327 for case in cases:
328 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000329 caseInstance = instance
330 if type.expr is not None:
331 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
332 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100333 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000334 if polymorphic.defaultType is None:
335 print r' default:'
336 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
337 print r' trace::localWriter.writeNull();'
338 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100339 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100340
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000341
José Fonseca0075f152012-04-14 20:25:52 +0100342class WrapDecider(stdapi.Traverser):
343 '''Type visitor which will decide wheter this type will need wrapping or not.
344
345 For complex types (arrays, structures), we need to know this before hand.
346 '''
347
348 def __init__(self):
349 self.needsWrapping = False
350
José Fonseca0075f152012-04-14 20:25:52 +0100351 def visitLinearPointer(self, void):
352 pass
353
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100354 def visitObjPointer(self, interface):
José Fonseca0075f152012-04-14 20:25:52 +0100355 self.needsWrapping = True
356
357
José Fonsecadbf714b2012-11-20 17:03:43 +0000358class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000359 '''Type visitor which will generate the code to wrap an instance.
360
361 Wrapping is necessary mostly for interfaces, however interface pointers can
362 appear anywhere inside complex types.
363 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000364
José Fonseca54f304a2012-01-14 19:33:08 +0000365 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000366 for member in struct.members:
367 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000368
José Fonseca54f304a2012-01-14 19:33:08 +0000369 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000370 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100371 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000372 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
373 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100374 print " }"
375 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000376
José Fonseca54f304a2012-01-14 19:33:08 +0000377 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100378 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000379 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100380 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000381
José Fonsecafbcf6832012-04-05 07:10:30 +0100382 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100383 elem_type = pointer.type.mutable()
384 if isinstance(elem_type, stdapi.Interface):
385 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100386 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
387 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100388 else:
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100389 # All interfaces should at least implement IUnknown
390 print " WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,)
José Fonsecafbcf6832012-04-05 07:10:30 +0100391
José Fonseca54f304a2012-01-14 19:33:08 +0000392 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100393 raise NotImplementedError
394
395 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100396 print " Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100397
José Fonseca54f304a2012-01-14 19:33:08 +0000398 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100399 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100400 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000401
402
José Fonseca54f304a2012-01-14 19:33:08 +0000403class ValueUnwrapper(ValueWrapper):
404 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000405
José Fonseca0075f152012-04-14 20:25:52 +0100406 allocated = False
407
José Fonsecae7cb2b92012-09-28 08:40:24 +0100408 def visitStruct(self, struct, instance):
409 if not self.allocated:
410 # Argument is constant. We need to create a non const
411 print ' {'
412 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
413 print ' *_t = %s;' % (instance,)
414 assert instance.startswith('*')
415 print ' %s = _t;' % (instance[1:],)
416 instance = '*_t'
417 self.allocated = True
418 try:
419 return ValueWrapper.visitStruct(self, struct, instance)
420 finally:
421 print ' }'
422 else:
423 return ValueWrapper.visitStruct(self, struct, instance)
424
José Fonseca0075f152012-04-14 20:25:52 +0100425 def visitArray(self, array, instance):
426 if self.allocated or isinstance(instance, stdapi.Interface):
427 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000428 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100429 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000430 print " if (%s && %s) {" % (instance, array_length)
431 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
432 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100433 print " _t[_i] = %s[_i];" % instance
434 self.allocated = True
435 self.visit(array.type, "_t[_i]")
436 print " }"
437 print " %s = _t;" % instance
438 print " }"
439
José Fonseca9782b292012-04-14 22:02:42 +0100440 def visitInterfacePointer(self, interface, instance):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100441 print r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
442
443
444def _getInterfaceHierarchy(allIfaces, baseIface, result):
445 for iface in allIfaces:
446 if iface.base is baseIface:
447 _getInterfaceHierarchy(allIfaces, iface, result)
448 result.append(iface)
449
450def getInterfaceHierarchy(allIfaces, baseIface):
451 result = []
452 _getInterfaceHierarchy(allIfaces, baseIface, result)
453 return result
José Fonseca87d1cc62010-11-29 15:57:25 +0000454
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000455
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000456class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000457 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000458
José Fonseca4b466a92012-11-26 19:47:26 +0000459 # 0-3 are reserved to memcpy, malloc, free, and realloc
460 __id = 4
461
José Fonsecabb8760b2011-05-25 23:21:18 +0100462 def __init__(self):
463 self.api = None
464
José Fonseca54f304a2012-01-14 19:33:08 +0000465 def serializerFactory(self):
466 '''Create a serializer.
467
468 Can be overriden by derived classes to inject their own serialzer.
469 '''
470
471 return ValueSerializer()
472
José Fonseca1b6c8752012-04-15 14:33:00 +0100473 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100474 self.api = api
475
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000476 self.header(api)
477
478 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000479 for module in api.modules:
480 for header in module.headers:
481 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000482 print
483
José Fonseca54f304a2012-01-14 19:33:08 +0000484 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000485 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000486 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000487 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000488 print
489
490 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100491 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000492
493 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100494 self.interface = None
495 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000496 for function in api.getAllFunctions():
497 self.traceFunctionDecl(function)
498 for function in api.getAllFunctions():
499 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000500 print
501
502 self.footer(api)
503
504 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100505 print '#ifdef _WIN32'
506 print '# include <malloc.h> // alloca'
507 print '# ifndef alloca'
508 print '# define alloca _alloca'
509 print '# endif'
510 print '#else'
511 print '# include <alloca.h> // alloca'
512 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100513 print
José Fonseca537c5072012-07-07 12:54:09 +0100514 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000515 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000516
517 def footer(self, api):
518 pass
519
José Fonseca54f304a2012-01-14 19:33:08 +0000520 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000521 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000522
José Fonseca84cea3b2012-05-09 21:12:30 +0100523 if not function.internal:
524 if function.args:
525 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
526 else:
527 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100528 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 +0100529 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000530
José Fonseca4b466a92012-11-26 19:47:26 +0000531 def getFunctionSigId(self):
532 id = Tracer.__id
533 Tracer.__id += 1
534 return id
535
José Fonseca54f304a2012-01-14 19:33:08 +0000536 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100537 return True
538
José Fonseca54f304a2012-01-14 19:33:08 +0000539 def traceFunctionImpl(self, function):
540 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100541 print 'extern "C" PUBLIC'
542 else:
543 print 'extern "C" PRIVATE'
544 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000545 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100546 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100547
José Fonseca9362a9f2014-10-07 21:34:49 +0100548 for arg in function.args:
549 if not arg.output:
550 self.unwrapArg(function, arg)
551
José Fonseca54f304a2012-01-14 19:33:08 +0000552 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100553
554 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
555
José Fonseca14c21bc2011-02-20 23:32:22 +0000556 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100557 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100558
José Fonseca14c21bc2011-02-20 23:32:22 +0000559 print '}'
560 print
561
José Fonseca54f304a2012-01-14 19:33:08 +0000562 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100563 if not function.internal:
564 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
565 for arg in function.args:
566 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100567 self.serializeArg(function, arg)
568 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000569 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100570 if not function.internal:
571 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000572 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100573 for arg in function.args:
574 if arg.output:
575 self.serializeArg(function, arg)
576 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000577 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100578 if function.type is not stdapi.Void:
579 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100580 if function.type is not stdapi.Void:
581 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000582 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000583
José Fonseca2cfa02c2013-06-10 08:05:29 +0100584 def invokeFunction(self, function):
585 self.doInvokeFunction(function)
586
587 def doInvokeFunction(self, function, prefix='_', suffix=''):
588 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000589 if function.type is stdapi.Void:
590 result = ''
591 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100592 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100593 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000594 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000595
José Fonseca4fb1ab02012-11-08 10:23:40 +0000596 def wasFunctionSuccessful(self, function):
597 if function.type is stdapi.Void:
598 return 'true'
599 if str(function.type) == 'HRESULT':
600 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000601 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000602
José Fonseca54f304a2012-01-14 19:33:08 +0000603 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100604 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000605 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100606 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000607
José Fonseca54f304a2012-01-14 19:33:08 +0000608 def serializeArgValue(self, function, arg):
609 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000610
José Fonseca54f304a2012-01-14 19:33:08 +0000611 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100612 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100613
614 from specs.winapi import REFIID
615 riid = None
616 for other_arg in function.args:
617 if not other_arg.output and other_arg.type is REFIID:
618 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100619 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100620 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100621 and isinstance(arg.type, stdapi.Pointer) \
622 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100623 self.wrapIid(function, riid, arg)
624 return
625
José Fonseca54f304a2012-01-14 19:33:08 +0000626 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca54f304a2012-01-14 19:33:08 +0000628 def unwrapArg(self, function, arg):
629 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000630
José Fonseca54f304a2012-01-14 19:33:08 +0000631 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100632 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000633 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100634 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000635
José Fonseca54f304a2012-01-14 19:33:08 +0000636 def serializeValue(self, type, instance):
637 serializer = self.serializerFactory()
638 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000639
José Fonseca54f304a2012-01-14 19:33:08 +0000640 def wrapRet(self, function, instance):
641 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000642
José Fonseca0075f152012-04-14 20:25:52 +0100643 def needsWrapping(self, type):
644 visitor = WrapDecider()
645 visitor.visit(type)
646 return visitor.needsWrapping
647
José Fonseca54f304a2012-01-14 19:33:08 +0000648 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100649 if self.needsWrapping(type):
650 visitor = ValueWrapper()
651 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000652
653 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100654 if self.needsWrapping(type):
655 visitor = ValueUnwrapper()
656 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000657
José Fonseca143e9252012-04-15 09:31:18 +0100658 def traceInterfaces(self, api):
659 interfaces = api.getAllInterfaces()
660 if not interfaces:
661 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100662
Jose Fonseca82dbc602015-08-13 12:22:07 +0100663 print r'#include "guids.hpp"'
664 print
665
José Fonseca143e9252012-04-15 09:31:18 +0100666 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100667
668 # Helper functions to wrap/unwrap interface pointers
669 print r'static inline bool'
670 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
671 print r' IUnknown *pObj = NULL;'
672 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
673 print r' if (FAILED(hr)) {'
674 print r' return false;'
675 print r' }'
676 print r' assert(pObj);'
677 print r' pObj->Release();'
678 print r' return pUnknown == pObj;'
679 print r'}'
680 print
681 print r'static inline const void *'
682 print r'getVtbl(const void *pvObj) {'
683 print r' return pvObj ? *(const void **)pvObj : NULL;'
684 print r'}'
685 print
686
José Fonseca143e9252012-04-15 09:31:18 +0100687 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100688
José Fonseca143e9252012-04-15 09:31:18 +0100689 map(self.implementWrapperInterface, interfaces)
690 print
691
José Fonseca0423d2c2012-01-20 19:16:17 +0000692 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100693 wrapperInterfaceName = getWrapperInterfaceName(interface)
694 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000695 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000696 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100697 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
698 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000699 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100700 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
701 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
702 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000703 print
José Fonseca01e50592014-08-22 15:35:27 +0100704
705 methods = list(interface.iterMethods())
706 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000707 print " " + method.prototype() + ";"
708 print
José Fonseca01e50592014-08-22 15:35:27 +0100709
José Fonsecaacc90622012-05-02 13:10:07 +0100710 for type, name, value in self.enumWrapperInterfaceVariables(interface):
711 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100712 print
713
714 print r'private:'
715 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100716 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 +0100717 print r' trace::localWriter.flush();'
718 print r' os::abort();'
719 print r' }'
720 print
721 for i in range(len(methods), 64):
722 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
723 print
724
José Fonseca0423d2c2012-01-20 19:16:17 +0000725 print "};"
726 print
727
José Fonsecaacc90622012-05-02 13:10:07 +0100728 def enumWrapperInterfaceVariables(self, interface):
729 return [
730 ("DWORD", "m_dwMagic", "0xd8365d6c"),
731 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100732 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000733 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100734 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000735
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100736 def implementWrapperInterface(self, iface):
737 self.interface = iface
738
739 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100740
José Fonsecab7a9b182012-11-23 17:02:48 +0000741 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100742 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
743 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100744 if value is not None:
745 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000746 print '}'
747 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000748
749 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100750 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
751 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100752 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100753 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 +0000754 print r' g_WrappedObjects[pInstance] = pWrapper;'
755 print r' return pWrapper;'
756 print '}'
757 print
758
759 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100760 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100761 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100762 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 +0000763 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000764 print '}'
765 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100766
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100767 baseMethods = list(iface.iterBaseMethods())
768 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100769 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100770 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100771
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000772 print
773
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100774 # Wrap pointer
775 ifaces = self.api.getAllInterfaces()
776 print r'void'
777 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
778 print r' if (!ppObj) {'
779 print r' return;'
780 print r' }'
781 print r' %s *pObj = *ppObj;' % (iface.name,)
782 print r' if (!pObj) {'
783 print r' return;'
784 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100785 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100786 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
787 print r' if (it != g_WrappedObjects.end()) {'
788 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
789 print r' assert(pWrapper);'
790 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
791 print r' assert(pWrapper->m_pInstance == pObj);'
792 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
793 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
794 if debug:
795 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
796 print r' *ppObj = pWrapper;'
797 print r' return;'
798 print r' }'
799 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100800 for childIface in getInterfaceHierarchy(ifaces, iface):
Jose Fonseca971c9512015-08-12 11:07:34 +0100801 print r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
802 print r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
803 print r' return;'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100804 print r' }'
Jose Fonseca971c9512015-08-12 11:07:34 +0100805 print r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100806 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
Jose Fonseca07b5f132015-07-30 15:12:40 +0100820 print r' trace::localWriter.flush();'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100821 print r' }'
822 print r'}'
823 print
824
José Fonseca4220b1b2012-02-03 19:05:29 +0000825 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100826 wrapperInterfaceName = getWrapperInterfaceName(interface)
827
828 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000829
830 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100831 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000832
José Fonseca0423d2c2012-01-20 19:16:17 +0000833 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100834 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000835
José Fonseca9362a9f2014-10-07 21:34:49 +0100836 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
837 for arg in method.args:
838 if not arg.output:
839 self.unwrapArg(method, arg)
840
José Fonseca4220b1b2012-02-03 19:05:29 +0000841 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100842
843 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
844
José Fonseca0423d2c2012-01-20 19:16:17 +0000845 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100846 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100847
José Fonseca0423d2c2012-01-20 19:16:17 +0000848 print '}'
849 print
850
José Fonseca4220b1b2012-02-03 19:05:29 +0000851 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100852 assert not method.internal
853
José Fonseca632a78d2012-04-19 07:18:59 +0100854 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 +0100855 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 +0100856
José Fonseca632a78d2012-04-19 07:18:59 +0100857 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100858 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100859 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100860 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000861 for arg in method.args:
862 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000863 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100864 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000865
José Fonseca4220b1b2012-02-03 19:05:29 +0000866 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000867
José Fonseca632a78d2012-04-19 07:18:59 +0100868 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000869
870 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000871 for arg in method.args:
872 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000873 self.serializeArg(method, arg)
874 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000875 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000876
José Fonseca87d1cc62010-11-29 15:57:25 +0000877 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100878 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100879 if method.type is not stdapi.Void:
880 self.wrapRet(method, '_result')
881
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000882 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000883 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000884 print r' if (!_result) {'
885 print r' delete this;'
886 print r' }'
887
888 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000889
José Fonseca143e9252012-04-15 09:31:18 +0100890 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100891 ifaces = api.getAllInterfaces()
892
José Fonseca143e9252012-04-15 09:31:18 +0100893 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000894 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100895 print r' os::log("apitrace: warning: %s: %s IID %s\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100896 print r' entryName, reason,'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100897 print r' getGuidName(riid));'
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' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100921 for iface in ifaces:
Jose Fonseca971c9512015-08-12 11:07:34 +0100922 print r' if (riid == IID_%s) {' % (iface.name,)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100923 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
Jose Fonseca971c9512015-08-12 11:07:34 +0100924 print r' return;'
José Fonseca143e9252012-04-15 09:31:18 +0100925 print r' }'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100926 print r' warnIID(entryName, riid, *ppvObj, "unsupported");'
José Fonseca143e9252012-04-15 09:31:18 +0100927 print r'}'
928 print
929
José Fonsecabcb26b22012-04-15 08:42:25 +0100930 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100931 # Cast output arg to `void **` if necessary
932 out_name = out.name
933 obj_type = out.type.type.type
934 if not obj_type is stdapi.Void:
935 assert isinstance(obj_type, stdapi.Interface)
936 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
937
José Fonsecabcb26b22012-04-15 08:42:25 +0100938 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100939 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100940 else_ = ''
941 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100942 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100943 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100944 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100945 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100946 print r' }'
947 else_ = 'else '
948 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100949 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100950 print r' }'
951 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000952
José Fonseca4220b1b2012-02-03 19:05:29 +0000953 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000954 if method.type is stdapi.Void:
955 result = ''
956 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100957 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100958 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000959
José Fonseca6f0e3032014-06-25 01:00:35 +0100960 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100961 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100962
963 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100964 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100965 for arg, instance in zip(function.args, args):
966 assert not arg.output
967 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
968 self.serializeValue(arg.type, instance)
969 print ' trace::localWriter.endArg();'
970 print ' trace::localWriter.endEnter();'
971 print ' trace::localWriter.beginLeave(_fake_call);'
972 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000973