blob: 958c07279a1bf55eab84d44d349ef6a3fded764f [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é Fonseca632a78d2012-04-19 07:18:59 +010090 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000091 for value in enum.values:
92 print ' {"%s", %s},' % (value, value)
93 print '};'
94 print
José Fonseca632a78d2012-04-19 07:18:59 +010095 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
96 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000097 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000098 print
99
José Fonseca54f304a2012-01-14 19:33:08 +0000100 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +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é Fonseca632a78d2012-04-19 07:18:59 +0100106 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
107 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é Fonsecab95e3722012-04-16 14:01:15 +0100139 if not polymorphic.contextLess:
140 return
José Fonseca06e85192011-10-16 14:15:36 +0100141 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100142 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000143 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100144 for case in cases:
145 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000146 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100147 print ' break;'
148 print ' }'
149 print '}'
150 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100151
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000152
José Fonseca54f304a2012-01-14 19:33:08 +0000153class ValueSerializer(stdapi.Visitor):
154 '''Visitor which generates code to serialize any type.
155
156 Simple types are serialized inline here, whereas the serialization of
157 complex types is dispatched to the serialization functions generated by
158 ComplexValueSerializer visitor above.
159 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000160
José Fonseca54f304a2012-01-14 19:33:08 +0000161 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100162 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000163
José Fonseca54f304a2012-01-14 19:33:08 +0000164 def visitString(self, string, instance):
José Fonseca280a1762012-01-31 15:10:13 +0000165 if string.kind == 'String':
166 cast = 'const char *'
167 elif string.kind == 'WString':
168 cast = 'const wchar_t *'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000169 else:
José Fonseca280a1762012-01-31 15:10:13 +0000170 assert False
171 if cast != string.expr:
172 # reinterpret_cast is necessary for GLubyte * <=> char *
173 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
174 if string.length is not None:
175 length = ', %s' % string.length
176 else:
177 length = ''
178 print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000179
José Fonseca54f304a2012-01-14 19:33:08 +0000180 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000181 self.visit(const.type, instance)
182
José Fonseca54f304a2012-01-14 19:33:08 +0000183 def visitStruct(self, struct, instance):
José Fonseca06e85192011-10-16 14:15:36 +0100184 print ' _write__%s(%s);' % (struct.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000185
José Fonseca54f304a2012-01-14 19:33:08 +0000186 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100187 length = '_c' + array.type.tag
188 index = '_i' + array.type.tag
José Fonsecafd34e4e2011-06-03 19:34:29 +0100189 print ' if (%s) {' % instance
Carl Worth61417442012-06-04 14:47:33 -0700190 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array.length, array.length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100191 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100192 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100193 print ' trace::localWriter.beginElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000194 self.visit(array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100195 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000196 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100197 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100198 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100199 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100200 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000201
José Fonseca54f304a2012-01-14 19:33:08 +0000202 def visitBlob(self, blob, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100203 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000204
José Fonseca54f304a2012-01-14 19:33:08 +0000205 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100206 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000207
José Fonseca54f304a2012-01-14 19:33:08 +0000208 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100209 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000210
José Fonseca54f304a2012-01-14 19:33:08 +0000211 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100212 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100213 print ' trace::localWriter.beginArray(1);'
214 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000215 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100216 print ' trace::localWriter.endElement();'
217 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100218 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100219 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100220 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000221
José Fonseca59ee88e2012-01-15 14:24:10 +0000222 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100223 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000224
José Fonsecafbcf6832012-04-05 07:10:30 +0100225 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100226 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100227
José Fonseca59ee88e2012-01-15 14:24:10 +0000228 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100229 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000230
José Fonsecab89c5932012-04-01 22:47:11 +0200231 def visitReference(self, reference, instance):
232 self.visit(reference.type, instance)
233
José Fonseca54f304a2012-01-14 19:33:08 +0000234 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000235 self.visit(handle.type, instance)
236
José Fonseca54f304a2012-01-14 19:33:08 +0000237 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000238 self.visit(alias.type, instance)
239
José Fonseca54f304a2012-01-14 19:33:08 +0000240 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100241 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000242
José Fonseca54f304a2012-01-14 19:33:08 +0000243 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100244 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000245
José Fonseca54f304a2012-01-14 19:33:08 +0000246 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100247 if polymorphic.contextLess:
248 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
249 else:
250 print ' switch (%s) {' % polymorphic.switchExpr
251 for cases, type in polymorphic.iterSwitch():
252 for case in cases:
253 print ' %s:' % case
254 self.visit(type, 'static_cast<%s>(%s)' % (type, instance))
255 print ' break;'
256 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100257
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000258
José Fonseca0075f152012-04-14 20:25:52 +0100259class WrapDecider(stdapi.Traverser):
260 '''Type visitor which will decide wheter this type will need wrapping or not.
261
262 For complex types (arrays, structures), we need to know this before hand.
263 '''
264
265 def __init__(self):
266 self.needsWrapping = False
267
José Fonseca0075f152012-04-14 20:25:52 +0100268 def visitLinearPointer(self, void):
269 pass
270
271 def visitInterface(self, interface):
272 self.needsWrapping = True
273
274
275class ValueWrapper(stdapi.Traverser):
José Fonseca54f304a2012-01-14 19:33:08 +0000276 '''Type visitor which will generate the code to wrap an instance.
277
278 Wrapping is necessary mostly for interfaces, however interface pointers can
279 appear anywhere inside complex types.
280 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000281
José Fonseca54f304a2012-01-14 19:33:08 +0000282 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000283 for type, name in struct.members:
284 self.visit(type, "(%s).%s" % (instance, name))
285
José Fonseca54f304a2012-01-14 19:33:08 +0000286 def visitArray(self, array, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100287 print " if (%s) {" % instance
288 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
289 self.visit(array.type, instance + "[_i]")
290 print " }"
291 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000292
José Fonseca54f304a2012-01-14 19:33:08 +0000293 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100294 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000295 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100296 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000297
José Fonsecafbcf6832012-04-05 07:10:30 +0100298 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100299 elem_type = pointer.type.mutable()
300 if isinstance(elem_type, stdapi.Interface):
301 self.visitInterfacePointer(elem_type, instance)
302 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100303 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100304
José Fonseca54f304a2012-01-14 19:33:08 +0000305 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100306 raise NotImplementedError
307
308 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100309 print " if (%s) {" % instance
José Fonseca0423d2c2012-01-20 19:16:17 +0000310 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100311 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100312
José Fonseca54f304a2012-01-14 19:33:08 +0000313 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100314 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100315 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000316
317
José Fonseca54f304a2012-01-14 19:33:08 +0000318class ValueUnwrapper(ValueWrapper):
319 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000320
José Fonseca0075f152012-04-14 20:25:52 +0100321 allocated = False
322
323 def visitArray(self, array, instance):
324 if self.allocated or isinstance(instance, stdapi.Interface):
325 return ValueWrapper.visitArray(self, array, instance)
326 elem_type = array.type.mutable()
327 print " if (%s && %s) {" % (instance, array.length)
328 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
329 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
330 print " _t[_i] = %s[_i];" % instance
331 self.allocated = True
332 self.visit(array.type, "_t[_i]")
333 print " }"
334 print " %s = _t;" % instance
335 print " }"
336
José Fonseca9782b292012-04-14 22:02:42 +0100337 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000338 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100339 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000340 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
341 print r' %s = pWrapper->m_pInstance;' % (instance,)
342 print r' } else {'
343 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
344 print r' }'
345 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000346
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000347
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000348class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000349 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000350
José Fonsecabb8760b2011-05-25 23:21:18 +0100351 def __init__(self):
352 self.api = None
353
José Fonseca54f304a2012-01-14 19:33:08 +0000354 def serializerFactory(self):
355 '''Create a serializer.
356
357 Can be overriden by derived classes to inject their own serialzer.
358 '''
359
360 return ValueSerializer()
361
José Fonseca1b6c8752012-04-15 14:33:00 +0100362 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100363 self.api = api
364
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000365 self.header(api)
366
367 # Includes
368 for header in api.headers:
José Fonsecae6a50bd2010-11-24 10:12:22 +0000369 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000370 print
371
José Fonseca54f304a2012-01-14 19:33:08 +0000372 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000373 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000374 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000375 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000376 print
377
378 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100379 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000380
381 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100382 self.interface = None
383 self.base = None
José Fonseca54f304a2012-01-14 19:33:08 +0000384 map(self.traceFunctionDecl, api.functions)
385 map(self.traceFunctionImpl, api.functions)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000386 print
387
388 self.footer(api)
389
390 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100391 print '#ifdef _WIN32'
392 print '# include <malloc.h> // alloca'
393 print '# ifndef alloca'
394 print '# define alloca _alloca'
395 print '# endif'
396 print '#else'
397 print '# include <alloca.h> // alloca'
398 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100399 print
400 print '#include "trace.hpp"'
401 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000402
403 def footer(self, api):
404 pass
405
José Fonseca54f304a2012-01-14 19:33:08 +0000406 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000407 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000408
José Fonseca84cea3b2012-05-09 21:12:30 +0100409 if not function.internal:
410 if function.args:
411 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
412 else:
413 print 'static const char ** _%s_args = NULL;' % (function.name,)
414 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
415 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000416
José Fonseca54f304a2012-01-14 19:33:08 +0000417 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100418 return True
419
José Fonseca54f304a2012-01-14 19:33:08 +0000420 def traceFunctionImpl(self, function):
421 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100422 print 'extern "C" PUBLIC'
423 else:
424 print 'extern "C" PRIVATE'
425 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000426 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100427 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100428
429 # No-op if tracing is disabled
430 print ' if (!trace::isTracingEnabled()) {'
Imre Deak1242ab52012-03-30 15:46:26 +0300431 Tracer.invokeFunction(self, function)
432 if function.type is not stdapi.Void:
433 print ' return _result;'
434 else:
435 print ' return;'
436 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100437
José Fonseca54f304a2012-01-14 19:33:08 +0000438 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000439 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100440 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000441 print '}'
442 print
443
José Fonseca54f304a2012-01-14 19:33:08 +0000444 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100445 if not function.internal:
446 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
447 for arg in function.args:
448 if not arg.output:
449 self.unwrapArg(function, arg)
450 self.serializeArg(function, arg)
451 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000452 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100453 if not function.internal:
454 print ' trace::localWriter.beginLeave(_call);'
455 for arg in function.args:
456 if arg.output:
457 self.serializeArg(function, arg)
458 self.wrapArg(function, arg)
459 if function.type is not stdapi.Void:
460 self.serializeRet(function, "_result")
461 print ' trace::localWriter.endLeave();'
462 if function.type is not stdapi.Void:
463 self.wrapRet(function, "_result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000464
José Fonseca632a78d2012-04-19 07:18:59 +0100465 def invokeFunction(self, function, prefix='_', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000466 if function.type is stdapi.Void:
467 result = ''
468 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100469 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100470 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000471 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000472
José Fonseca54f304a2012-01-14 19:33:08 +0000473 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100474 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000475 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100476 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000477
José Fonseca54f304a2012-01-14 19:33:08 +0000478 def serializeArgValue(self, function, arg):
479 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000480
José Fonseca54f304a2012-01-14 19:33:08 +0000481 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100482 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100483
484 from specs.winapi import REFIID
485 riid = None
486 for other_arg in function.args:
487 if not other_arg.output and other_arg.type is REFIID:
488 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100489 if riid is not None \
490 and isinstance(arg.type, stdapi.Pointer) \
491 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100492 self.wrapIid(function, riid, arg)
493 return
494
José Fonseca54f304a2012-01-14 19:33:08 +0000495 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000496
José Fonseca54f304a2012-01-14 19:33:08 +0000497 def unwrapArg(self, function, arg):
498 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000499
José Fonseca54f304a2012-01-14 19:33:08 +0000500 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100501 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000502 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100503 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000504
José Fonseca54f304a2012-01-14 19:33:08 +0000505 def serializeValue(self, type, instance):
506 serializer = self.serializerFactory()
507 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000508
José Fonseca54f304a2012-01-14 19:33:08 +0000509 def wrapRet(self, function, instance):
510 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000511
José Fonseca54f304a2012-01-14 19:33:08 +0000512 def unwrapRet(self, function, instance):
513 self.unwrapValue(function.type, instance)
514
José Fonseca0075f152012-04-14 20:25:52 +0100515 def needsWrapping(self, type):
516 visitor = WrapDecider()
517 visitor.visit(type)
518 return visitor.needsWrapping
519
José Fonseca54f304a2012-01-14 19:33:08 +0000520 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100521 if self.needsWrapping(type):
522 visitor = ValueWrapper()
523 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000524
525 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100526 if self.needsWrapping(type):
527 visitor = ValueUnwrapper()
528 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000529
José Fonseca143e9252012-04-15 09:31:18 +0100530 def traceInterfaces(self, api):
531 interfaces = api.getAllInterfaces()
532 if not interfaces:
533 return
534 map(self.declareWrapperInterface, interfaces)
535 self.implementIidWrapper(api)
536 map(self.implementWrapperInterface, interfaces)
537 print
538
José Fonseca0423d2c2012-01-20 19:16:17 +0000539 def declareWrapperInterface(self, interface):
540 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
541 print "{"
542 print "public:"
543 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
544 print " virtual ~%s();" % getWrapperInterfaceName(interface)
545 print
546 for method in interface.iterMethods():
547 print " " + method.prototype() + ";"
548 print
José Fonsecaacc90622012-05-02 13:10:07 +0100549 #print "private:"
550 for type, name, value in self.enumWrapperInterfaceVariables(interface):
551 print ' %s %s;' % (type, name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000552 print "};"
553 print
554
José Fonsecaacc90622012-05-02 13:10:07 +0100555 def enumWrapperInterfaceVariables(self, interface):
556 return [
557 ("DWORD", "m_dwMagic", "0xd8365d6c"),
558 ("%s *" % interface.name, "m_pInstance", "pInstance"),
559 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000560
561 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100562 self.interface = interface
563
José Fonseca0423d2c2012-01-20 19:16:17 +0000564 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100565 for type, name, value in self.enumWrapperInterfaceVariables(interface):
566 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000567 print '}'
568 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000569 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000570 print '}'
571 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100572
José Fonseca4220b1b2012-02-03 19:05:29 +0000573 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100574 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000575 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100576
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000577 print
578
José Fonseca4220b1b2012-02-03 19:05:29 +0000579 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000580 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
581 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100582 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000583
José Fonseca4220b1b2012-02-03 19:05:29 +0000584 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000585
586 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100587 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000588 print '}'
589 print
590
José Fonseca4220b1b2012-02-03 19:05:29 +0000591 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100592 assert not method.internal
593
José Fonseca632a78d2012-04-19 07:18:59 +0100594 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
595 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
José Fonsecaa0e97862012-04-29 23:22:52 +0100596
597 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
598
José Fonseca632a78d2012-04-19 07:18:59 +0100599 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100600 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100601 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100602 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000603 for arg in method.args:
604 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000605 self.unwrapArg(method, arg)
606 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100607 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000608
José Fonseca4220b1b2012-02-03 19:05:29 +0000609 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000610
José Fonseca632a78d2012-04-19 07:18:59 +0100611 print ' trace::localWriter.beginLeave(_call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000612 for arg in method.args:
613 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000614 self.serializeArg(method, arg)
615 self.wrapArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000616
José Fonseca87d1cc62010-11-29 15:57:25 +0000617 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100618 self.serializeRet(method, '_result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100619 print ' trace::localWriter.endLeave();'
José Fonseca3a259b82012-05-09 19:33:33 +0100620 if method.type is not stdapi.Void:
621 self.wrapRet(method, '_result')
622
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000623 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000624 assert method.type is not stdapi.Void
José Fonseca632a78d2012-04-19 07:18:59 +0100625 print ' if (!_result)'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000626 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627
José Fonseca143e9252012-04-15 09:31:18 +0100628 def implementIidWrapper(self, api):
629 print r'static void'
630 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
631 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",'
632 print r' functionName, reason,'
633 print r' riid.Data1, riid.Data2, riid.Data3,'
634 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]);'
635 print r'}'
636 print
637 print r'static void'
638 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
639 print r' if (!ppvObj || !*ppvObj) {'
640 print r' return;'
641 print r' }'
642 else_ = ''
643 for iface in api.getAllInterfaces():
644 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
645 print r' *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
646 print r' }'
647 else_ = 'else '
648 print r' %s{' % else_
649 print r' warnIID(functionName, riid, "unknown");'
650 print r' }'
651 print r'}'
652 print
653
José Fonsecabcb26b22012-04-15 08:42:25 +0100654 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100655 # Cast output arg to `void **` if necessary
656 out_name = out.name
657 obj_type = out.type.type.type
658 if not obj_type is stdapi.Void:
659 assert isinstance(obj_type, stdapi.Interface)
660 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
661
José Fonsecabcb26b22012-04-15 08:42:25 +0100662 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100663 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100664 else_ = ''
665 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100666 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100667 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100668 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100669 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100670 print r' }'
671 else_ = 'else '
672 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100673 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100674 print r' }'
675 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000676
José Fonseca4220b1b2012-02-03 19:05:29 +0000677 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000678 if method.type is stdapi.Void:
679 result = ''
680 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100681 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100682 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000683
684 def emit_memcpy(self, dest, src, length):
José Fonseca632a78d2012-04-19 07:18:59 +0100685 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000686 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100687 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000688 print ' trace::localWriter.endArg();'
689 print ' trace::localWriter.beginArg(1);'
690 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
691 print ' trace::localWriter.endArg();'
692 print ' trace::localWriter.beginArg(2);'
693 print ' trace::localWriter.writeUInt(%s);' % length
694 print ' trace::localWriter.endArg();'
695 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100696 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000697 print ' trace::localWriter.endLeave();'
698