blob: 706d3479dcb15473d5254b1ad56e6a840e179571 [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é Fonseca54f304a2012-01-14 19:33:08 +000042class ComplexValueSerializer(stdapi.OnceVisitor):
43 '''Type visitors which generates serialization functions for
44 complex types.
45
46 Simple types are serialized inline.
47 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000048
José Fonseca54f304a2012-01-14 19:33:08 +000049 def __init__(self, serializer):
50 stdapi.OnceVisitor.__init__(self)
51 self.serializer = serializer
52
53 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000054 pass
55
José Fonseca54f304a2012-01-14 19:33:08 +000056 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000057 pass
58
José Fonseca54f304a2012-01-14 19:33:08 +000059 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000060 pass
61
José Fonseca54f304a2012-01-14 19:33:08 +000062 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000063 self.visit(const.type)
64
José Fonseca54f304a2012-01-14 19:33:08 +000065 def visitStruct(self, struct):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000066 for type, name in struct.members:
67 self.visit(type)
José Fonseca06e85192011-10-16 14:15:36 +010068 print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
José Fonseca7eef8ce2010-11-26 15:46:36 +000069 print ' static const char * members[%u] = {' % (len(struct.members),)
70 for type, name, in struct.members:
71 print ' "%s",' % (name,)
72 print ' };'
José Fonsecab4a3d142011-10-27 07:43:19 +010073 print ' static const trace::StructSig sig = {'
José Fonseca02c25002011-10-15 13:17:26 +010074 print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000075 print ' };'
José Fonsecab4a3d142011-10-27 07:43:19 +010076 print ' trace::localWriter.beginStruct(&sig);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000077 for type, name in struct.members:
José Fonseca54f304a2012-01-14 19:33:08 +000078 self.serializer.visit(type, 'value.%s' % (name,))
José Fonsecab4a3d142011-10-27 07:43:19 +010079 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000080 print '}'
81 print
82
José Fonseca54f304a2012-01-14 19:33:08 +000083 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000084 self.visit(array.type)
85
José Fonseca54f304a2012-01-14 19:33:08 +000086 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000087 pass
88
José Fonseca54f304a2012-01-14 19:33:08 +000089 def visitEnum(self, enum):
José Fonsecaeb644512011-12-11 10:33:55 +000090 print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag)
91 for value in enum.values:
92 print ' {"%s", %s},' % (value, value)
93 print '};'
94 print
95 print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag)
96 print ' %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag)
97 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000098 print
99
José Fonseca54f304a2012-01-14 19:33:08 +0000100 def visitBitmask(self, bitmask):
José Fonsecab4a3d142011-10-27 07:43:19 +0100101 print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000102 for value in bitmask.values:
José Fonsecad35973c2010-11-26 14:14:45 +0000103 print ' {"%s", %s},' % (value, value)
104 print '};'
105 print
José Fonsecab4a3d142011-10-27 07:43:19 +0100106 print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag)
José Fonseca02c25002011-10-15 13:17:26 +0100107 print ' %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000108 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000109 print
110
José Fonseca54f304a2012-01-14 19:33:08 +0000111 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000112 self.visit(pointer.type)
113
José Fonseca59ee88e2012-01-15 14:24:10 +0000114 def visitIntPointer(self, pointer):
115 pass
116
José Fonsecafbcf6832012-04-05 07:10:30 +0100117 def visitObjPointer(self, pointer):
118 self.visit(pointer.type)
119
José Fonseca59ee88e2012-01-15 14:24:10 +0000120 def visitLinearPointer(self, pointer):
121 self.visit(pointer.type)
122
José Fonseca54f304a2012-01-14 19:33:08 +0000123 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000124 self.visit(handle.type)
125
José Fonsecab89c5932012-04-01 22:47:11 +0200126 def visitReference(self, reference):
127 self.visit(reference.type)
128
José Fonseca54f304a2012-01-14 19:33:08 +0000129 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000130 self.visit(alias.type)
131
José Fonseca54f304a2012-01-14 19:33:08 +0000132 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000133 pass
134
José Fonseca54f304a2012-01-14 19:33:08 +0000135 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000136 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitPolymorphic(self, polymorphic):
José Fonseca06e85192011-10-16 14:15:36 +0100139 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100140 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000141 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100142 for case in cases:
143 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000144 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100145 print ' break;'
146 print ' }'
147 print '}'
148 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100149
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000150
José Fonseca54f304a2012-01-14 19:33:08 +0000151class ValueSerializer(stdapi.Visitor):
152 '''Visitor which generates code to serialize any type.
153
154 Simple types are serialized inline here, whereas the serialization of
155 complex types is dispatched to the serialization functions generated by
156 ComplexValueSerializer visitor above.
157 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000158
José Fonseca54f304a2012-01-14 19:33:08 +0000159 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100160 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000161
José Fonseca54f304a2012-01-14 19:33:08 +0000162 def visitString(self, string, instance):
José Fonseca280a1762012-01-31 15:10:13 +0000163 if string.kind == 'String':
164 cast = 'const char *'
165 elif string.kind == 'WString':
166 cast = 'const wchar_t *'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000167 else:
José Fonseca280a1762012-01-31 15:10:13 +0000168 assert False
169 if cast != string.expr:
170 # reinterpret_cast is necessary for GLubyte * <=> char *
171 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
172 if string.length is not None:
173 length = ', %s' % string.length
174 else:
175 length = ''
176 print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000177
José Fonseca54f304a2012-01-14 19:33:08 +0000178 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000179 self.visit(const.type, instance)
180
José Fonseca54f304a2012-01-14 19:33:08 +0000181 def visitStruct(self, struct, instance):
José Fonseca06e85192011-10-16 14:15:36 +0100182 print ' _write__%s(%s);' % (struct.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000183
José Fonseca54f304a2012-01-14 19:33:08 +0000184 def visitArray(self, array, instance):
José Fonseca02c25002011-10-15 13:17:26 +0100185 length = '__c' + array.type.tag
186 index = '__i' + array.type.tag
José Fonsecafd34e4e2011-06-03 19:34:29 +0100187 print ' if (%s) {' % instance
188 print ' size_t %s = %s;' % (length, array.length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100189 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100190 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100191 print ' trace::localWriter.beginElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000192 self.visit(array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100193 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000194 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100195 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100196 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100197 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100198 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000199
José Fonseca54f304a2012-01-14 19:33:08 +0000200 def visitBlob(self, blob, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100201 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000202
José Fonseca54f304a2012-01-14 19:33:08 +0000203 def visitEnum(self, enum, instance):
José Fonsecaeb644512011-12-11 10:33:55 +0000204 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000205
José Fonseca54f304a2012-01-14 19:33:08 +0000206 def visitBitmask(self, bitmask, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100207 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000208
José Fonseca54f304a2012-01-14 19:33:08 +0000209 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100210 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100211 print ' trace::localWriter.beginArray(1);'
212 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000213 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100214 print ' trace::localWriter.endElement();'
215 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100216 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100217 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100218 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000219
José Fonseca59ee88e2012-01-15 14:24:10 +0000220 def visitIntPointer(self, pointer, instance):
221 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
222
José Fonsecafbcf6832012-04-05 07:10:30 +0100223 def visitObjPointer(self, pointer, instance):
224 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
225
José Fonseca59ee88e2012-01-15 14:24:10 +0000226 def visitLinearPointer(self, pointer, instance):
227 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
228
José Fonsecab89c5932012-04-01 22:47:11 +0200229 def visitReference(self, reference, instance):
230 self.visit(reference.type, instance)
231
José Fonseca54f304a2012-01-14 19:33:08 +0000232 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000233 self.visit(handle.type, instance)
234
José Fonseca54f304a2012-01-14 19:33:08 +0000235 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000236 self.visit(alias.type, instance)
237
José Fonseca54f304a2012-01-14 19:33:08 +0000238 def visitOpaque(self, opaque, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100239 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000240
José Fonseca54f304a2012-01-14 19:33:08 +0000241 def visitInterface(self, interface, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100242 print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000243
José Fonseca54f304a2012-01-14 19:33:08 +0000244 def visitPolymorphic(self, polymorphic, instance):
245 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
José Fonseca16d46dd2011-10-13 09:52:52 +0100246
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000247
José Fonseca0075f152012-04-14 20:25:52 +0100248class WrapDecider(stdapi.Traverser):
249 '''Type visitor which will decide wheter this type will need wrapping or not.
250
251 For complex types (arrays, structures), we need to know this before hand.
252 '''
253
254 def __init__(self):
255 self.needsWrapping = False
256
José Fonseca0075f152012-04-14 20:25:52 +0100257 def visitLinearPointer(self, void):
258 pass
259
260 def visitInterface(self, interface):
261 self.needsWrapping = True
262
263
264class ValueWrapper(stdapi.Traverser):
José Fonseca54f304a2012-01-14 19:33:08 +0000265 '''Type visitor which will generate the code to wrap an instance.
266
267 Wrapping is necessary mostly for interfaces, however interface pointers can
268 appear anywhere inside complex types.
269 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000270
José Fonseca54f304a2012-01-14 19:33:08 +0000271 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000272 for type, name in struct.members:
273 self.visit(type, "(%s).%s" % (instance, name))
274
José Fonseca54f304a2012-01-14 19:33:08 +0000275 def visitArray(self, array, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100276 print " if (%s) {" % instance
277 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
278 self.visit(array.type, instance + "[_i]")
279 print " }"
280 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000281
José Fonseca54f304a2012-01-14 19:33:08 +0000282 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100283 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000284 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100285 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000286
José Fonsecafbcf6832012-04-05 07:10:30 +0100287 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100288 elem_type = pointer.type.mutable()
289 if isinstance(elem_type, stdapi.Interface):
290 self.visitInterfacePointer(elem_type, instance)
291 else:
292 self.visitPointer(self, pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100293
José Fonseca54f304a2012-01-14 19:33:08 +0000294 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100295 raise NotImplementedError
296
297 def visitInterfacePointer(self, interface, instance):
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
José Fonseca0075f152012-04-14 20:25:52 +0100304 raise NotImplementedError
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é Fonseca0075f152012-04-14 20:25:52 +0100310 allocated = False
311
312 def visitArray(self, array, instance):
313 if self.allocated or isinstance(instance, stdapi.Interface):
314 return ValueWrapper.visitArray(self, array, instance)
315 elem_type = array.type.mutable()
316 print " if (%s && %s) {" % (instance, array.length)
317 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
318 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
319 print " _t[_i] = %s[_i];" % instance
320 self.allocated = True
321 self.visit(array.type, "_t[_i]")
322 print " }"
323 print " %s = _t;" % instance
324 print " }"
325
José Fonseca9782b292012-04-14 22:02:42 +0100326 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000327 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100328 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000329 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
330 print r' %s = pWrapper->m_pInstance;' % (instance,)
331 print r' } else {'
332 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
333 print r' }'
334 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000335
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000336
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000337class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000338 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000339
José Fonsecabb8760b2011-05-25 23:21:18 +0100340 def __init__(self):
341 self.api = None
342
José Fonseca54f304a2012-01-14 19:33:08 +0000343 def serializerFactory(self):
344 '''Create a serializer.
345
346 Can be overriden by derived classes to inject their own serialzer.
347 '''
348
349 return ValueSerializer()
350
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000351 def trace_api(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100352 self.api = api
353
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000354 self.header(api)
355
356 # Includes
357 for header in api.headers:
José Fonsecae6a50bd2010-11-24 10:12:22 +0000358 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000359 print
360
José Fonseca54f304a2012-01-14 19:33:08 +0000361 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000362 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000363 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000364 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000365 print
366
367 # Interfaces wrapers
José Fonseca2ef6d5b2012-01-31 10:56:38 +0000368 interfaces = api.getAllInterfaces()
José Fonseca0423d2c2012-01-20 19:16:17 +0000369 map(self.declareWrapperInterface, interfaces)
370 map(self.implementWrapperInterface, interfaces)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000371 print
372
373 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100374 self.interface = None
375 self.base = None
José Fonseca54f304a2012-01-14 19:33:08 +0000376 map(self.traceFunctionDecl, api.functions)
377 map(self.traceFunctionImpl, api.functions)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000378 print
379
380 self.footer(api)
381
382 def header(self, api):
José Fonseca0ad465c2011-08-24 16:58:13 +0100383 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000384
385 def footer(self, api):
386 pass
387
José Fonseca54f304a2012-01-14 19:33:08 +0000388 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000389 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000390
José Fonseca14c21bc2011-02-20 23:32:22 +0000391 if function.args:
392 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 +0000393 else:
José Fonseca14c21bc2011-02-20 23:32:22 +0000394 print 'static const char ** __%s_args = NULL;' % (function.name,)
José Fonsecab4a3d142011-10-27 07:43:19 +0100395 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 +0000396 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000397
José Fonseca54f304a2012-01-14 19:33:08 +0000398 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100399 return True
400
José Fonseca54f304a2012-01-14 19:33:08 +0000401 def traceFunctionImpl(self, function):
402 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100403 print 'extern "C" PUBLIC'
404 else:
405 print 'extern "C" PRIVATE'
406 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000407 if function.type is not stdapi.Void:
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000408 print ' %s __result;' % function.type
José Fonseca54f304a2012-01-14 19:33:08 +0000409 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000410 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000411 self.wrapRet(function, "__result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000412 print ' return __result;'
413 print '}'
414 print
415
José Fonseca54f304a2012-01-14 19:33:08 +0000416 def traceFunctionImplBody(self, function):
José Fonsecab4a3d142011-10-27 07:43:19 +0100417 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000418 for arg in function.args:
419 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000420 self.unwrapArg(function, arg)
421 self.serializeArg(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100422 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000423 self.invokeFunction(function)
José Fonsecab4a3d142011-10-27 07:43:19 +0100424 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000425 for arg in function.args:
426 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000427 self.serializeArg(function, arg)
428 self.wrapArg(function, arg)
José Fonseca9796b842010-11-25 11:44:50 +0000429 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000430 self.serializeRet(function, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100431 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000432
José Fonseca54f304a2012-01-14 19:33:08 +0000433 def invokeFunction(self, function, prefix='__', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000434 if function.type is stdapi.Void:
435 result = ''
436 else:
437 result = '__result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100438 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000439 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000440
José Fonseca54f304a2012-01-14 19:33:08 +0000441 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100442 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000443 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100444 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000445
José Fonseca54f304a2012-01-14 19:33:08 +0000446 def serializeArgValue(self, function, arg):
447 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000448
José Fonseca54f304a2012-01-14 19:33:08 +0000449 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100450 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100451
452 from specs.winapi import REFIID
453 riid = None
454 for other_arg in function.args:
455 if not other_arg.output and other_arg.type is REFIID:
456 riid = other_arg
457 if riid is not None and isinstance(arg.type, stdapi.Pointer):
458 assert isinstance(arg.type.type, stdapi.ObjPointer)
459 obj_type = arg.type.type.type
460 assert obj_type is stdapi.Void
461 self.wrapIid(function, riid, arg)
462 return
463
José Fonseca54f304a2012-01-14 19:33:08 +0000464 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000465
José Fonseca54f304a2012-01-14 19:33:08 +0000466 def unwrapArg(self, function, arg):
467 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000468
José Fonseca54f304a2012-01-14 19:33:08 +0000469 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100470 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000471 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100472 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000473
José Fonseca54f304a2012-01-14 19:33:08 +0000474 def serializeValue(self, type, instance):
475 serializer = self.serializerFactory()
476 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000477
José Fonseca54f304a2012-01-14 19:33:08 +0000478 def wrapRet(self, function, instance):
479 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000480
José Fonseca54f304a2012-01-14 19:33:08 +0000481 def unwrapRet(self, function, instance):
482 self.unwrapValue(function.type, instance)
483
José Fonseca0075f152012-04-14 20:25:52 +0100484 def needsWrapping(self, type):
485 visitor = WrapDecider()
486 visitor.visit(type)
487 return visitor.needsWrapping
488
José Fonseca54f304a2012-01-14 19:33:08 +0000489 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100490 if self.needsWrapping(type):
491 visitor = ValueWrapper()
492 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000493
494 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100495 if self.needsWrapping(type):
496 visitor = ValueUnwrapper()
497 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000498
José Fonseca0423d2c2012-01-20 19:16:17 +0000499 def declareWrapperInterface(self, interface):
500 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
501 print "{"
502 print "public:"
503 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
504 print " virtual ~%s();" % getWrapperInterfaceName(interface)
505 print
506 for method in interface.iterMethods():
507 print " " + method.prototype() + ";"
508 print
509 self.declareWrapperInterfaceVariables(interface)
510 print "};"
511 print
512
513 def declareWrapperInterfaceVariables(self, interface):
514 #print "private:"
José Fonseca7aa86902012-01-31 20:14:31 +0000515 print " DWORD m_dwMagic;"
José Fonseca0423d2c2012-01-20 19:16:17 +0000516 print " %s * m_pInstance;" % (interface.name,)
517
518 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100519 self.interface = interface
520
José Fonseca0423d2c2012-01-20 19:16:17 +0000521 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonseca7aa86902012-01-31 20:14:31 +0000522 print ' m_dwMagic = 0xd8365d6c;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000523 print ' m_pInstance = pInstance;'
524 print '}'
525 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000526 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000527 print '}'
528 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100529
José Fonseca4220b1b2012-02-03 19:05:29 +0000530 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100531 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000532 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100533
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000534 print
535
José Fonseca4220b1b2012-02-03 19:05:29 +0000536 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000537 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
538 if method.type is not stdapi.Void:
539 print ' %s __result;' % method.type
540
José Fonseca4220b1b2012-02-03 19:05:29 +0000541 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000542
543 if method.type is not stdapi.Void:
544 print ' return __result;'
545 print '}'
546 print
547
José Fonseca4220b1b2012-02-03 19:05:29 +0000548 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca87d1cc62010-11-29 15:57:25 +0000549 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 +0100550 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
551 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
552 print ' trace::localWriter.beginArg(0);'
553 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
554 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000555 for arg in method.args:
556 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000557 self.unwrapArg(method, arg)
558 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100559 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000560
José Fonseca4220b1b2012-02-03 19:05:29 +0000561 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000562
José Fonsecab4a3d142011-10-27 07:43:19 +0100563 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000564 for arg in method.args:
565 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000566 self.serializeArg(method, arg)
567 self.wrapArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000568
José Fonseca87d1cc62010-11-29 15:57:25 +0000569 if method.type is not stdapi.Void:
José Fonsecab4a3d142011-10-27 07:43:19 +0100570 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000571 self.serializeValue(method.type, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100572 print ' trace::localWriter.endReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000573 self.wrapValue(method.type, '__result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100574 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000575 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000576 assert method.type is not stdapi.Void
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000577 print ' if (!__result)'
578 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000579
José Fonsecabcb26b22012-04-15 08:42:25 +0100580 def wrapIid(self, function, riid, out):
581 print r' if (%s && *%s) {' % (out.name, out.name)
582 function_name = function.name
583 else_ = ''
584 if self.interface is not None:
585 function_name = self.interface.name + '::' + function_name
586 print r' %sif (*%s == m_pInstance) {' % (else_, out.name,)
587 print r' *%s = this;' % (out.name,)
José Fonseca1ce52f02012-01-31 12:19:57 +0000588 print r' }'
José Fonsecabcb26b22012-04-15 08:42:25 +0100589 else_ = 'else '
590 for iface in self.api.getAllInterfaces():
591 print r' %sif (%s == IID_%s) {' % (else_, riid.name, iface.name)
592 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
593 print r' }'
594 else_ = 'else '
595 print r' %s{' % else_
596 print r' os::log("apitrace: warning: %s: unknown IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
597 print r' "%s",' % (function_name)
598 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
599 print r' %s.Data4[0],' % (riid.name,)
600 print r' %s.Data4[1],' % (riid.name,)
601 print r' %s.Data4[2],' % (riid.name,)
602 print r' %s.Data4[3],' % (riid.name,)
603 print r' %s.Data4[4],' % (riid.name,)
604 print r' %s.Data4[5],' % (riid.name,)
605 print r' %s.Data4[6],' % (riid.name,)
606 print r' %s.Data4[7]);' % (riid.name,)
607 print r' }'
608 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000609
José Fonseca4220b1b2012-02-03 19:05:29 +0000610 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000611 if method.type is stdapi.Void:
612 result = ''
613 else:
614 result = '__result = '
José Fonseca4220b1b2012-02-03 19:05:29 +0000615 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 +0000616
617 def emit_memcpy(self, dest, src, length):
618 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
619 print ' trace::localWriter.beginArg(0);'
620 print ' trace::localWriter.writeOpaque(%s);' % dest
621 print ' trace::localWriter.endArg();'
622 print ' trace::localWriter.beginArg(1);'
623 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
624 print ' trace::localWriter.endArg();'
625 print ' trace::localWriter.beginArg(2);'
626 print ' trace::localWriter.writeUInt(%s);' % length
627 print ' trace::localWriter.endArg();'
628 print ' trace::localWriter.endEnter();'
629 print ' trace::localWriter.beginLeave(__call);'
630 print ' trace::localWriter.endLeave();'
631