blob: a43841fc2fc404009dd24db3e2dc652d4ef4f692 [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():
Jose Fonseca00eba862016-01-26 12:30:54 +0000499 try:
500 self.traceFunctionImpl(function)
501 except:
502 sys.stderr.write("error: %s: exception\n" % function.name)
503 raise
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000504 print
505
506 self.footer(api)
507
508 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100509 print '#ifdef _WIN32'
510 print '# include <malloc.h> // alloca'
511 print '# ifndef alloca'
512 print '# define alloca _alloca'
513 print '# endif'
514 print '#else'
515 print '# include <alloca.h> // alloca'
516 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100517 print
José Fonseca537c5072012-07-07 12:54:09 +0100518 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000519 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000520
521 def footer(self, api):
522 pass
523
José Fonseca54f304a2012-01-14 19:33:08 +0000524 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000525 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000526
José Fonseca84cea3b2012-05-09 21:12:30 +0100527 if not function.internal:
528 if function.args:
529 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
530 else:
531 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100532 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 +0100533 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000534
José Fonseca4b466a92012-11-26 19:47:26 +0000535 def getFunctionSigId(self):
536 id = Tracer.__id
537 Tracer.__id += 1
538 return id
539
José Fonseca54f304a2012-01-14 19:33:08 +0000540 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100541 return True
542
José Fonseca54f304a2012-01-14 19:33:08 +0000543 def traceFunctionImpl(self, function):
544 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100545 print 'extern "C" PUBLIC'
546 else:
547 print 'extern "C" PRIVATE'
548 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000549 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100550 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100551
José Fonseca9362a9f2014-10-07 21:34:49 +0100552 for arg in function.args:
553 if not arg.output:
554 self.unwrapArg(function, arg)
555
José Fonseca54f304a2012-01-14 19:33:08 +0000556 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100557
558 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
559
José Fonseca14c21bc2011-02-20 23:32:22 +0000560 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100561 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100562
José Fonseca14c21bc2011-02-20 23:32:22 +0000563 print '}'
564 print
565
José Fonseca54f304a2012-01-14 19:33:08 +0000566 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100567 if not function.internal:
568 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
569 for arg in function.args:
570 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100571 self.serializeArg(function, arg)
572 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000573 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100574 if not function.internal:
575 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000576 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100577 for arg in function.args:
578 if arg.output:
579 self.serializeArg(function, arg)
580 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000581 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100582 if function.type is not stdapi.Void:
583 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100584 if function.type is not stdapi.Void:
585 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000586 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000587
José Fonseca2cfa02c2013-06-10 08:05:29 +0100588 def invokeFunction(self, function):
589 self.doInvokeFunction(function)
590
591 def doInvokeFunction(self, function, prefix='_', suffix=''):
592 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000593 if function.type is stdapi.Void:
594 result = ''
595 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100596 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100597 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000598 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000599
José Fonseca4fb1ab02012-11-08 10:23:40 +0000600 def wasFunctionSuccessful(self, function):
601 if function.type is stdapi.Void:
602 return 'true'
603 if str(function.type) == 'HRESULT':
604 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000605 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000606
José Fonseca54f304a2012-01-14 19:33:08 +0000607 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100608 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000609 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100610 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000611
José Fonseca54f304a2012-01-14 19:33:08 +0000612 def serializeArgValue(self, function, arg):
613 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000614
José Fonseca54f304a2012-01-14 19:33:08 +0000615 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100616 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100617
618 from specs.winapi import REFIID
619 riid = None
620 for other_arg in function.args:
621 if not other_arg.output and other_arg.type is REFIID:
622 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100623 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100624 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100625 and isinstance(arg.type, stdapi.Pointer) \
626 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100627 self.wrapIid(function, riid, arg)
628 return
629
José Fonseca54f304a2012-01-14 19:33:08 +0000630 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000631
José Fonseca54f304a2012-01-14 19:33:08 +0000632 def unwrapArg(self, function, arg):
633 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000634
José Fonseca54f304a2012-01-14 19:33:08 +0000635 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100636 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000637 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100638 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000639
José Fonseca54f304a2012-01-14 19:33:08 +0000640 def serializeValue(self, type, instance):
641 serializer = self.serializerFactory()
642 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000643
José Fonseca54f304a2012-01-14 19:33:08 +0000644 def wrapRet(self, function, instance):
645 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000646
José Fonseca0075f152012-04-14 20:25:52 +0100647 def needsWrapping(self, type):
648 visitor = WrapDecider()
649 visitor.visit(type)
650 return visitor.needsWrapping
651
José Fonseca54f304a2012-01-14 19:33:08 +0000652 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100653 if self.needsWrapping(type):
654 visitor = ValueWrapper()
655 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000656
657 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100658 if self.needsWrapping(type):
659 visitor = ValueUnwrapper()
660 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000661
José Fonseca143e9252012-04-15 09:31:18 +0100662 def traceInterfaces(self, api):
663 interfaces = api.getAllInterfaces()
664 if not interfaces:
665 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100666
Jose Fonseca82dbc602015-08-13 12:22:07 +0100667 print r'#include "guids.hpp"'
668 print
669
José Fonseca143e9252012-04-15 09:31:18 +0100670 map(self.declareWrapperInterface, interfaces)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100671
672 # Helper functions to wrap/unwrap interface pointers
673 print r'static inline bool'
674 print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
675 print r' IUnknown *pObj = NULL;'
676 print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
677 print r' if (FAILED(hr)) {'
678 print r' return false;'
679 print r' }'
680 print r' assert(pObj);'
681 print r' pObj->Release();'
682 print r' return pUnknown == pObj;'
683 print r'}'
684 print
685 print r'static inline const void *'
686 print r'getVtbl(const void *pvObj) {'
687 print r' return pvObj ? *(const void **)pvObj : NULL;'
688 print r'}'
689 print
690
José Fonseca143e9252012-04-15 09:31:18 +0100691 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100692
José Fonseca143e9252012-04-15 09:31:18 +0100693 map(self.implementWrapperInterface, interfaces)
694 print
695
José Fonseca0423d2c2012-01-20 19:16:17 +0000696 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100697 wrapperInterfaceName = getWrapperInterfaceName(interface)
698 print "class %s : public %s " % (wrapperInterfaceName, interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000699 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000700 print "private:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100701 print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
702 print " virtual ~%s();" % wrapperInterfaceName
José Fonsecab7a9b182012-11-23 17:02:48 +0000703 print "public:"
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100704 print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
705 print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
706 print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
José Fonseca0423d2c2012-01-20 19:16:17 +0000707 print
José Fonseca01e50592014-08-22 15:35:27 +0100708
709 methods = list(interface.iterMethods())
710 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000711 print " " + method.prototype() + ";"
712 print
José Fonseca01e50592014-08-22 15:35:27 +0100713
José Fonsecaacc90622012-05-02 13:10:07 +0100714 for type, name, value in self.enumWrapperInterfaceVariables(interface):
715 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100716 print
717
718 print r'private:'
719 print r' void _dummy(unsigned i) const {'
José Fonseca21b2d8e2014-09-14 21:26:51 +0100720 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 +0100721 print r' trace::localWriter.flush();'
722 print r' os::abort();'
723 print r' }'
724 print
725 for i in range(len(methods), 64):
726 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
727 print
728
José Fonseca0423d2c2012-01-20 19:16:17 +0000729 print "};"
730 print
731
José Fonsecaacc90622012-05-02 13:10:07 +0100732 def enumWrapperInterfaceVariables(self, interface):
733 return [
734 ("DWORD", "m_dwMagic", "0xd8365d6c"),
735 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100736 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000737 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100738 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000739
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100740 def implementWrapperInterface(self, iface):
741 self.interface = iface
742
743 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100744
José Fonsecab7a9b182012-11-23 17:02:48 +0000745 # Private constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100746 print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
747 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100748 if value is not None:
749 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000750 print '}'
751 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000752
753 # Public constructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100754 print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
755 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100756 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100757 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 +0000758 print r' g_WrappedObjects[pInstance] = pWrapper;'
759 print r' return pWrapper;'
760 print '}'
761 print
762
763 # Destructor
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100764 print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
José Fonsecaab623c52014-07-22 17:05:00 +0100765 if debug:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100766 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 +0000767 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000768 print '}'
769 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100770
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100771 baseMethods = list(iface.iterBaseMethods())
772 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100773 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100774 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100775
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000776 print
777
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100778 # Wrap pointer
779 ifaces = self.api.getAllInterfaces()
780 print r'void'
781 print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
782 print r' if (!ppObj) {'
783 print r' return;'
784 print r' }'
785 print r' %s *pObj = *ppObj;' % (iface.name,)
786 print r' if (!pObj) {'
787 print r' return;'
788 print r' }'
José Fonsecad2bff852014-09-14 21:23:15 +0100789 print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100790 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
791 print r' if (it != g_WrappedObjects.end()) {'
792 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
793 print r' assert(pWrapper);'
794 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
795 print r' assert(pWrapper->m_pInstance == pObj);'
796 print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
797 print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
798 if debug:
799 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
800 print r' *ppObj = pWrapper;'
801 print r' return;'
802 print r' }'
803 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100804 for childIface in getInterfaceHierarchy(ifaces, iface):
Jose Fonseca971c9512015-08-12 11:07:34 +0100805 print r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
806 print r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
807 print r' return;'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100808 print r' }'
Jose Fonseca971c9512015-08-12 11:07:34 +0100809 print r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100810 print r'}'
811 print
812
813 # Unwrap pointer
814 print r'void'
815 print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
816 print r' if (!ppObj || !*ppObj) {'
817 print r' return;'
818 print r' }'
819 print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
820 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
821 print r' *ppObj = pWrapper->m_pInstance;'
822 print r' } else {'
Jose Fonseca897d0092015-06-19 22:28:42 +0100823 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
Jose Fonseca07b5f132015-07-30 15:12:40 +0100824 print r' trace::localWriter.flush();'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100825 print r' }'
826 print r'}'
827 print
828
José Fonseca4220b1b2012-02-03 19:05:29 +0000829 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100830 wrapperInterfaceName = getWrapperInterfaceName(interface)
831
832 print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000833
834 if False:
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100835 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000836
José Fonseca0423d2c2012-01-20 19:16:17 +0000837 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100838 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000839
José Fonseca9362a9f2014-10-07 21:34:49 +0100840 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
841 for arg in method.args:
842 if not arg.output:
843 self.unwrapArg(method, arg)
844
José Fonseca4220b1b2012-02-03 19:05:29 +0000845 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100846
847 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
848
José Fonseca0423d2c2012-01-20 19:16:17 +0000849 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100850 print ' return _result;'
José Fonseca9362a9f2014-10-07 21:34:49 +0100851
José Fonseca0423d2c2012-01-20 19:16:17 +0000852 print '}'
853 print
854
José Fonseca4220b1b2012-02-03 19:05:29 +0000855 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100856 assert not method.internal
857
José Fonseca632a78d2012-04-19 07:18:59 +0100858 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 +0100859 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 +0100860
José Fonseca632a78d2012-04-19 07:18:59 +0100861 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100862 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100863 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100864 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000865 for arg in method.args:
866 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000867 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100868 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000869
José Fonseca4220b1b2012-02-03 19:05:29 +0000870 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000871
José Fonseca632a78d2012-04-19 07:18:59 +0100872 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000873
874 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000875 for arg in method.args:
876 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000877 self.serializeArg(method, arg)
878 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000879 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000880
José Fonseca87d1cc62010-11-29 15:57:25 +0000881 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100882 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100883 if method.type is not stdapi.Void:
884 self.wrapRet(method, '_result')
885
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000886 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000887 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000888 print r' if (!_result) {'
889 print r' delete this;'
890 print r' }'
891
892 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000893
José Fonseca143e9252012-04-15 09:31:18 +0100894 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100895 ifaces = api.getAllInterfaces()
896
José Fonseca143e9252012-04-15 09:31:18 +0100897 print r'static void'
José Fonseca92624532015-02-07 23:20:37 +0000898 print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100899 print r' os::log("apitrace: warning: %s: %s IID %s\n",'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100900 print r' entryName, reason,'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100901 print r' getGuidName(riid));'
José Fonseca92624532015-02-07 23:20:37 +0000902 print r' void * pVtbl = *(void **)pvObj;'
903 print r' HMODULE hModule = 0;'
Jose Fonsecaa316c6e2015-07-10 11:07:10 +0100904 print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
905 print r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
José Fonseca92624532015-02-07 23:20:37 +0000906 print r' (LPCTSTR)pVtbl,'
907 print r' &hModule);'
908 print r' assert(bRet);'
909 print r' if (bRet) {'
910 print r' char szModule[MAX_PATH];'
911 print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
912 print r' assert(dwRet);'
913 print r' if (dwRet) {'
914 print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
915 print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
916 print r' }'
917 print r' }'
José Fonseca143e9252012-04-15 09:31:18 +0100918 print r'}'
919 print
920 print r'static void'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100921 print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
José Fonseca143e9252012-04-15 09:31:18 +0100922 print r' if (!ppvObj || !*ppvObj) {'
923 print r' return;'
924 print r' }'
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100925 for iface in ifaces:
Jose Fonseca971c9512015-08-12 11:07:34 +0100926 print r' if (riid == IID_%s) {' % (iface.name,)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100927 print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
Jose Fonseca971c9512015-08-12 11:07:34 +0100928 print r' return;'
José Fonseca143e9252012-04-15 09:31:18 +0100929 print r' }'
Jose Fonseca82dbc602015-08-13 12:22:07 +0100930 print r' warnIID(entryName, riid, *ppvObj, "unsupported");'
José Fonseca143e9252012-04-15 09:31:18 +0100931 print r'}'
932 print
933
José Fonsecabcb26b22012-04-15 08:42:25 +0100934 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100935 # Cast output arg to `void **` if necessary
936 out_name = out.name
937 obj_type = out.type.type.type
938 if not obj_type is stdapi.Void:
939 assert isinstance(obj_type, stdapi.Interface)
940 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
941
José Fonsecabcb26b22012-04-15 08:42:25 +0100942 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100943 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100944 else_ = ''
945 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100946 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100947 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100948 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100949 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100950 print r' }'
951 else_ = 'else '
952 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100953 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100954 print r' }'
955 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000956
José Fonseca4220b1b2012-02-03 19:05:29 +0000957 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000958 if method.type is stdapi.Void:
959 result = ''
960 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100961 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100962 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000963
José Fonseca6f0e3032014-06-25 01:00:35 +0100964 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100965 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100966
967 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100968 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100969 for arg, instance in zip(function.args, args):
970 assert not arg.output
971 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
972 self.serializeValue(arg.type, instance)
973 print ' trace::localWriter.endArg();'
974 print ' trace::localWriter.endEnter();'
975 print ' trace::localWriter.beginLeave(_fake_call);'
976 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000977