blob: 97e545a1778becb12bbb1f406406b72e6d4d32a1 [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 Fonseca83e6ddf2016-02-01 13:29:50 +000070 # Write array with structure's member names
71 numMembers = len(struct.members)
72 if numMembers:
73 # Ensure member array has nonzero length to avoid MSVC error C2466
74 memberNames = '_struct%s_members' % (struct.tag,)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010075 print('static const char * %s[%u] = {' % (memberNames, numMembers))
Jose Fonseca83e6ddf2016-02-01 13:29:50 +000076 for type, name, in struct.members:
77 if name is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010078 print(' "",')
Jose Fonseca83e6ddf2016-02-01 13:29:50 +000079 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010080 print(' "%s",' % (name,))
81 print('};')
Jose Fonseca83e6ddf2016-02-01 13:29:50 +000082 else:
83 sys.stderr.write('warning: %s has no members\n' % struct.name)
84 memberNames = 'nullptr'
85
86 # Write structure's signature
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010087 print('static const trace::StructSig _struct%s_sig = {' % (struct.tag,))
José Fonsecaeb216e62012-11-20 11:08:08 +000088 if struct.name is None:
89 structName = '""'
90 else:
91 structName = '"%s"' % struct.name
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +010092 print(' %u, %s, %u, %s' % (struct.id, structName, numMembers, memberNames))
93 print('};')
94 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +000095
José Fonseca54f304a2012-01-14 19:33:08 +000096 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000097 self.visit(array.type)
98
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020099 def visitAttribArray(self, array):
100 pass
101
José Fonseca54f304a2012-01-14 19:33:08 +0000102 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000103 pass
104
José Fonseca54f304a2012-01-14 19:33:08 +0000105 def visitEnum(self, enum):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100106 print('static const trace::EnumValue _enum%s_values[] = {' % (enum.tag))
José Fonsecaeb644512011-12-11 10:33:55 +0000107 for value in enum.values:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100108 print(' {"%s", %s},' % (value, value))
109 print('};')
110 print()
111 print('static const trace::EnumSig _enum%s_sig = {' % (enum.tag))
112 print(' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag))
113 print('};')
114 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000115
José Fonseca54f304a2012-01-14 19:33:08 +0000116 def visitBitmask(self, bitmask):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100117 print('static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000118 for value in bitmask.values:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100119 print(' {"%s", %s},' % (value, value))
120 print('};')
121 print()
122 print('static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag))
123 print(' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag))
124 print('};')
125 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000126
José Fonseca54f304a2012-01-14 19:33:08 +0000127 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000128 self.visit(pointer.type)
129
José Fonseca59ee88e2012-01-15 14:24:10 +0000130 def visitIntPointer(self, pointer):
131 pass
132
José Fonsecafbcf6832012-04-05 07:10:30 +0100133 def visitObjPointer(self, pointer):
134 self.visit(pointer.type)
135
José Fonseca59ee88e2012-01-15 14:24:10 +0000136 def visitLinearPointer(self, pointer):
137 self.visit(pointer.type)
138
José Fonseca54f304a2012-01-14 19:33:08 +0000139 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000140 self.visit(handle.type)
141
José Fonsecab89c5932012-04-01 22:47:11 +0200142 def visitReference(self, reference):
143 self.visit(reference.type)
144
José Fonseca54f304a2012-01-14 19:33:08 +0000145 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000146 self.visit(alias.type)
147
José Fonseca54f304a2012-01-14 19:33:08 +0000148 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000149 pass
150
José Fonseca54f304a2012-01-14 19:33:08 +0000151 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000152 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000153
José Fonseca54f304a2012-01-14 19:33:08 +0000154 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100155 if not polymorphic.contextLess:
156 return
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100157 print('static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr))
158 print(' switch (selector) {')
José Fonseca54f304a2012-01-14 19:33:08 +0000159 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100160 for case in cases:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100161 print(' %s:' % case)
Jose Fonsecae28c4e92015-01-25 09:53:23 +0000162 self.serializer.visit(type, '(%s)(value)' % (type,))
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100163 print(' break;')
164 print(' }')
165 print('}')
166 print()
José Fonseca16d46dd2011-10-13 09:52:52 +0100167
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000168
José Fonsecadbf714b2012-11-20 17:03:43 +0000169class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000170 '''Visitor which generates code to serialize any type.
171
172 Simple types are serialized inline here, whereas the serialization of
173 complex types is dispatched to the serialization functions generated by
174 ComplexValueSerializer visitor above.
175 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000176
José Fonseca54f304a2012-01-14 19:33:08 +0000177 def visitLiteral(self, literal, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100178 print(' trace::localWriter.write%s(%s);' % (literal.kind, instance))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000179
José Fonseca54f304a2012-01-14 19:33:08 +0000180 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100181 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000182 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100183 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000184 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100185 cast = 'const wchar_t *'
186 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000187 if cast != string.expr:
188 # reinterpret_cast is necessary for GLubyte * <=> char *
189 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
190 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000191 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000192 else:
193 length = ''
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100194 print(' trace::localWriter.write%s(%s%s);' % (suffix, instance, length))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000195
José Fonseca54f304a2012-01-14 19:33:08 +0000196 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000197 self.visit(const.type, instance)
198
José Fonseca54f304a2012-01-14 19:33:08 +0000199 def visitStruct(self, struct, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100200 print(' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,))
José Fonsecadbf714b2012-11-20 17:03:43 +0000201 for member in struct.members:
202 self.visitMember(member, instance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100203 print(' trace::localWriter.endStruct();')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000204
José Fonseca54f304a2012-01-14 19:33:08 +0000205 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100206 length = '_c' + array.type.tag
207 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000208 array_length = self.expand(array.length)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100209 print(' if (%s) {' % instance)
210 print(' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length))
211 print(' trace::localWriter.beginArray(%s);' % length)
212 print(' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index))
213 print(' trace::localWriter.beginElement();')
José Fonsecaf6b05132012-11-06 00:16:28 +0000214 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100215 print(' trace::localWriter.endElement();')
216 print(' }')
217 print(' trace::localWriter.endArray();')
218 print(' } else {')
219 print(' trace::localWriter.writeNull();')
220 print(' }')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000221
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200222 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200223 # For each element, decide if it is a key or a value (which depends on the previous key).
224 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
225 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200226
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200227 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100228 count = '_c' + array.baseType.tag
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100229 print(' {')
230 print(' int %s;' % count)
231 print(' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
232 % {'c': count, 'array': instance, 'terminator': array.terminator})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200233 if array.hasKeysWithoutValues:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100234 print(' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200235 for key, valueType in array.valueTypes:
236 if valueType is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100237 print(' case %s:' % key)
238 print(' %s--;' % count) # the next value is a key again and checked if it's the terminator
239 print(' break;')
240 print(' }')
241 print(' }')
242 print(' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance})
243 print(' trace::localWriter.beginArray(%s);' % count)
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200244
245 # for each key / key-value pair write the key and the value, if the key requires one
246
José Fonseca77c10d82013-07-20 15:27:29 +0100247 index = '_i' + array.baseType.tag
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100248 print(' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count})
249 print(' trace::localWriter.beginElement();')
José Fonseca77c10d82013-07-20 15:27:29 +0100250 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100251 print(' trace::localWriter.endElement();')
252 print(' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count})
253 print(' break;')
254 print(' }')
255 print(' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index})
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200256 # write generic value the usual way
257 for key, valueType in array.valueTypes:
258 if valueType is not None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100259 print(' case %s:' % key)
260 print(' trace::localWriter.beginElement();')
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200261 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100262 print(' trace::localWriter.endElement();')
263 print(' break;')
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200264 # known key with no value, just decrease the index so we treat the next value as a key
265 if array.hasKeysWithoutValues:
266 for key, valueType in array.valueTypes:
267 if valueType is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100268 print(' case %s:' % key)
269 print(' %s--;' % index)
270 print(' break;')
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200271 # unknown key, write an int value
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100272 print(' default:')
273 print(' trace::localWriter.beginElement();')
274 print(' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
275 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index})
276 print(' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index})
277 print(' trace::localWriter.endElement();')
278 print(' break;')
279 print(' }')
280 print(' }')
281 print(' trace::localWriter.endArray();')
282 print(' }')
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200283
284
José Fonseca54f304a2012-01-14 19:33:08 +0000285 def visitBlob(self, blob, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100286 print(' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size)))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000287
José Fonseca54f304a2012-01-14 19:33:08 +0000288 def visitEnum(self, enum, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100289 print(' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000290
José Fonseca54f304a2012-01-14 19:33:08 +0000291 def visitBitmask(self, bitmask, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100292 print(' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000293
José Fonseca54f304a2012-01-14 19:33:08 +0000294 def visitPointer(self, pointer, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100295 print(' if (%s) {' % instance)
296 print(' trace::localWriter.beginArray(1);')
297 print(' trace::localWriter.beginElement();')
José Fonseca54f304a2012-01-14 19:33:08 +0000298 self.visit(pointer.type, "*" + instance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100299 print(' trace::localWriter.endElement();')
300 print(' trace::localWriter.endArray();')
301 print(' } else {')
302 print(' trace::localWriter.writeNull();')
303 print(' }')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000304
José Fonseca59ee88e2012-01-15 14:24:10 +0000305 def visitIntPointer(self, pointer, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100306 print(' trace::localWriter.writePointer((uintptr_t)%s);' % instance)
José Fonseca59ee88e2012-01-15 14:24:10 +0000307
José Fonsecafbcf6832012-04-05 07:10:30 +0100308 def visitObjPointer(self, pointer, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100309 print(' trace::localWriter.writePointer((uintptr_t)%s);' % instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100310
José Fonseca59ee88e2012-01-15 14:24:10 +0000311 def visitLinearPointer(self, pointer, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100312 print(' trace::localWriter.writePointer((uintptr_t)%s);' % instance)
José Fonseca59ee88e2012-01-15 14:24:10 +0000313
José Fonsecab89c5932012-04-01 22:47:11 +0200314 def visitReference(self, reference, instance):
315 self.visit(reference.type, instance)
316
José Fonseca54f304a2012-01-14 19:33:08 +0000317 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000318 self.visit(handle.type, instance)
319
José Fonseca54f304a2012-01-14 19:33:08 +0000320 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000321 self.visit(alias.type, instance)
322
José Fonseca54f304a2012-01-14 19:33:08 +0000323 def visitOpaque(self, opaque, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100324 print(' trace::localWriter.writePointer((uintptr_t)%s);' % instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000325
José Fonseca54f304a2012-01-14 19:33:08 +0000326 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100327 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000328
José Fonseca54f304a2012-01-14 19:33:08 +0000329 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100330 if polymorphic.contextLess:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100331 print(' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance))
José Fonsecab95e3722012-04-16 14:01:15 +0100332 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000333 switchExpr = self.expand(polymorphic.switchExpr)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100334 print(' switch (%s) {' % switchExpr)
José Fonsecab95e3722012-04-16 14:01:15 +0100335 for cases, type in polymorphic.iterSwitch():
336 for case in cases:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100337 print(' %s:' % case)
José Fonsecaeb216e62012-11-20 11:08:08 +0000338 caseInstance = instance
339 if type.expr is not None:
340 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
341 self.visit(type, caseInstance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100342 print(' break;')
José Fonsecadbf714b2012-11-20 17:03:43 +0000343 if polymorphic.defaultType is None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100344 print(r' default:')
345 print(r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,))
346 print(r' trace::localWriter.writeNull();')
347 print(r' break;')
348 print(' }')
José Fonseca16d46dd2011-10-13 09:52:52 +0100349
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000350
José Fonseca0075f152012-04-14 20:25:52 +0100351class WrapDecider(stdapi.Traverser):
352 '''Type visitor which will decide wheter this type will need wrapping or not.
353
354 For complex types (arrays, structures), we need to know this before hand.
355 '''
356
357 def __init__(self):
358 self.needsWrapping = False
359
José Fonseca0075f152012-04-14 20:25:52 +0100360 def visitLinearPointer(self, void):
361 pass
362
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100363 def visitObjPointer(self, interface):
José Fonseca0075f152012-04-14 20:25:52 +0100364 self.needsWrapping = True
365
366
José Fonsecadbf714b2012-11-20 17:03:43 +0000367class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000368 '''Type visitor which will generate the code to wrap an instance.
369
370 Wrapping is necessary mostly for interfaces, however interface pointers can
371 appear anywhere inside complex types.
372 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000373
José Fonseca54f304a2012-01-14 19:33:08 +0000374 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000375 for member in struct.members:
376 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000377
José Fonseca54f304a2012-01-14 19:33:08 +0000378 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000379 array_length = self.expand(array.length)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100380 print(" if (%s) {" % instance)
381 print(" for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length)
José Fonsecaf6b05132012-11-06 00:16:28 +0000382 self.visitElement('_i', array.type, instance + "[_i]")
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100383 print(" }")
384 print(" }")
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000385
José Fonseca54f304a2012-01-14 19:33:08 +0000386 def visitPointer(self, pointer, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100387 print(" if (%s) {" % instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000388 self.visit(pointer.type, "*" + instance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100389 print(" }")
José Fonseca59ee88e2012-01-15 14:24:10 +0000390
José Fonsecafbcf6832012-04-05 07:10:30 +0100391 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100392 elem_type = pointer.type.mutable()
393 if isinstance(elem_type, stdapi.Interface):
394 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100395 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
396 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100397 else:
Jose Fonsecaf753c3f2015-07-30 15:12:14 +0100398 # All interfaces should at least implement IUnknown
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100399 print(" WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,))
José Fonsecafbcf6832012-04-05 07:10:30 +0100400
José Fonseca54f304a2012-01-14 19:33:08 +0000401 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100402 raise NotImplementedError
403
404 def visitInterfacePointer(self, interface, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100405 print(" Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance))
José Fonseca16d46dd2011-10-13 09:52:52 +0100406
José Fonseca54f304a2012-01-14 19:33:08 +0000407 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100408 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100409 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000410
411
José Fonseca54f304a2012-01-14 19:33:08 +0000412class ValueUnwrapper(ValueWrapper):
413 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000414
José Fonseca0075f152012-04-14 20:25:52 +0100415 allocated = False
416
José Fonsecae7cb2b92012-09-28 08:40:24 +0100417 def visitStruct(self, struct, instance):
418 if not self.allocated:
419 # Argument is constant. We need to create a non const
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100420 print(' {')
421 print(" %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct))
422 print(' *_t = %s;' % (instance,))
José Fonsecae7cb2b92012-09-28 08:40:24 +0100423 assert instance.startswith('*')
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100424 print(' %s = _t;' % (instance[1:],))
José Fonsecae7cb2b92012-09-28 08:40:24 +0100425 instance = '*_t'
426 self.allocated = True
427 try:
428 return ValueWrapper.visitStruct(self, struct, instance)
429 finally:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100430 print(' }')
José Fonsecae7cb2b92012-09-28 08:40:24 +0100431 else:
432 return ValueWrapper.visitStruct(self, struct, instance)
433
José Fonseca0075f152012-04-14 20:25:52 +0100434 def visitArray(self, array, instance):
435 if self.allocated or isinstance(instance, stdapi.Interface):
436 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000437 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100438 elem_type = array.type.mutable()
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100439 print(" if (%s && %s) {" % (instance, array_length))
440 print(" %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length))
441 print(" for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length)
442 print(" _t[_i] = %s[_i];" % instance)
José Fonseca0075f152012-04-14 20:25:52 +0100443 self.allocated = True
444 self.visit(array.type, "_t[_i]")
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100445 print(" }")
446 print(" %s = _t;" % instance)
447 print(" }")
José Fonseca0075f152012-04-14 20:25:52 +0100448
José Fonseca9782b292012-04-14 22:02:42 +0100449 def visitInterfacePointer(self, interface, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100450 print(r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance))
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100451
452
453def _getInterfaceHierarchy(allIfaces, baseIface, result):
454 for iface in allIfaces:
455 if iface.base is baseIface:
456 _getInterfaceHierarchy(allIfaces, iface, result)
457 result.append(iface)
458
459def getInterfaceHierarchy(allIfaces, baseIface):
460 result = []
461 _getInterfaceHierarchy(allIfaces, baseIface, result)
462 return result
José Fonseca87d1cc62010-11-29 15:57:25 +0000463
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000464
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000465class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000466 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000467
José Fonseca4b466a92012-11-26 19:47:26 +0000468 # 0-3 are reserved to memcpy, malloc, free, and realloc
469 __id = 4
470
José Fonsecabb8760b2011-05-25 23:21:18 +0100471 def __init__(self):
472 self.api = None
473
José Fonseca54f304a2012-01-14 19:33:08 +0000474 def serializerFactory(self):
475 '''Create a serializer.
476
477 Can be overriden by derived classes to inject their own serialzer.
478 '''
479
480 return ValueSerializer()
481
José Fonseca1b6c8752012-04-15 14:33:00 +0100482 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100483 self.api = api
484
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000485 self.header(api)
486
487 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000488 for module in api.modules:
489 for header in module.headers:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100490 print(header)
491 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000492
José Fonseca54f304a2012-01-14 19:33:08 +0000493 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000494 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000495 visitor = ComplexValueSerializer(self.serializerFactory())
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100496
497 for tp in types:
498 visitor.visit(tp)
499
500 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000501
502 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100503 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000504
505 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100506 self.interface = None
507 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000508 for function in api.getAllFunctions():
509 self.traceFunctionDecl(function)
510 for function in api.getAllFunctions():
Jose Fonseca00eba862016-01-26 12:30:54 +0000511 try:
512 self.traceFunctionImpl(function)
513 except:
514 sys.stderr.write("error: %s: exception\n" % function.name)
515 raise
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100516 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000517
518 self.footer(api)
519
520 def header(self, api):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100521 print('#ifdef _WIN32')
522 print('# include <malloc.h> // alloca')
523 print('# ifndef alloca')
524 print('# define alloca _alloca')
525 print('# endif')
526 print('#else')
527 print('# include <alloca.h> // alloca')
528 print('#endif')
529 print()
530 print()
Andrii Simiklit04be2762019-05-24 17:58:31 +0300531 print(r'/*')
532 print(r' * g_WrappedObjects is already protected by trace::LocalWriter::mutex')
533 print(r' * This lock is hold during the beginEnter/endEnter and beginLeave/endLeave sections')
534 print(r' */')
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100535 print('static std::map<void *, void *> g_WrappedObjects;')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000536
537 def footer(self, api):
538 pass
539
José Fonseca54f304a2012-01-14 19:33:08 +0000540 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000541 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000542
José Fonseca84cea3b2012-05-09 21:12:30 +0100543 if not function.internal:
544 if function.args:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100545 print('static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])))
José Fonseca84cea3b2012-05-09 21:12:30 +0100546 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100547 print('static const char ** _%s_args = NULL;' % (function.name,))
548 print('static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.sigName(), len(function.args), function.name))
549 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000550
José Fonseca4b466a92012-11-26 19:47:26 +0000551 def getFunctionSigId(self):
552 id = Tracer.__id
553 Tracer.__id += 1
554 return id
555
José Fonseca54f304a2012-01-14 19:33:08 +0000556 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100557 return True
558
José Fonseca54f304a2012-01-14 19:33:08 +0000559 def traceFunctionImpl(self, function):
560 if self.isFunctionPublic(function):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100561 print('extern "C" PUBLIC')
José Fonseca23691292011-04-22 10:40:25 +0100562 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100563 print('extern "C" PRIVATE')
564 print(function.prototype() + ' {')
José Fonseca14c21bc2011-02-20 23:32:22 +0000565 if function.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100566 print(' %s _result;' % function.type)
José Fonseca537c5072012-07-07 12:54:09 +0100567
José Fonseca9362a9f2014-10-07 21:34:49 +0100568 for arg in function.args:
569 if not arg.output:
570 self.unwrapArg(function, arg)
571
José Fonseca54f304a2012-01-14 19:33:08 +0000572 self.traceFunctionImplBody(function)
José Fonseca9362a9f2014-10-07 21:34:49 +0100573
574 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
575
José Fonseca14c21bc2011-02-20 23:32:22 +0000576 if function.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100577 print(' return _result;')
José Fonseca9362a9f2014-10-07 21:34:49 +0100578
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100579 print('}')
580 print()
José Fonseca14c21bc2011-02-20 23:32:22 +0000581
José Fonseca54f304a2012-01-14 19:33:08 +0000582 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100583 if not function.internal:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100584 print(' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,))
José Fonseca84cea3b2012-05-09 21:12:30 +0100585 for arg in function.args:
586 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100587 self.serializeArg(function, arg)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100588 print(' trace::localWriter.endEnter();')
José Fonseca54f304a2012-01-14 19:33:08 +0000589 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100590 if not function.internal:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100591 print(' trace::localWriter.beginLeave(_call);')
592 print(' if (%s) {' % self.wasFunctionSuccessful(function))
José Fonseca84cea3b2012-05-09 21:12:30 +0100593 for arg in function.args:
594 if arg.output:
595 self.serializeArg(function, arg)
596 self.wrapArg(function, arg)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100597 print(' }')
José Fonseca84cea3b2012-05-09 21:12:30 +0100598 if function.type is not stdapi.Void:
599 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100600 if function.type is not stdapi.Void:
601 self.wrapRet(function, "_result")
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100602 print(' trace::localWriter.endLeave();')
José Fonseca14c21bc2011-02-20 23:32:22 +0000603
José Fonseca2cfa02c2013-06-10 08:05:29 +0100604 def invokeFunction(self, function):
605 self.doInvokeFunction(function)
606
607 def doInvokeFunction(self, function, prefix='_', suffix=''):
608 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000609 if function.type is stdapi.Void:
610 result = ''
611 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100612 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100613 dispatch = prefix + function.name + suffix
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100614 print(' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args])))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000615
José Fonseca4fb1ab02012-11-08 10:23:40 +0000616 def wasFunctionSuccessful(self, function):
617 if function.type is stdapi.Void:
618 return 'true'
619 if str(function.type) == 'HRESULT':
620 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000621 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000622
José Fonseca54f304a2012-01-14 19:33:08 +0000623 def serializeArg(self, function, arg):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100624 print(' trace::localWriter.beginArg(%u);' % (arg.index,))
José Fonseca54f304a2012-01-14 19:33:08 +0000625 self.serializeArgValue(function, arg)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100626 print(' trace::localWriter.endArg();')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca54f304a2012-01-14 19:33:08 +0000628 def serializeArgValue(self, function, arg):
629 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000630
José Fonseca54f304a2012-01-14 19:33:08 +0000631 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100632 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100633
634 from specs.winapi import REFIID
635 riid = None
636 for other_arg in function.args:
637 if not other_arg.output and other_arg.type is REFIID:
638 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100639 if riid is not None \
José Fonsecad2bff852014-09-14 21:23:15 +0100640 and riid.name != 'EmulatedInterface' \
José Fonsecac328b8c2012-04-28 21:45:38 +0100641 and isinstance(arg.type, stdapi.Pointer) \
642 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100643 self.wrapIid(function, riid, arg)
644 return
645
José Fonseca54f304a2012-01-14 19:33:08 +0000646 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000647
José Fonseca54f304a2012-01-14 19:33:08 +0000648 def unwrapArg(self, function, arg):
649 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000650
José Fonseca54f304a2012-01-14 19:33:08 +0000651 def serializeRet(self, function, instance):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100652 print(' trace::localWriter.beginReturn();')
José Fonseca54f304a2012-01-14 19:33:08 +0000653 self.serializeValue(function.type, instance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100654 print(' trace::localWriter.endReturn();')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000655
José Fonseca54f304a2012-01-14 19:33:08 +0000656 def serializeValue(self, type, instance):
657 serializer = self.serializerFactory()
658 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000659
José Fonseca54f304a2012-01-14 19:33:08 +0000660 def wrapRet(self, function, instance):
661 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000662
José Fonseca0075f152012-04-14 20:25:52 +0100663 def needsWrapping(self, type):
664 visitor = WrapDecider()
665 visitor.visit(type)
666 return visitor.needsWrapping
667
José Fonseca54f304a2012-01-14 19:33:08 +0000668 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100669 if self.needsWrapping(type):
670 visitor = ValueWrapper()
671 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000672
673 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100674 if self.needsWrapping(type):
675 visitor = ValueUnwrapper()
676 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000677
José Fonseca143e9252012-04-15 09:31:18 +0100678 def traceInterfaces(self, api):
679 interfaces = api.getAllInterfaces()
680 if not interfaces:
681 return
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100682
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100683 print(r'#include "guids.hpp"')
684 print()
Jose Fonseca82dbc602015-08-13 12:22:07 +0100685
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100686 # Helper functions to wrap/unwrap interface pointers
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100687 print(r'static inline bool')
688 print(r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {')
689 print(r' IUnknown *pObj = NULL;')
690 print(r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);')
691 print(r' if (FAILED(hr)) {')
692 print(r' return false;')
693 print(r' }')
694 print(r' assert(pObj);')
695 print(r' pObj->Release();')
696 print(r' return pUnknown == pObj;')
697 print(r'}')
698 print()
699 print(r'static inline const void *')
700 print(r'getVtbl(const void *pvObj) {')
701 print(r' return pvObj ? *(const void **)pvObj : NULL;')
702 print(r'}')
703 print()
704 print(r'static void')
705 print(r'warnVtbl(const void *pVtbl) {')
706 print(r' HMODULE hModule = 0;')
707 print(r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |')
708 print(r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,')
709 print(r' (LPCTSTR)pVtbl,')
710 print(r' &hModule);')
711 print(r' if (bRet) {')
712 print(r' char szModule[MAX_PATH];')
713 print(r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);')
714 print(r' assert(dwRet);')
715 print(r' if (dwRet) {')
716 print(r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;')
717 print(r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);')
718 print(r' } else {')
719 print(r' os::log("apitrace: warning: pVtbl = %p\n", pVtbl);')
720 print(r' }')
721 print(r' }')
722 print(r'}')
723 print()
Jose Fonseca3615c342016-06-30 10:37:19 +0100724
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100725 for iface in interfaces:
726 self.declareWrapperInterface(iface)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100727
José Fonseca143e9252012-04-15 09:31:18 +0100728 self.implementIidWrapper(api)
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100729
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100730 for iface in interfaces:
731 self.implementWrapperInterface(iface)
732
733 print()
José Fonseca143e9252012-04-15 09:31:18 +0100734
José Fonseca0423d2c2012-01-20 19:16:17 +0000735 def declareWrapperInterface(self, interface):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100736 wrapperInterfaceName = getWrapperInterfaceName(interface)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100737 print("class %s : public %s " % (wrapperInterfaceName, interface.name))
738 print("{")
739 print("private:")
740 print(" %s(%s * pInstance);" % (wrapperInterfaceName, interface.name))
741 print(" ~%s(); // Not implemented" % wrapperInterfaceName)
742 print("public:")
743 print(" static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name))
744 print(" static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,))
745 print(" static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,))
746 print()
José Fonseca01e50592014-08-22 15:35:27 +0100747
748 methods = list(interface.iterMethods())
749 for method in methods:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100750 print(" " + method.prototype() + " override;")
751 print()
José Fonseca01e50592014-08-22 15:35:27 +0100752
José Fonsecaacc90622012-05-02 13:10:07 +0100753 for type, name, value in self.enumWrapperInterfaceVariables(interface):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100754 print(' %s %s;' % (type, name))
755 print()
José Fonseca01e50592014-08-22 15:35:27 +0100756
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100757 print(r'private:')
758 print(r' void _dummy(unsigned i) const {')
759 print(r' os::log("error: %%s: unexpected virtual method %%i of instance pvObj=%%p pWrapper=%%p pVtbl=%%p\n", "%s", i, m_pInstance, this, m_pVtbl);' % interface.name)
760 print(r' warnVtbl(m_pVtbl);')
761 print(r' warnVtbl(getVtbl(m_pInstance));')
762 print(r' trace::localWriter.flush();')
763 print(r' os::abort();')
764 print(r' }')
765 print()
José Fonseca01e50592014-08-22 15:35:27 +0100766 for i in range(len(methods), 64):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100767 print(r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i))
768 print()
José Fonseca01e50592014-08-22 15:35:27 +0100769
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100770 print("};")
771 print()
José Fonseca0423d2c2012-01-20 19:16:17 +0000772
José Fonsecaacc90622012-05-02 13:10:07 +0100773 def enumWrapperInterfaceVariables(self, interface):
774 return [
775 ("DWORD", "m_dwMagic", "0xd8365d6c"),
776 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100777 ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000778 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100779 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000780
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100781 def implementWrapperInterface(self, iface):
782 self.interface = iface
783
784 wrapperInterfaceName = getWrapperInterfaceName(iface)
José Fonsecabcb26b22012-04-15 08:42:25 +0100785
José Fonsecab7a9b182012-11-23 17:02:48 +0000786 # Private constructor
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100787 print('%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name))
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100788 for type, name, value in self.enumWrapperInterfaceVariables(iface):
José Fonseca003b8be2013-05-29 19:59:40 +0100789 if value is not None:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100790 print(' %s = %s;' % (name, value))
791 print('}')
792 print()
José Fonsecab7a9b182012-11-23 17:02:48 +0000793
794 # Public constructor
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100795 print('%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name))
796 print(r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name))
José Fonsecaab623c52014-07-22 17:05:00 +0100797 if debug:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100798 print(r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", entryName, pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name)
799 print(r' g_WrappedObjects[pInstance] = pWrapper;')
800 print(r' return pWrapper;')
801 print('}')
802 print()
José Fonsecab7a9b182012-11-23 17:02:48 +0000803
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100804 baseMethods = list(iface.iterBaseMethods())
805 for base, method in baseMethods:
José Fonsecabcb26b22012-04-15 08:42:25 +0100806 self.base = base
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100807 self.implementWrapperInterfaceMethod(iface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100808
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100809 print()
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000810
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100811 # Wrap pointer
812 ifaces = self.api.getAllInterfaces()
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100813 print(r'void')
814 print(r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name))
815 print(r' if (!ppObj) {')
816 print(r' return;')
817 print(r' }')
818 print(r' %s *pObj = *ppObj;' % (iface.name,))
819 print(r' if (!pObj) {')
820 print(r' return;')
821 print(r' }')
822 print(r' assert(hasChildInterface(IID_%s, pObj));' % iface.name)
823 print(r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);')
824 print(r' if (it != g_WrappedObjects.end()) {')
825 print(r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name))
826 print(r' assert(pWrapper);')
827 print(r' assert(pWrapper->m_dwMagic == 0xd8365d6c);')
828 print(r' assert(pWrapper->m_pInstance == pObj);')
829 print(r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&')
830 print(r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods))
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100831 if debug:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100832 print(r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);')
833 print(r' assert(hasChildInterface(IID_%s, pWrapper->m_pInstance));' % iface.name)
834 print(r' *ppObj = pWrapper;')
835 print(r' return;')
836 print(r' } else {')
Jose Fonsecacc0e7c72016-06-30 16:15:24 +0100837 if debug:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100838 print(r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", pWrapper->m_pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name)
839 print(r' g_WrappedObjects.erase(pObj);')
840 print(r' }')
841 print(r' }')
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100842 for childIface in getInterfaceHierarchy(ifaces, iface):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100843 print(r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,))
844 print(r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name))
845 print(r' return;')
846 print(r' }')
847 print(r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name)
848 print(r'}')
849 print()
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100850
851 # Unwrap pointer
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100852 print(r'void')
853 print(r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name))
854 print(r' if (!ppObj || !*ppObj) {')
855 print(r' return;')
856 print(r' }')
857 print(r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface)))
858 print(r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {')
859 print(r' *ppObj = pWrapper->m_pInstance;')
860 print(r' } else {')
861 print(r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name)
862 print(r' trace::localWriter.flush();')
863 print(r' }')
864 print(r'}')
865 print()
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100866
José Fonseca4220b1b2012-02-03 19:05:29 +0000867 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100868 wrapperInterfaceName = getWrapperInterfaceName(interface)
869
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100870 print(method.prototype(wrapperInterfaceName + '::' + method.name) + ' {')
José Fonsecab7a9b182012-11-23 17:02:48 +0000871
872 if False:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100873 print(r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name))
José Fonsecab7a9b182012-11-23 17:02:48 +0000874
José Fonseca0423d2c2012-01-20 19:16:17 +0000875 if method.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100876 print(' %s _result;' % method.type)
José Fonseca0423d2c2012-01-20 19:16:17 +0000877
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100878 print(' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base))
José Fonseca9362a9f2014-10-07 21:34:49 +0100879 for arg in method.args:
880 if not arg.output:
881 self.unwrapArg(method, arg)
882
José Fonseca4220b1b2012-02-03 19:05:29 +0000883 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca9362a9f2014-10-07 21:34:49 +0100884
885 # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
886
José Fonseca0423d2c2012-01-20 19:16:17 +0000887 if method.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100888 print(' return _result;')
José Fonseca9362a9f2014-10-07 21:34:49 +0100889
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100890 print('}')
891 print()
José Fonseca0423d2c2012-01-20 19:16:17 +0000892
José Fonseca4220b1b2012-02-03 19:05:29 +0000893 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100894 assert not method.internal
895
Jose Fonsecafdcd30b2016-02-01 14:13:40 +0000896 sigName = interface.name + '::' + method.sigName()
897 if method.overloaded:
898 # Once the method signature name goes into a trace, we'll need to
899 # support it indefinetely, so log them so one can make sure nothing
900 # weird gets baked in
901 sys.stderr.write('note: overloaded method %s\n' % (sigName,))
902
903 numArgs = len(method.args) + 1
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100904 print(' static const char * _args[%u] = {%s};' % (numArgs, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args])))
905 print(' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), sigName, numArgs))
José Fonsecaa0e97862012-04-29 23:22:52 +0100906
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100907 print(' unsigned _call = trace::localWriter.beginEnter(&_sig);')
908 print(' trace::localWriter.beginArg(0);')
909 print(' trace::localWriter.writePointer((uintptr_t)m_pInstance);')
910 print(' trace::localWriter.endArg();')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000911 for arg in method.args:
912 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000913 self.serializeArg(method, arg)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100914 print(' trace::localWriter.endEnter();')
José Fonseca0423d2c2012-01-20 19:16:17 +0000915
José Fonseca4220b1b2012-02-03 19:05:29 +0000916 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000917
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100918 print(' trace::localWriter.beginLeave(_call);')
José Fonseca4fb1ab02012-11-08 10:23:40 +0000919
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100920 print(' if (%s) {' % self.wasFunctionSuccessful(method))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000921 for arg in method.args:
922 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000923 self.serializeArg(method, arg)
924 self.wrapArg(method, arg)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100925 print(' }')
José Fonseca1ce52f02012-01-31 12:19:57 +0000926
José Fonseca87d1cc62010-11-29 15:57:25 +0000927 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100928 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100929 if method.type is not stdapi.Void:
930 self.wrapRet(method, '_result')
931
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000932 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000933 assert method.type is not stdapi.Void
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100934 print(r' if (!_result) {')
935 print(r' // NOTE: Must not delete the wrapper here. See')
936 print(r' // https://github.com/apitrace/apitrace/issues/462')
937 print(r' }')
José Fonsecab7a9b182012-11-23 17:02:48 +0000938
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100939 print(' trace::localWriter.endLeave();')
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000940
José Fonseca143e9252012-04-15 09:31:18 +0100941 def implementIidWrapper(self, api):
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100942 ifaces = api.getAllInterfaces()
943
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100944 print(r'static void')
945 print(r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {')
946 print(r' os::log("apitrace: warning: %s: %s IID %s\n",')
947 print(r' entryName, reason,')
948 print(r' getGuidName(riid));')
949 print(r' const void * pVtbl = getVtbl(pvObj);')
950 print(r' warnVtbl(pVtbl);')
951 print(r'}')
952 print()
953 print(r'static void')
954 print(r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {')
955 print(r' if (!ppvObj || !*ppvObj) {')
956 print(r' return;')
957 print(r' }')
José Fonsecaf7e2fb32014-08-22 15:33:28 +0100958 for iface in ifaces:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100959 print(r' if (riid == IID_%s) {' % (iface.name,))
960 print(r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name))
961 print(r' return;')
962 print(r' }')
963 print(r' warnIID(entryName, riid, *ppvObj, "unsupported");')
964 print(r'}')
965 print()
José Fonseca143e9252012-04-15 09:31:18 +0100966
José Fonsecabcb26b22012-04-15 08:42:25 +0100967 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100968 # Cast output arg to `void **` if necessary
969 out_name = out.name
970 obj_type = out.type.type.type
971 if not obj_type is stdapi.Void:
972 assert isinstance(obj_type, stdapi.Interface)
973 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
974
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100975 print(r' if (%s && *%s) {' % (out.name, out.name))
José Fonseca143e9252012-04-15 09:31:18 +0100976 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100977 else_ = ''
978 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100979 functionName = self.interface.name + '::' + functionName
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100980 print(r' if (*%s == m_pInstance &&' % (out_name,))
981 print(r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases()))
982 print(r' *%s = this;' % (out_name,))
983 print(r' }')
José Fonsecabcb26b22012-04-15 08:42:25 +0100984 else_ = 'else '
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100985 print(r' %s{' % else_)
986 print(r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name))
987 print(r' }')
988 print(r' }')
José Fonseca1ce52f02012-01-31 12:19:57 +0000989
José Fonseca4220b1b2012-02-03 19:05:29 +0000990 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000991 if method.type is stdapi.Void:
992 result = ''
993 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100994 result = '_result = '
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100995 print(' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args])))
José Fonseca0423d2c2012-01-20 19:16:17 +0000996
José Fonseca6f0e3032014-06-25 01:00:35 +0100997 def emit_memcpy(self, ptr, size):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100998 print(' trace::fakeMemcpy(%s, %s);' % (ptr, size))
José Fonseca122c9872012-08-02 08:42:24 +0100999
1000 def fake_call(self, function, args):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +01001001 print(' {')
1002 print(' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,))
José Fonseca122c9872012-08-02 08:42:24 +01001003 for arg, instance in zip(function.args, args):
1004 assert not arg.output
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +01001005 print(' trace::localWriter.beginArg(%u);' % (arg.index,))
José Fonseca122c9872012-08-02 08:42:24 +01001006 self.serializeValue(arg.type, instance)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +01001007 print(' trace::localWriter.endArg();')
1008 print(' trace::localWriter.endEnter();')
1009 print(' trace::localWriter.beginLeave(_fake_call);')
1010 print(' trace::localWriter.endLeave();')
1011 print(' }')
José Fonseca0423d2c2012-01-20 19:16:17 +00001012