blob: d9b592fa1dc780a4c7e6ff644d7e988fe9e0fc20 [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
34
José Fonsecabd86a222011-09-27 09:21:38 +010035import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000036
37
José Fonseca0423d2c2012-01-20 19:16:17 +000038def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000039 return "Wrap" + interface.expr
40
José Fonseca6fac5ae2010-11-29 16:09:13 +000041
José Fonsecaab623c52014-07-22 17:05:00 +010042debug = False
43
José Fonsecaf6b05132012-11-06 00:16:28 +000044
José Fonseca54f304a2012-01-14 19:33:08 +000045class ComplexValueSerializer(stdapi.OnceVisitor):
46 '''Type visitors which generates serialization functions for
47 complex types.
48
49 Simple types are serialized inline.
50 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000051
José Fonseca54f304a2012-01-14 19:33:08 +000052 def __init__(self, serializer):
53 stdapi.OnceVisitor.__init__(self)
54 self.serializer = serializer
55
56 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000057 pass
58
José Fonseca54f304a2012-01-14 19:33:08 +000059 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000060 pass
61
José Fonseca54f304a2012-01-14 19:33:08 +000062 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000063 pass
64
José Fonseca54f304a2012-01-14 19:33:08 +000065 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000066 self.visit(const.type)
67
José Fonseca54f304a2012-01-14 19:33:08 +000068 def visitStruct(self, struct):
José Fonseca30fb4c32012-11-04 11:07:45 +000069 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000070 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000071 if name is None:
72 print ' "",'
73 else:
74 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000075 print '};'
76 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000077 if struct.name is None:
78 structName = '""'
79 else:
80 structName = '"%s"' % struct.name
81 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000082 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000083 print
84
José Fonseca54f304a2012-01-14 19:33:08 +000085 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000086 self.visit(array.type)
87
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +020088 def visitAttribArray(self, array):
89 pass
90
José Fonseca54f304a2012-01-14 19:33:08 +000091 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000092 pass
93
José Fonseca54f304a2012-01-14 19:33:08 +000094 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010095 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000096 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000097 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +000098 print '};'
99 print
José Fonseca632a78d2012-04-19 07:18:59 +0100100 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000101 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000102 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000103 print
104
José Fonseca54f304a2012-01-14 19:33:08 +0000105 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100106 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000107 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000108 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000109 print '};'
110 print
José Fonseca632a78d2012-04-19 07:18:59 +0100111 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000112 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000113 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000114 print
115
José Fonseca54f304a2012-01-14 19:33:08 +0000116 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000117 self.visit(pointer.type)
118
José Fonseca59ee88e2012-01-15 14:24:10 +0000119 def visitIntPointer(self, pointer):
120 pass
121
José Fonsecafbcf6832012-04-05 07:10:30 +0100122 def visitObjPointer(self, pointer):
123 self.visit(pointer.type)
124
José Fonseca59ee88e2012-01-15 14:24:10 +0000125 def visitLinearPointer(self, pointer):
126 self.visit(pointer.type)
127
José Fonseca54f304a2012-01-14 19:33:08 +0000128 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000129 self.visit(handle.type)
130
José Fonsecab89c5932012-04-01 22:47:11 +0200131 def visitReference(self, reference):
132 self.visit(reference.type)
133
José Fonseca54f304a2012-01-14 19:33:08 +0000134 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000135 self.visit(alias.type)
136
José Fonseca54f304a2012-01-14 19:33:08 +0000137 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000138 pass
139
José Fonseca54f304a2012-01-14 19:33:08 +0000140 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000141 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000142
José Fonseca54f304a2012-01-14 19:33:08 +0000143 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100144 if not polymorphic.contextLess:
145 return
José Fonsecafbc51922013-04-14 14:45:04 +0100146 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100147 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000148 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100149 for case in cases:
150 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000151 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100152 print ' break;'
153 print ' }'
154 print '}'
155 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100156
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000157
José Fonsecadbf714b2012-11-20 17:03:43 +0000158class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000159 '''Visitor which generates code to serialize any type.
160
161 Simple types are serialized inline here, whereas the serialization of
162 complex types is dispatched to the serialization functions generated by
163 ComplexValueSerializer visitor above.
164 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000165
José Fonseca54f304a2012-01-14 19:33:08 +0000166 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100167 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000168
José Fonseca54f304a2012-01-14 19:33:08 +0000169 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100170 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000171 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100172 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000173 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100174 cast = 'const wchar_t *'
175 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000176 if cast != string.expr:
177 # reinterpret_cast is necessary for GLubyte * <=> char *
178 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
179 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000180 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000181 else:
182 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100183 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000184
José Fonseca54f304a2012-01-14 19:33:08 +0000185 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000186 self.visit(const.type, instance)
187
José Fonseca54f304a2012-01-14 19:33:08 +0000188 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000189 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000190 for member in struct.members:
191 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000192 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000193
José Fonseca54f304a2012-01-14 19:33:08 +0000194 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100195 length = '_c' + array.type.tag
196 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000197 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100198 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000199 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100200 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100201 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100202 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000203 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100204 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000205 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100206 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100207 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100208 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100209 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000210
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200211 def visitAttribArray(self, array, instance):
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200212 # For each element, decide if it is a key or a value (which depends on the previous key).
213 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
214 # It is currently assumed that an unknown key means that it is followed by an int value.
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200215
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200216 # determine the array length which must be passed to writeArray() up front
José Fonseca77c10d82013-07-20 15:27:29 +0100217 count = '_c' + array.baseType.tag
José Fonsecaa78c1472013-07-20 14:05:10 +0100218 print ' {'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200219 print ' int %s;' % count
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200220 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
221 % {'c': count, 'array': instance, 'terminator': array.terminator}
222 if array.hasKeysWithoutValues:
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200223 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200224 for key, valueType in array.valueTypes:
225 if valueType is None:
226 print ' case %s:' % key
227 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
228 print ' break;'
229 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200230 print ' }'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200231 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200232 print ' trace::localWriter.beginArray(%s);' % count
233
234 # for each key / key-value pair write the key and the value, if the key requires one
235
José Fonseca77c10d82013-07-20 15:27:29 +0100236 index = '_i' + array.baseType.tag
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200237 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200238 print ' trace::localWriter.beginElement();'
José Fonseca77c10d82013-07-20 15:27:29 +0100239 self.visit(array.baseType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200240 print ' trace::localWriter.endElement();'
241 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
242 print ' break;'
243 print ' }'
Andreas Hartmetzedea8992013-07-12 11:37:35 +0200244 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200245 # write generic value the usual way
246 for key, valueType in array.valueTypes:
247 if valueType is not None:
248 print ' case %s:' % key
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200249 print ' trace::localWriter.beginElement();'
250 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
251 print ' trace::localWriter.endElement();'
252 print ' break;'
Andreas Hartmetzb491f9b2013-07-09 22:43:15 +0200253 # known key with no value, just decrease the index so we treat the next value as a key
254 if array.hasKeysWithoutValues:
255 for key, valueType in array.valueTypes:
256 if valueType is None:
257 print ' case %s:' % key
258 print ' %s--;' % index
259 print ' break;'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200260 # unknown key, write an int value
261 print ' default:'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200262 print ' trace::localWriter.beginElement();'
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200263 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
José Fonsecada7bbff2013-07-20 14:54:02 +0100264 '__FUNCTION__, int(%(array)s[%(i)s - 1]));' % {'array': instance, 'i': index}
Andreas Hartmetz621d0b32013-07-12 10:12:11 +0200265 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200266 print ' trace::localWriter.endElement();'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200267 print ' break;'
268 print ' }'
269 print ' }'
270 print ' trace::localWriter.endArray();'
José Fonsecaa78c1472013-07-20 14:05:10 +0100271 print ' }'
Andreas Hartmetzba7bb0d2013-07-07 22:51:12 +0200272
273
José Fonseca54f304a2012-01-14 19:33:08 +0000274 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000275 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000276
José Fonseca54f304a2012-01-14 19:33:08 +0000277 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100278 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000279
José Fonseca54f304a2012-01-14 19:33:08 +0000280 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100281 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000282
José Fonseca54f304a2012-01-14 19:33:08 +0000283 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100284 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100285 print ' trace::localWriter.beginArray(1);'
286 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000287 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100288 print ' trace::localWriter.endElement();'
289 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100290 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100291 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100292 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000293
José Fonseca59ee88e2012-01-15 14:24:10 +0000294 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100295 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000296
José Fonsecafbcf6832012-04-05 07:10:30 +0100297 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100298 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100299
José Fonseca59ee88e2012-01-15 14:24:10 +0000300 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100301 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000302
José Fonsecab89c5932012-04-01 22:47:11 +0200303 def visitReference(self, reference, instance):
304 self.visit(reference.type, instance)
305
José Fonseca54f304a2012-01-14 19:33:08 +0000306 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000307 self.visit(handle.type, instance)
308
José Fonseca54f304a2012-01-14 19:33:08 +0000309 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000310 self.visit(alias.type, instance)
311
José Fonseca54f304a2012-01-14 19:33:08 +0000312 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100313 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000314
José Fonseca54f304a2012-01-14 19:33:08 +0000315 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100316 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000317
José Fonseca54f304a2012-01-14 19:33:08 +0000318 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100319 if polymorphic.contextLess:
320 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
321 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000322 switchExpr = self.expand(polymorphic.switchExpr)
323 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100324 for cases, type in polymorphic.iterSwitch():
325 for case in cases:
326 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000327 caseInstance = instance
328 if type.expr is not None:
329 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
330 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100331 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000332 if polymorphic.defaultType is None:
333 print r' default:'
334 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
335 print r' trace::localWriter.writeNull();'
336 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100337 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100338
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000339
José Fonseca0075f152012-04-14 20:25:52 +0100340class WrapDecider(stdapi.Traverser):
341 '''Type visitor which will decide wheter this type will need wrapping or not.
342
343 For complex types (arrays, structures), we need to know this before hand.
344 '''
345
346 def __init__(self):
347 self.needsWrapping = False
348
José Fonseca0075f152012-04-14 20:25:52 +0100349 def visitLinearPointer(self, void):
350 pass
351
352 def visitInterface(self, interface):
353 self.needsWrapping = True
354
355
José Fonsecadbf714b2012-11-20 17:03:43 +0000356class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000357 '''Type visitor which will generate the code to wrap an instance.
358
359 Wrapping is necessary mostly for interfaces, however interface pointers can
360 appear anywhere inside complex types.
361 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000362
José Fonseca54f304a2012-01-14 19:33:08 +0000363 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000364 for member in struct.members:
365 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000366
José Fonseca54f304a2012-01-14 19:33:08 +0000367 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000368 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100369 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000370 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
371 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100372 print " }"
373 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000374
José Fonseca54f304a2012-01-14 19:33:08 +0000375 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100376 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000377 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100378 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000379
José Fonsecafbcf6832012-04-05 07:10:30 +0100380 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100381 elem_type = pointer.type.mutable()
382 if isinstance(elem_type, stdapi.Interface):
383 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100384 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
385 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100386 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100387 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100388
José Fonseca54f304a2012-01-14 19:33:08 +0000389 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100390 raise NotImplementedError
391
392 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100393 print " if (%s) {" % instance
José Fonsecab7a9b182012-11-23 17:02:48 +0000394 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100395 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100396
José Fonseca54f304a2012-01-14 19:33:08 +0000397 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100398 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100399 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000400
401
José Fonseca54f304a2012-01-14 19:33:08 +0000402class ValueUnwrapper(ValueWrapper):
403 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000404
José Fonseca0075f152012-04-14 20:25:52 +0100405 allocated = False
406
José Fonsecae7cb2b92012-09-28 08:40:24 +0100407 def visitStruct(self, struct, instance):
408 if not self.allocated:
409 # Argument is constant. We need to create a non const
410 print ' {'
411 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
412 print ' *_t = %s;' % (instance,)
413 assert instance.startswith('*')
414 print ' %s = _t;' % (instance[1:],)
415 instance = '*_t'
416 self.allocated = True
417 try:
418 return ValueWrapper.visitStruct(self, struct, instance)
419 finally:
420 print ' }'
421 else:
422 return ValueWrapper.visitStruct(self, struct, instance)
423
José Fonseca0075f152012-04-14 20:25:52 +0100424 def visitArray(self, array, instance):
425 if self.allocated or isinstance(instance, stdapi.Interface):
426 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000427 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100428 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000429 print " if (%s && %s) {" % (instance, array_length)
430 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
431 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100432 print " _t[_i] = %s[_i];" % instance
433 self.allocated = True
434 self.visit(array.type, "_t[_i]")
435 print " }"
436 print " %s = _t;" % instance
437 print " }"
438
José Fonseca9782b292012-04-14 22:02:42 +0100439 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000440 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100441 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000442 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
443 print r' %s = pWrapper->m_pInstance;' % (instance,)
444 print r' } else {'
445 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
446 print r' }'
447 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000448
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000449
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000450class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000451 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000452
José Fonseca4b466a92012-11-26 19:47:26 +0000453 # 0-3 are reserved to memcpy, malloc, free, and realloc
454 __id = 4
455
José Fonsecabb8760b2011-05-25 23:21:18 +0100456 def __init__(self):
457 self.api = None
458
José Fonseca54f304a2012-01-14 19:33:08 +0000459 def serializerFactory(self):
460 '''Create a serializer.
461
462 Can be overriden by derived classes to inject their own serialzer.
463 '''
464
465 return ValueSerializer()
466
José Fonseca1b6c8752012-04-15 14:33:00 +0100467 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100468 self.api = api
469
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000470 self.header(api)
471
472 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000473 for module in api.modules:
474 for header in module.headers:
475 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000476 print
477
José Fonseca54f304a2012-01-14 19:33:08 +0000478 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000479 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000480 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000481 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000482 print
483
484 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100485 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000486
487 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100488 self.interface = None
489 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000490 for function in api.getAllFunctions():
491 self.traceFunctionDecl(function)
492 for function in api.getAllFunctions():
493 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000494 print
495
496 self.footer(api)
497
498 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100499 print '#ifdef _WIN32'
500 print '# include <malloc.h> // alloca'
501 print '# ifndef alloca'
502 print '# define alloca _alloca'
503 print '# endif'
504 print '#else'
505 print '# include <alloca.h> // alloca'
506 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100507 print
José Fonseca537c5072012-07-07 12:54:09 +0100508 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000509 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000510
511 def footer(self, api):
512 pass
513
José Fonseca54f304a2012-01-14 19:33:08 +0000514 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000515 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000516
José Fonseca84cea3b2012-05-09 21:12:30 +0100517 if not function.internal:
518 if function.args:
519 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
520 else:
521 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100522 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 +0100523 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000524
José Fonseca4b466a92012-11-26 19:47:26 +0000525 def getFunctionSigId(self):
526 id = Tracer.__id
527 Tracer.__id += 1
528 return id
529
José Fonseca54f304a2012-01-14 19:33:08 +0000530 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100531 return True
532
José Fonseca54f304a2012-01-14 19:33:08 +0000533 def traceFunctionImpl(self, function):
534 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100535 print 'extern "C" PUBLIC'
536 else:
537 print 'extern "C" PRIVATE'
538 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000539 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100540 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100541
José Fonseca54f304a2012-01-14 19:33:08 +0000542 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000543 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100544 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000545 print '}'
546 print
547
José Fonseca54f304a2012-01-14 19:33:08 +0000548 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100549 if not function.internal:
550 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
551 for arg in function.args:
552 if not arg.output:
553 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000554 for arg in function.args:
555 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100556 self.serializeArg(function, arg)
557 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000558 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100559 if not function.internal:
560 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000561 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100562 for arg in function.args:
563 if arg.output:
564 self.serializeArg(function, arg)
565 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000566 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100567 if function.type is not stdapi.Void:
568 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100569 if function.type is not stdapi.Void:
570 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000571 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000572
José Fonseca2cfa02c2013-06-10 08:05:29 +0100573 def invokeFunction(self, function):
574 self.doInvokeFunction(function)
575
576 def doInvokeFunction(self, function, prefix='_', suffix=''):
577 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000578 if function.type is stdapi.Void:
579 result = ''
580 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100581 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100582 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000583 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000584
José Fonseca4fb1ab02012-11-08 10:23:40 +0000585 def wasFunctionSuccessful(self, function):
586 if function.type is stdapi.Void:
587 return 'true'
588 if str(function.type) == 'HRESULT':
589 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000590 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000591
José Fonseca54f304a2012-01-14 19:33:08 +0000592 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100593 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000594 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100595 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000596
José Fonseca54f304a2012-01-14 19:33:08 +0000597 def serializeArgValue(self, function, arg):
598 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000599
José Fonseca54f304a2012-01-14 19:33:08 +0000600 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100601 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100602
603 from specs.winapi import REFIID
604 riid = None
605 for other_arg in function.args:
606 if not other_arg.output and other_arg.type is REFIID:
607 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100608 if riid is not None \
609 and isinstance(arg.type, stdapi.Pointer) \
610 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100611 self.wrapIid(function, riid, arg)
612 return
613
José Fonseca54f304a2012-01-14 19:33:08 +0000614 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000615
José Fonseca54f304a2012-01-14 19:33:08 +0000616 def unwrapArg(self, function, arg):
617 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000618
José Fonseca54f304a2012-01-14 19:33:08 +0000619 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100620 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000621 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100622 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000623
José Fonseca54f304a2012-01-14 19:33:08 +0000624 def serializeValue(self, type, instance):
625 serializer = self.serializerFactory()
626 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca54f304a2012-01-14 19:33:08 +0000628 def wrapRet(self, function, instance):
629 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000630
José Fonseca0075f152012-04-14 20:25:52 +0100631 def needsWrapping(self, type):
632 visitor = WrapDecider()
633 visitor.visit(type)
634 return visitor.needsWrapping
635
José Fonseca54f304a2012-01-14 19:33:08 +0000636 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100637 if self.needsWrapping(type):
638 visitor = ValueWrapper()
639 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000640
641 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100642 if self.needsWrapping(type):
643 visitor = ValueUnwrapper()
644 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000645
José Fonseca143e9252012-04-15 09:31:18 +0100646 def traceInterfaces(self, api):
647 interfaces = api.getAllInterfaces()
648 if not interfaces:
649 return
650 map(self.declareWrapperInterface, interfaces)
651 self.implementIidWrapper(api)
652 map(self.implementWrapperInterface, interfaces)
653 print
654
José Fonseca0423d2c2012-01-20 19:16:17 +0000655 def declareWrapperInterface(self, interface):
656 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
657 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000658 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000659 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
660 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000661 print "public:"
662 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000663 print
José Fonseca01e50592014-08-22 15:35:27 +0100664
665 methods = list(interface.iterMethods())
666 for method in methods:
José Fonseca0423d2c2012-01-20 19:16:17 +0000667 print " " + method.prototype() + ";"
668 print
José Fonseca01e50592014-08-22 15:35:27 +0100669
José Fonsecaacc90622012-05-02 13:10:07 +0100670 for type, name, value in self.enumWrapperInterfaceVariables(interface):
671 print ' %s %s;' % (type, name)
José Fonseca01e50592014-08-22 15:35:27 +0100672 print
673
674 print r'private:'
675 print r' void _dummy(unsigned i) const {'
676 print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p\n", "%s", i, this, m_pInstance);' % interface.name
677 print r' trace::localWriter.flush();'
678 print r' os::abort();'
679 print r' }'
680 print
681 for i in range(len(methods), 64):
682 print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
683 print
684
José Fonseca0423d2c2012-01-20 19:16:17 +0000685 print "};"
686 print
687
José Fonsecaacc90622012-05-02 13:10:07 +0100688 def enumWrapperInterfaceVariables(self, interface):
689 return [
690 ("DWORD", "m_dwMagic", "0xd8365d6c"),
691 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000692 ("void *", "m_pVtbl", "*(void **)pInstance"),
693 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100694 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000695
696 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100697 self.interface = interface
698
José Fonsecab7a9b182012-11-23 17:02:48 +0000699 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000700 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100701 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100702 if value is not None:
703 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000704 print '}'
705 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000706
707 # Public constructor
708 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
709 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
710 print r' if (it != g_WrappedObjects.end()) {'
711 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
712 print r' assert(pWrapper);'
713 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
714 print r' assert(pWrapper->m_pInstance == pInstance);'
715 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
716 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonsecaab623c52014-07-22 17:05:00 +0100717 if debug:
718 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
José Fonsecab7a9b182012-11-23 17:02:48 +0000719 print r' return pWrapper;'
720 print r' }'
721 print r' }'
722 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonsecaab623c52014-07-22 17:05:00 +0100723 if debug:
724 print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000725 print r' g_WrappedObjects[pInstance] = pWrapper;'
726 print r' return pWrapper;'
727 print '}'
728 print
729
730 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000731 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonsecaab623c52014-07-22 17:05:00 +0100732 if debug:
733 print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000734 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000735 print '}'
736 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100737
José Fonseca4220b1b2012-02-03 19:05:29 +0000738 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100739 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000740 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100741
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000742 print
743
José Fonseca4220b1b2012-02-03 19:05:29 +0000744 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000745 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000746
747 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000748 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000749
José Fonseca0423d2c2012-01-20 19:16:17 +0000750 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100751 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000752
José Fonseca4220b1b2012-02-03 19:05:29 +0000753 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000754
755 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100756 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000757 print '}'
758 print
759
José Fonseca4220b1b2012-02-03 19:05:29 +0000760 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100761 assert not method.internal
762
José Fonseca632a78d2012-04-19 07:18:59 +0100763 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 +0100764 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 +0100765
766 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
767
José Fonseca632a78d2012-04-19 07:18:59 +0100768 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100769 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100770 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100771 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000772 for arg in method.args:
773 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000774 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000775 for arg in method.args:
776 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000777 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100778 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000779
José Fonseca4220b1b2012-02-03 19:05:29 +0000780 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000781
José Fonseca632a78d2012-04-19 07:18:59 +0100782 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000783
784 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000785 for arg in method.args:
786 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000787 self.serializeArg(method, arg)
788 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000789 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000790
José Fonseca87d1cc62010-11-29 15:57:25 +0000791 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100792 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100793 if method.type is not stdapi.Void:
794 self.wrapRet(method, '_result')
795
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000796 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000797 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000798 print r' if (!_result) {'
799 print r' delete this;'
800 print r' }'
801
802 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000803
José Fonseca143e9252012-04-15 09:31:18 +0100804 def implementIidWrapper(self, api):
805 print r'static void'
806 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
807 print r' os::log("apitrace: warning: %s: %s IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
808 print r' functionName, reason,'
809 print r' riid.Data1, riid.Data2, riid.Data3,'
810 print r' riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
811 print r'}'
812 print
813 print r'static void'
814 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
815 print r' if (!ppvObj || !*ppvObj) {'
816 print r' return;'
817 print r' }'
818 else_ = ''
819 for iface in api.getAllInterfaces():
820 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000821 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100822 print r' }'
823 else_ = 'else '
824 print r' %s{' % else_
825 print r' warnIID(functionName, riid, "unknown");'
826 print r' }'
827 print r'}'
828 print
829
José Fonsecabcb26b22012-04-15 08:42:25 +0100830 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100831 # Cast output arg to `void **` if necessary
832 out_name = out.name
833 obj_type = out.type.type.type
834 if not obj_type is stdapi.Void:
835 assert isinstance(obj_type, stdapi.Interface)
836 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
837
José Fonsecabcb26b22012-04-15 08:42:25 +0100838 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100839 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100840 else_ = ''
841 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100842 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100843 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100844 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100845 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100846 print r' }'
847 else_ = 'else '
848 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100849 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100850 print r' }'
851 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000852
José Fonseca4220b1b2012-02-03 19:05:29 +0000853 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000854 if method.type is stdapi.Void:
855 result = ''
856 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100857 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100858 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000859
José Fonseca6f0e3032014-06-25 01:00:35 +0100860 def emit_memcpy(self, ptr, size):
José Fonseca7f9ec132014-06-25 16:47:40 +0100861 print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
José Fonseca122c9872012-08-02 08:42:24 +0100862
863 def fake_call(self, function, args):
José Fonseca7a5f23a2014-06-24 19:20:36 +0100864 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca122c9872012-08-02 08:42:24 +0100865 for arg, instance in zip(function.args, args):
866 assert not arg.output
867 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
868 self.serializeValue(arg.type, instance)
869 print ' trace::localWriter.endArg();'
870 print ' trace::localWriter.endEnter();'
871 print ' trace::localWriter.beginLeave(_fake_call);'
872 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000873