blob: 4f39129add7c782a754f226f81dd5a6d1db82d39 [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é Fonsecabd86a222011-09-27 09:21:38 +010029import specs.stdapi as stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000030
31
José Fonseca0423d2c2012-01-20 19:16:17 +000032def getWrapperInterfaceName(interface):
José Fonseca87d1cc62010-11-29 15:57:25 +000033 return "Wrap" + interface.expr
34
José Fonseca6fac5ae2010-11-29 16:09:13 +000035
José Fonseca54f304a2012-01-14 19:33:08 +000036class ComplexValueSerializer(stdapi.OnceVisitor):
37 '''Type visitors which generates serialization functions for
38 complex types.
39
40 Simple types are serialized inline.
41 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000042
José Fonseca54f304a2012-01-14 19:33:08 +000043 def __init__(self, serializer):
44 stdapi.OnceVisitor.__init__(self)
45 self.serializer = serializer
46
47 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000048 pass
49
José Fonseca54f304a2012-01-14 19:33:08 +000050 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000051 pass
52
José Fonseca54f304a2012-01-14 19:33:08 +000053 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000054 pass
55
José Fonseca54f304a2012-01-14 19:33:08 +000056 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000057 self.visit(const.type)
58
José Fonseca54f304a2012-01-14 19:33:08 +000059 def visitStruct(self, struct):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000060 for type, name in struct.members:
61 self.visit(type)
José Fonseca06e85192011-10-16 14:15:36 +010062 print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
José Fonseca7eef8ce2010-11-26 15:46:36 +000063 print ' static const char * members[%u] = {' % (len(struct.members),)
64 for type, name, in struct.members:
65 print ' "%s",' % (name,)
66 print ' };'
José Fonsecab4a3d142011-10-27 07:43:19 +010067 print ' static const trace::StructSig sig = {'
José Fonseca02c25002011-10-15 13:17:26 +010068 print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000069 print ' };'
José Fonsecab4a3d142011-10-27 07:43:19 +010070 print ' trace::localWriter.beginStruct(&sig);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000071 for type, name in struct.members:
José Fonseca54f304a2012-01-14 19:33:08 +000072 self.serializer.visit(type, 'value.%s' % (name,))
José Fonsecab4a3d142011-10-27 07:43:19 +010073 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000074 print '}'
75 print
76
José Fonseca54f304a2012-01-14 19:33:08 +000077 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000078 self.visit(array.type)
79
José Fonseca54f304a2012-01-14 19:33:08 +000080 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000081 pass
82
José Fonseca54f304a2012-01-14 19:33:08 +000083 def visitEnum(self, enum):
José Fonsecaeb644512011-12-11 10:33:55 +000084 print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag)
85 for value in enum.values:
86 print ' {"%s", %s},' % (value, value)
87 print '};'
88 print
89 print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag)
90 print ' %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag)
91 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000092 print
93
José Fonseca54f304a2012-01-14 19:33:08 +000094 def visitBitmask(self, bitmask):
José Fonsecab4a3d142011-10-27 07:43:19 +010095 print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +000096 for value in bitmask.values:
José Fonsecad35973c2010-11-26 14:14:45 +000097 print ' {"%s", %s},' % (value, value)
98 print '};'
99 print
José Fonsecab4a3d142011-10-27 07:43:19 +0100100 print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag)
José Fonseca02c25002011-10-15 13:17:26 +0100101 print ' %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000102 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000103 print
104
José Fonseca54f304a2012-01-14 19:33:08 +0000105 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000106 self.visit(pointer.type)
107
José Fonseca59ee88e2012-01-15 14:24:10 +0000108 def visitIntPointer(self, pointer):
109 pass
110
111 def visitLinearPointer(self, pointer):
112 self.visit(pointer.type)
113
José Fonseca54f304a2012-01-14 19:33:08 +0000114 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000115 self.visit(handle.type)
116
José Fonsecab89c5932012-04-01 22:47:11 +0200117 def visitReference(self, reference):
118 self.visit(reference.type)
119
José Fonseca54f304a2012-01-14 19:33:08 +0000120 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000121 self.visit(alias.type)
122
José Fonseca54f304a2012-01-14 19:33:08 +0000123 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000124 pass
125
José Fonseca54f304a2012-01-14 19:33:08 +0000126 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000127 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000128
José Fonseca54f304a2012-01-14 19:33:08 +0000129 def visitPolymorphic(self, polymorphic):
José Fonseca06e85192011-10-16 14:15:36 +0100130 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100131 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000132 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100133 for case in cases:
134 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000135 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100136 print ' break;'
137 print ' }'
138 print '}'
139 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100140
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000141
José Fonseca54f304a2012-01-14 19:33:08 +0000142class ValueSerializer(stdapi.Visitor):
143 '''Visitor which generates code to serialize any type.
144
145 Simple types are serialized inline here, whereas the serialization of
146 complex types is dispatched to the serialization functions generated by
147 ComplexValueSerializer visitor above.
148 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000149
José Fonseca54f304a2012-01-14 19:33:08 +0000150 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100151 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000152
José Fonseca54f304a2012-01-14 19:33:08 +0000153 def visitString(self, string, instance):
José Fonseca280a1762012-01-31 15:10:13 +0000154 if string.kind == 'String':
155 cast = 'const char *'
156 elif string.kind == 'WString':
157 cast = 'const wchar_t *'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000158 else:
José Fonseca280a1762012-01-31 15:10:13 +0000159 assert False
160 if cast != string.expr:
161 # reinterpret_cast is necessary for GLubyte * <=> char *
162 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
163 if string.length is not None:
164 length = ', %s' % string.length
165 else:
166 length = ''
167 print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000168
José Fonseca54f304a2012-01-14 19:33:08 +0000169 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000170 self.visit(const.type, instance)
171
José Fonseca54f304a2012-01-14 19:33:08 +0000172 def visitStruct(self, struct, instance):
José Fonseca06e85192011-10-16 14:15:36 +0100173 print ' _write__%s(%s);' % (struct.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000174
José Fonseca54f304a2012-01-14 19:33:08 +0000175 def visitArray(self, array, instance):
José Fonseca02c25002011-10-15 13:17:26 +0100176 length = '__c' + array.type.tag
177 index = '__i' + array.type.tag
José Fonsecafd34e4e2011-06-03 19:34:29 +0100178 print ' if (%s) {' % instance
179 print ' size_t %s = %s;' % (length, array.length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100180 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100181 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100182 print ' trace::localWriter.beginElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000183 self.visit(array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100184 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000185 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100186 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100187 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100188 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100189 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000190
José Fonseca54f304a2012-01-14 19:33:08 +0000191 def visitBlob(self, blob, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100192 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000193
José Fonseca54f304a2012-01-14 19:33:08 +0000194 def visitEnum(self, enum, instance):
José Fonsecaeb644512011-12-11 10:33:55 +0000195 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000196
José Fonseca54f304a2012-01-14 19:33:08 +0000197 def visitBitmask(self, bitmask, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100198 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000199
José Fonseca54f304a2012-01-14 19:33:08 +0000200 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100201 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100202 print ' trace::localWriter.beginArray(1);'
203 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000204 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100205 print ' trace::localWriter.endElement();'
206 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
José Fonseca59ee88e2012-01-15 14:24:10 +0000211 def visitIntPointer(self, pointer, instance):
212 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
213
214 def visitLinearPointer(self, pointer, instance):
215 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
216
José Fonsecab89c5932012-04-01 22:47:11 +0200217 def visitReference(self, reference, instance):
218 self.visit(reference.type, instance)
219
José Fonseca54f304a2012-01-14 19:33:08 +0000220 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000221 self.visit(handle.type, instance)
222
José Fonseca54f304a2012-01-14 19:33:08 +0000223 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000224 self.visit(alias.type, instance)
225
José Fonseca54f304a2012-01-14 19:33:08 +0000226 def visitOpaque(self, opaque, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100227 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000228
José Fonseca54f304a2012-01-14 19:33:08 +0000229 def visitInterface(self, interface, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100230 print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000231
José Fonseca54f304a2012-01-14 19:33:08 +0000232 def visitPolymorphic(self, polymorphic, instance):
233 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100234
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000235
José Fonseca54f304a2012-01-14 19:33:08 +0000236class ValueWrapper(stdapi.Visitor):
237 '''Type visitor which will generate the code to wrap an instance.
238
239 Wrapping is necessary mostly for interfaces, however interface pointers can
240 appear anywhere inside complex types.
241 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000242
José Fonseca54f304a2012-01-14 19:33:08 +0000243 def visitVoid(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000244 raise NotImplementedError
245
José Fonseca54f304a2012-01-14 19:33:08 +0000246 def visitLiteral(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000247 pass
248
José Fonseca54f304a2012-01-14 19:33:08 +0000249 def visitString(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000250 pass
251
José Fonseca54f304a2012-01-14 19:33:08 +0000252 def visitConst(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000253 pass
254
José Fonseca54f304a2012-01-14 19:33:08 +0000255 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000256 for type, name in struct.members:
257 self.visit(type, "(%s).%s" % (instance, name))
258
José Fonseca54f304a2012-01-14 19:33:08 +0000259 def visitArray(self, array, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000260 # XXX: actually it is possible to return an array of pointers
261 pass
262
José Fonseca54f304a2012-01-14 19:33:08 +0000263 def visitBlob(self, blob, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000264 pass
265
José Fonseca54f304a2012-01-14 19:33:08 +0000266 def visitEnum(self, enum, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000267 pass
268
José Fonseca54f304a2012-01-14 19:33:08 +0000269 def visitBitmask(self, bitmask, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000270 pass
271
José Fonseca54f304a2012-01-14 19:33:08 +0000272 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100273 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000274 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100275 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000276
277 def visitIntPointer(self, pointer, instance):
278 pass
279
280 def visitLinearPointer(self, pointer, instance):
281 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000282
José Fonsecab89c5932012-04-01 22:47:11 +0200283 def visitReference(self, reference, instance):
284 self.visit(reference.type, instance)
285
José Fonseca54f304a2012-01-14 19:33:08 +0000286 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000287 self.visit(handle.type, instance)
288
José Fonseca54f304a2012-01-14 19:33:08 +0000289 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000290 self.visit(alias.type, instance)
291
José Fonseca54f304a2012-01-14 19:33:08 +0000292 def visitOpaque(self, opaque, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000293 pass
294
José Fonseca54f304a2012-01-14 19:33:08 +0000295 def visitInterface(self, interface, instance):
José Fonseca87d1cc62010-11-29 15:57:25 +0000296 assert instance.startswith('*')
297 instance = instance[1:]
José Fonseca3a2a4762011-05-26 11:37:30 +0100298 print " if (%s) {" % instance
José Fonseca0423d2c2012-01-20 19:16:17 +0000299 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100300 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100301
José Fonseca54f304a2012-01-14 19:33:08 +0000302 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100303 # XXX: There might be polymorphic values that need wrapping in the future
304 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000305
306
José Fonseca54f304a2012-01-14 19:33:08 +0000307class ValueUnwrapper(ValueWrapper):
308 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000309
José Fonseca54f304a2012-01-14 19:33:08 +0000310 def visitInterface(self, interface, instance):
José Fonseca87d1cc62010-11-29 15:57:25 +0000311 assert instance.startswith('*')
312 instance = instance[1:]
José Fonseca7aa86902012-01-31 20:14:31 +0000313 print r' if (%s) {' % instance
314 print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
315 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
316 print r' %s = pWrapper->m_pInstance;' % (instance,)
317 print r' } else {'
318 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
319 print r' }'
320 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000321
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000322
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000323class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000324 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000325
José Fonsecabb8760b2011-05-25 23:21:18 +0100326 def __init__(self):
327 self.api = None
328
José Fonseca54f304a2012-01-14 19:33:08 +0000329 def serializerFactory(self):
330 '''Create a serializer.
331
332 Can be overriden by derived classes to inject their own serialzer.
333 '''
334
335 return ValueSerializer()
336
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000337 def trace_api(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100338 self.api = api
339
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340 self.header(api)
341
342 # Includes
343 for header in api.headers:
José Fonsecae6a50bd2010-11-24 10:12:22 +0000344 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000345 print
346
José Fonseca54f304a2012-01-14 19:33:08 +0000347 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000348 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000349 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000350 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000351 print
352
353 # Interfaces wrapers
José Fonseca2ef6d5b2012-01-31 10:56:38 +0000354 interfaces = api.getAllInterfaces()
José Fonseca0423d2c2012-01-20 19:16:17 +0000355 map(self.declareWrapperInterface, interfaces)
356 map(self.implementWrapperInterface, interfaces)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000357 print
358
359 # Function wrappers
José Fonseca54f304a2012-01-14 19:33:08 +0000360 map(self.traceFunctionDecl, api.functions)
361 map(self.traceFunctionImpl, api.functions)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000362 print
363
364 self.footer(api)
365
366 def header(self, api):
José Fonseca0ad465c2011-08-24 16:58:13 +0100367 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000368
369 def footer(self, api):
370 pass
371
José Fonseca54f304a2012-01-14 19:33:08 +0000372 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000373 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000374
José Fonseca14c21bc2011-02-20 23:32:22 +0000375 if function.args:
376 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000377 else:
José Fonseca14c21bc2011-02-20 23:32:22 +0000378 print 'static const char ** __%s_args = NULL;' % (function.name,)
José Fonsecab4a3d142011-10-27 07:43:19 +0100379 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000380 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000381
José Fonseca54f304a2012-01-14 19:33:08 +0000382 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100383 return True
384
José Fonseca54f304a2012-01-14 19:33:08 +0000385 def traceFunctionImpl(self, function):
386 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100387 print 'extern "C" PUBLIC'
388 else:
389 print 'extern "C" PRIVATE'
390 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000391 if function.type is not stdapi.Void:
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000392 print ' %s __result;' % function.type
José Fonseca54f304a2012-01-14 19:33:08 +0000393 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000394 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000395 self.wrapRet(function, "__result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000396 print ' return __result;'
397 print '}'
398 print
399
José Fonseca54f304a2012-01-14 19:33:08 +0000400 def traceFunctionImplBody(self, function):
José Fonsecab4a3d142011-10-27 07:43:19 +0100401 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000402 for arg in function.args:
403 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000404 self.unwrapArg(function, arg)
405 self.serializeArg(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100406 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000407 self.invokeFunction(function)
José Fonsecab4a3d142011-10-27 07:43:19 +0100408 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000409 for arg in function.args:
410 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000411 self.serializeArg(function, arg)
412 self.wrapArg(function, arg)
José Fonseca9796b842010-11-25 11:44:50 +0000413 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000414 self.serializeRet(function, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100415 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000416
José Fonseca54f304a2012-01-14 19:33:08 +0000417 def invokeFunction(self, function, prefix='__', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000418 if function.type is stdapi.Void:
419 result = ''
420 else:
421 result = '__result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100422 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000423 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000424
José Fonseca54f304a2012-01-14 19:33:08 +0000425 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100426 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000427 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100428 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000429
José Fonseca54f304a2012-01-14 19:33:08 +0000430 def serializeArgValue(self, function, arg):
431 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000432
José Fonseca54f304a2012-01-14 19:33:08 +0000433 def wrapArg(self, function, arg):
434 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000435
José Fonseca54f304a2012-01-14 19:33:08 +0000436 def unwrapArg(self, function, arg):
437 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000438
José Fonseca54f304a2012-01-14 19:33:08 +0000439 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100440 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000441 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100442 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000443
José Fonseca54f304a2012-01-14 19:33:08 +0000444 def serializeValue(self, type, instance):
445 serializer = self.serializerFactory()
446 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000447
José Fonseca54f304a2012-01-14 19:33:08 +0000448 def wrapRet(self, function, instance):
449 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000450
José Fonseca54f304a2012-01-14 19:33:08 +0000451 def unwrapRet(self, function, instance):
452 self.unwrapValue(function.type, instance)
453
454 def wrapValue(self, type, instance):
455 visitor = ValueWrapper()
456 visitor.visit(type, instance)
457
458 def unwrapValue(self, type, instance):
459 visitor = ValueUnwrapper()
460 visitor.visit(type, instance)
461
José Fonseca0423d2c2012-01-20 19:16:17 +0000462 def declareWrapperInterface(self, interface):
463 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
464 print "{"
465 print "public:"
466 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
467 print " virtual ~%s();" % getWrapperInterfaceName(interface)
468 print
469 for method in interface.iterMethods():
470 print " " + method.prototype() + ";"
471 print
472 self.declareWrapperInterfaceVariables(interface)
473 print "};"
474 print
475
476 def declareWrapperInterfaceVariables(self, interface):
477 #print "private:"
José Fonseca7aa86902012-01-31 20:14:31 +0000478 print " DWORD m_dwMagic;"
José Fonseca0423d2c2012-01-20 19:16:17 +0000479 print " %s * m_pInstance;" % (interface.name,)
480
481 def implementWrapperInterface(self, interface):
482 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonseca7aa86902012-01-31 20:14:31 +0000483 print ' m_dwMagic = 0xd8365d6c;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000484 print ' m_pInstance = pInstance;'
485 print '}'
486 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000487 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000488 print '}'
489 print
José Fonseca4220b1b2012-02-03 19:05:29 +0000490 for base, method in interface.iterBaseMethods():
491 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000492 print
493
José Fonseca4220b1b2012-02-03 19:05:29 +0000494 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000495 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
496 if method.type is not stdapi.Void:
497 print ' %s __result;' % method.type
498
José Fonseca4220b1b2012-02-03 19:05:29 +0000499 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000500
501 if method.type is not stdapi.Void:
502 print ' return __result;'
503 print '}'
504 print
505
José Fonseca4220b1b2012-02-03 19:05:29 +0000506 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca87d1cc62010-11-29 15:57:25 +0000507 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
José Fonsecab4a3d142011-10-27 07:43:19 +0100508 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
509 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
510 print ' trace::localWriter.beginArg(0);'
511 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
512 print ' trace::localWriter.endArg();'
José Fonseca1ce52f02012-01-31 12:19:57 +0000513
514 from specs.winapi import REFIID
José Fonseca3d2b0652012-01-31 19:35:24 +0000515 from specs.stdapi import Pointer, Opaque, Interface
José Fonseca1ce52f02012-01-31 12:19:57 +0000516
517 riid = None
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000518 for arg in method.args:
519 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000520 self.unwrapArg(method, arg)
521 self.serializeArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000522 if arg.type is REFIID:
523 riid = arg
José Fonsecab4a3d142011-10-27 07:43:19 +0100524 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000525
José Fonseca4220b1b2012-02-03 19:05:29 +0000526 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000527
José Fonsecab4a3d142011-10-27 07:43:19 +0100528 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000529 for arg in method.args:
530 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000531 self.serializeArg(method, arg)
532 self.wrapArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000533 if riid is not None and isinstance(arg.type, Pointer):
José Fonseca3d2b0652012-01-31 19:35:24 +0000534 if isinstance(arg.type.type, Opaque):
535 self.wrapIid(riid, arg)
536 else:
537 assert isinstance(arg.type.type, Pointer)
538 assert isinstance(arg.type.type.type, Interface)
José Fonseca1ce52f02012-01-31 12:19:57 +0000539
José Fonseca87d1cc62010-11-29 15:57:25 +0000540 if method.type is not stdapi.Void:
José Fonsecab4a3d142011-10-27 07:43:19 +0100541 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000542 self.serializeValue(method.type, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100543 print ' trace::localWriter.endReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000544 self.wrapValue(method.type, '__result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100545 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000546 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000547 assert method.type is not stdapi.Void
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000548 print ' if (!__result)'
549 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000550
José Fonseca7aa86902012-01-31 20:14:31 +0000551 def wrapIid(self, riid, out):
José Fonseca1ce52f02012-01-31 12:19:57 +0000552 print ' if (%s && *%s) {' % (out.name, out.name)
553 print ' if (*%s == m_pInstance) {' % (out.name,)
554 print ' *%s = this;' % (out.name,)
555 print ' }'
José Fonsecaccf250c2012-02-03 19:06:31 +0000556 for iface in self.api.getAllInterfaces():
José Fonseca1ce52f02012-01-31 12:19:57 +0000557 print r' else if (%s == IID_%s) {' % (riid.name, iface.name)
558 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
559 print r' }'
560 print r' else {'
José Fonseca7aa86902012-01-31 20:14:31 +0000561 print r' os::log("apitrace: warning: %s: unknown REFIID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
562 print r' __FUNCTION__,'
José Fonseca1ce52f02012-01-31 12:19:57 +0000563 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
564 print r' %s.Data4[0],' % (riid.name,)
565 print r' %s.Data4[1],' % (riid.name,)
566 print r' %s.Data4[2],' % (riid.name,)
567 print r' %s.Data4[3],' % (riid.name,)
568 print r' %s.Data4[4],' % (riid.name,)
569 print r' %s.Data4[5],' % (riid.name,)
570 print r' %s.Data4[6],' % (riid.name,)
571 print r' %s.Data4[7]);' % (riid.name,)
572 print r' }'
573 print ' }'
574
José Fonseca4220b1b2012-02-03 19:05:29 +0000575 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000576 if method.type is stdapi.Void:
577 result = ''
578 else:
579 result = '__result = '
José Fonseca4220b1b2012-02-03 19:05:29 +0000580 print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000581
582 def emit_memcpy(self, dest, src, length):
583 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
584 print ' trace::localWriter.beginArg(0);'
585 print ' trace::localWriter.writeOpaque(%s);' % dest
586 print ' trace::localWriter.endArg();'
587 print ' trace::localWriter.beginArg(1);'
588 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
589 print ' trace::localWriter.endArg();'
590 print ' trace::localWriter.beginArg(2);'
591 print ' trace::localWriter.writeUInt(%s);' % length
592 print ' trace::localWriter.endArg();'
593 print ' trace::localWriter.endEnter();'
594 print ' trace::localWriter.beginLeave(__call);'
595 print ' trace::localWriter.endLeave();'
596