blob: e2e11ec36c07433329fc2e69e1f8c15c94efcb33 [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é Fonseca54f304a2012-01-14 19:33:08 +0000248class ValueWrapper(stdapi.Visitor):
249 '''Type visitor which will generate the code to wrap an instance.
250
251 Wrapping is necessary mostly for interfaces, however interface pointers can
252 appear anywhere inside complex types.
253 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000254
José Fonseca54f304a2012-01-14 19:33:08 +0000255 def visitVoid(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000256 raise NotImplementedError
257
José Fonseca54f304a2012-01-14 19:33:08 +0000258 def visitLiteral(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000259 pass
260
José Fonseca54f304a2012-01-14 19:33:08 +0000261 def visitString(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000262 pass
263
José Fonseca54f304a2012-01-14 19:33:08 +0000264 def visitConst(self, type, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000265 pass
266
José Fonseca54f304a2012-01-14 19:33:08 +0000267 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000268 for type, name in struct.members:
269 self.visit(type, "(%s).%s" % (instance, name))
270
José Fonseca54f304a2012-01-14 19:33:08 +0000271 def visitArray(self, array, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000272 # XXX: actually it is possible to return an array of pointers
273 pass
274
José Fonseca54f304a2012-01-14 19:33:08 +0000275 def visitBlob(self, blob, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000276 pass
277
José Fonseca54f304a2012-01-14 19:33:08 +0000278 def visitEnum(self, enum, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000279 pass
280
José Fonseca54f304a2012-01-14 19:33:08 +0000281 def visitBitmask(self, bitmask, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000282 pass
283
José Fonseca54f304a2012-01-14 19:33:08 +0000284 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100285 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000286 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100287 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000288
289 def visitIntPointer(self, pointer, instance):
290 pass
291
José Fonsecafbcf6832012-04-05 07:10:30 +0100292 def visitObjPointer(self, pointer, instance):
293 print " if (%s) {" % instance
294 self.visit(pointer.type, "*" + instance)
295 print " }"
296
José Fonseca59ee88e2012-01-15 14:24:10 +0000297 def visitLinearPointer(self, pointer, instance):
298 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000299
José Fonsecab89c5932012-04-01 22:47:11 +0200300 def visitReference(self, reference, instance):
301 self.visit(reference.type, instance)
302
José Fonseca54f304a2012-01-14 19:33:08 +0000303 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000304 self.visit(handle.type, instance)
305
José Fonseca54f304a2012-01-14 19:33:08 +0000306 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000307 self.visit(alias.type, instance)
308
José Fonseca54f304a2012-01-14 19:33:08 +0000309 def visitOpaque(self, opaque, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000310 pass
311
José Fonseca54f304a2012-01-14 19:33:08 +0000312 def visitInterface(self, interface, instance):
José Fonseca87d1cc62010-11-29 15:57:25 +0000313 assert instance.startswith('*')
314 instance = instance[1:]
José Fonseca3a2a4762011-05-26 11:37:30 +0100315 print " if (%s) {" % instance
José Fonseca0423d2c2012-01-20 19:16:17 +0000316 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100317 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100318
José Fonseca54f304a2012-01-14 19:33:08 +0000319 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100320 # XXX: There might be polymorphic values that need wrapping in the future
321 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000322
323
José Fonseca54f304a2012-01-14 19:33:08 +0000324class ValueUnwrapper(ValueWrapper):
325 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000326
José Fonseca54f304a2012-01-14 19:33:08 +0000327 def visitInterface(self, interface, instance):
José Fonseca87d1cc62010-11-29 15:57:25 +0000328 assert instance.startswith('*')
329 instance = instance[1:]
José Fonseca7aa86902012-01-31 20:14:31 +0000330 print r' if (%s) {' % instance
331 print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
332 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
333 print r' %s = pWrapper->m_pInstance;' % (instance,)
334 print r' } else {'
335 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
336 print r' }'
337 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000338
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000339
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000341 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000342
José Fonsecabb8760b2011-05-25 23:21:18 +0100343 def __init__(self):
344 self.api = None
345
José Fonseca54f304a2012-01-14 19:33:08 +0000346 def serializerFactory(self):
347 '''Create a serializer.
348
349 Can be overriden by derived classes to inject their own serialzer.
350 '''
351
352 return ValueSerializer()
353
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000354 def trace_api(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100355 self.api = api
356
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000357 self.header(api)
358
359 # Includes
360 for header in api.headers:
José Fonsecae6a50bd2010-11-24 10:12:22 +0000361 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000362 print
363
José Fonseca54f304a2012-01-14 19:33:08 +0000364 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000365 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000366 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000367 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000368 print
369
370 # Interfaces wrapers
José Fonseca2ef6d5b2012-01-31 10:56:38 +0000371 interfaces = api.getAllInterfaces()
José Fonseca0423d2c2012-01-20 19:16:17 +0000372 map(self.declareWrapperInterface, interfaces)
373 map(self.implementWrapperInterface, interfaces)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000374 print
375
376 # Function wrappers
José Fonseca54f304a2012-01-14 19:33:08 +0000377 map(self.traceFunctionDecl, api.functions)
378 map(self.traceFunctionImpl, api.functions)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000379 print
380
381 self.footer(api)
382
383 def header(self, api):
José Fonseca0ad465c2011-08-24 16:58:13 +0100384 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000385
386 def footer(self, api):
387 pass
388
José Fonseca54f304a2012-01-14 19:33:08 +0000389 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000390 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000391
José Fonseca14c21bc2011-02-20 23:32:22 +0000392 if function.args:
393 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 +0000394 else:
José Fonseca14c21bc2011-02-20 23:32:22 +0000395 print 'static const char ** __%s_args = NULL;' % (function.name,)
José Fonsecab4a3d142011-10-27 07:43:19 +0100396 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 +0000397 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000398
José Fonseca54f304a2012-01-14 19:33:08 +0000399 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100400 return True
401
José Fonseca54f304a2012-01-14 19:33:08 +0000402 def traceFunctionImpl(self, function):
403 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100404 print 'extern "C" PUBLIC'
405 else:
406 print 'extern "C" PRIVATE'
407 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000408 if function.type is not stdapi.Void:
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000409 print ' %s __result;' % function.type
José Fonseca54f304a2012-01-14 19:33:08 +0000410 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000411 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000412 self.wrapRet(function, "__result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000413 print ' return __result;'
414 print '}'
415 print
416
José Fonseca54f304a2012-01-14 19:33:08 +0000417 def traceFunctionImplBody(self, function):
José Fonsecab4a3d142011-10-27 07:43:19 +0100418 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000419 for arg in function.args:
420 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000421 self.unwrapArg(function, arg)
422 self.serializeArg(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100423 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000424 self.invokeFunction(function)
José Fonsecab4a3d142011-10-27 07:43:19 +0100425 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000426 for arg in function.args:
427 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000428 self.serializeArg(function, arg)
429 self.wrapArg(function, arg)
José Fonseca9796b842010-11-25 11:44:50 +0000430 if function.type is not stdapi.Void:
José Fonseca54f304a2012-01-14 19:33:08 +0000431 self.serializeRet(function, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100432 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000433
José Fonseca54f304a2012-01-14 19:33:08 +0000434 def invokeFunction(self, function, prefix='__', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000435 if function.type is stdapi.Void:
436 result = ''
437 else:
438 result = '__result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100439 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000440 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000441
José Fonseca54f304a2012-01-14 19:33:08 +0000442 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100443 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000444 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100445 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000446
José Fonseca54f304a2012-01-14 19:33:08 +0000447 def serializeArgValue(self, function, arg):
448 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000449
José Fonseca54f304a2012-01-14 19:33:08 +0000450 def wrapArg(self, function, arg):
451 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000452
José Fonseca54f304a2012-01-14 19:33:08 +0000453 def unwrapArg(self, function, arg):
454 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000455
José Fonseca54f304a2012-01-14 19:33:08 +0000456 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100457 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000458 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100459 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000460
José Fonseca54f304a2012-01-14 19:33:08 +0000461 def serializeValue(self, type, instance):
462 serializer = self.serializerFactory()
463 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000464
José Fonseca54f304a2012-01-14 19:33:08 +0000465 def wrapRet(self, function, instance):
466 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000467
José Fonseca54f304a2012-01-14 19:33:08 +0000468 def unwrapRet(self, function, instance):
469 self.unwrapValue(function.type, instance)
470
471 def wrapValue(self, type, instance):
472 visitor = ValueWrapper()
473 visitor.visit(type, instance)
474
475 def unwrapValue(self, type, instance):
476 visitor = ValueUnwrapper()
477 visitor.visit(type, instance)
478
José Fonseca0423d2c2012-01-20 19:16:17 +0000479 def declareWrapperInterface(self, interface):
480 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
481 print "{"
482 print "public:"
483 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
484 print " virtual ~%s();" % getWrapperInterfaceName(interface)
485 print
486 for method in interface.iterMethods():
487 print " " + method.prototype() + ";"
488 print
489 self.declareWrapperInterfaceVariables(interface)
490 print "};"
491 print
492
493 def declareWrapperInterfaceVariables(self, interface):
494 #print "private:"
José Fonseca7aa86902012-01-31 20:14:31 +0000495 print " DWORD m_dwMagic;"
José Fonseca0423d2c2012-01-20 19:16:17 +0000496 print " %s * m_pInstance;" % (interface.name,)
497
498 def implementWrapperInterface(self, interface):
499 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonseca7aa86902012-01-31 20:14:31 +0000500 print ' m_dwMagic = 0xd8365d6c;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000501 print ' m_pInstance = pInstance;'
502 print '}'
503 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000504 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000505 print '}'
506 print
José Fonseca4220b1b2012-02-03 19:05:29 +0000507 for base, method in interface.iterBaseMethods():
508 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000509 print
510
José Fonseca4220b1b2012-02-03 19:05:29 +0000511 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000512 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
513 if method.type is not stdapi.Void:
514 print ' %s __result;' % method.type
515
José Fonseca4220b1b2012-02-03 19:05:29 +0000516 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000517
518 if method.type is not stdapi.Void:
519 print ' return __result;'
520 print '}'
521 print
522
José Fonseca4220b1b2012-02-03 19:05:29 +0000523 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca87d1cc62010-11-29 15:57:25 +0000524 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 +0100525 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
526 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
527 print ' trace::localWriter.beginArg(0);'
528 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
529 print ' trace::localWriter.endArg();'
José Fonseca1ce52f02012-01-31 12:19:57 +0000530
531 from specs.winapi import REFIID
José Fonseca3d2b0652012-01-31 19:35:24 +0000532 from specs.stdapi import Pointer, Opaque, Interface
José Fonseca1ce52f02012-01-31 12:19:57 +0000533
534 riid = None
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000535 for arg in method.args:
536 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000537 self.unwrapArg(method, arg)
538 self.serializeArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000539 if arg.type is REFIID:
540 riid = arg
José Fonsecab4a3d142011-10-27 07:43:19 +0100541 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000542
José Fonseca4220b1b2012-02-03 19:05:29 +0000543 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000544
José Fonsecab4a3d142011-10-27 07:43:19 +0100545 print ' trace::localWriter.beginLeave(__call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000546 for arg in method.args:
547 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000548 self.serializeArg(method, arg)
549 self.wrapArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000550 if riid is not None and isinstance(arg.type, Pointer):
José Fonseca3d2b0652012-01-31 19:35:24 +0000551 if isinstance(arg.type.type, Opaque):
José Fonsecab6aedae2012-04-05 11:22:53 +0100552 self.wrapIid(interface, method, riid, arg)
José Fonseca3d2b0652012-01-31 19:35:24 +0000553 else:
554 assert isinstance(arg.type.type, Pointer)
555 assert isinstance(arg.type.type.type, Interface)
José Fonseca1ce52f02012-01-31 12:19:57 +0000556
José Fonseca87d1cc62010-11-29 15:57:25 +0000557 if method.type is not stdapi.Void:
José Fonsecab4a3d142011-10-27 07:43:19 +0100558 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000559 self.serializeValue(method.type, "__result")
José Fonsecab4a3d142011-10-27 07:43:19 +0100560 print ' trace::localWriter.endReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000561 self.wrapValue(method.type, '__result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100562 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000563 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000564 assert method.type is not stdapi.Void
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000565 print ' if (!__result)'
566 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000567
José Fonsecab6aedae2012-04-05 11:22:53 +0100568 def wrapIid(self, interface, method, riid, out):
José Fonseca1ce52f02012-01-31 12:19:57 +0000569 print ' if (%s && *%s) {' % (out.name, out.name)
570 print ' if (*%s == m_pInstance) {' % (out.name,)
571 print ' *%s = this;' % (out.name,)
572 print ' }'
José Fonsecaccf250c2012-02-03 19:06:31 +0000573 for iface in self.api.getAllInterfaces():
José Fonseca1ce52f02012-01-31 12:19:57 +0000574 print r' else if (%s == IID_%s) {' % (riid.name, iface.name)
575 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
576 print r' }'
577 print r' else {'
José Fonsecab6aedae2012-04-05 11:22:53 +0100578 print r' os::log("apitrace: warning: %s::%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",'
579 print r' "%s", "%s",' % (interface.name, method.name)
José Fonseca1ce52f02012-01-31 12:19:57 +0000580 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
581 print r' %s.Data4[0],' % (riid.name,)
582 print r' %s.Data4[1],' % (riid.name,)
583 print r' %s.Data4[2],' % (riid.name,)
584 print r' %s.Data4[3],' % (riid.name,)
585 print r' %s.Data4[4],' % (riid.name,)
586 print r' %s.Data4[5],' % (riid.name,)
587 print r' %s.Data4[6],' % (riid.name,)
588 print r' %s.Data4[7]);' % (riid.name,)
589 print r' }'
590 print ' }'
591
José Fonseca4220b1b2012-02-03 19:05:29 +0000592 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000593 if method.type is stdapi.Void:
594 result = ''
595 else:
596 result = '__result = '
José Fonseca4220b1b2012-02-03 19:05:29 +0000597 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 +0000598
599 def emit_memcpy(self, dest, src, length):
600 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
601 print ' trace::localWriter.beginArg(0);'
602 print ' trace::localWriter.writeOpaque(%s);' % dest
603 print ' trace::localWriter.endArg();'
604 print ' trace::localWriter.beginArg(1);'
605 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
606 print ' trace::localWriter.endArg();'
607 print ' trace::localWriter.beginArg(2);'
608 print ' trace::localWriter.writeUInt(%s);' % length
609 print ' trace::localWriter.endArg();'
610 print ' trace::localWriter.endEnter();'
611 print ' trace::localWriter.beginLeave(__call);'
612 print ' trace::localWriter.endLeave();'
613