blob: 30825617ceca523567d69cbc876f8fa0d3a294ef [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é Fonseca30fb4c32012-11-04 11:07:45 +000066 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000067 for type, name, in struct.members:
José Fonseca30fb4c32012-11-04 11:07:45 +000068 print ' "%s",' % (name,)
69 print '};'
70 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
71 print ' %u, "%s", %u, _struct%s_members' % (struct.id, struct.name, len(struct.members), struct.tag)
72 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000073 print
74
José Fonseca54f304a2012-01-14 19:33:08 +000075 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000076 self.visit(array.type)
77
José Fonseca54f304a2012-01-14 19:33:08 +000078 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000079 pass
80
José Fonseca54f304a2012-01-14 19:33:08 +000081 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010082 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000083 for value in enum.values:
84 print ' {"%s", %s},' % (value, value)
85 print '};'
86 print
José Fonseca632a78d2012-04-19 07:18:59 +010087 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
88 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000089 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000090 print
91
José Fonseca54f304a2012-01-14 19:33:08 +000092 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +010093 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +000094 for value in bitmask.values:
José Fonsecad35973c2010-11-26 14:14:45 +000095 print ' {"%s", %s},' % (value, value)
96 print '};'
97 print
José Fonseca632a78d2012-04-19 07:18:59 +010098 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
99 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000100 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000101 print
102
José Fonseca54f304a2012-01-14 19:33:08 +0000103 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000104 self.visit(pointer.type)
105
José Fonseca59ee88e2012-01-15 14:24:10 +0000106 def visitIntPointer(self, pointer):
107 pass
108
José Fonsecafbcf6832012-04-05 07:10:30 +0100109 def visitObjPointer(self, pointer):
110 self.visit(pointer.type)
111
José Fonseca59ee88e2012-01-15 14:24:10 +0000112 def visitLinearPointer(self, pointer):
113 self.visit(pointer.type)
114
José Fonseca54f304a2012-01-14 19:33:08 +0000115 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000116 self.visit(handle.type)
117
José Fonsecab89c5932012-04-01 22:47:11 +0200118 def visitReference(self, reference):
119 self.visit(reference.type)
120
José Fonseca54f304a2012-01-14 19:33:08 +0000121 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000122 self.visit(alias.type)
123
José Fonseca54f304a2012-01-14 19:33:08 +0000124 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000125 pass
126
José Fonseca54f304a2012-01-14 19:33:08 +0000127 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000128 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000129
José Fonseca54f304a2012-01-14 19:33:08 +0000130 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100131 if not polymorphic.contextLess:
132 return
José Fonseca06e85192011-10-16 14:15:36 +0100133 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100134 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000135 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100136 for case in cases:
137 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000138 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100139 print ' break;'
140 print ' }'
141 print '}'
142 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100143
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000144
José Fonseca54f304a2012-01-14 19:33:08 +0000145class ValueSerializer(stdapi.Visitor):
146 '''Visitor which generates code to serialize any type.
147
148 Simple types are serialized inline here, whereas the serialization of
149 complex types is dispatched to the serialization functions generated by
150 ComplexValueSerializer visitor above.
151 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000152
José Fonseca30fb4c32012-11-04 11:07:45 +0000153 def __init__(self):
154 #stdapi.Visitor.__init__(self)
155 self.indices = []
156 self.instances = []
157
158 def expand(self, expr):
159 # Expand a C expression, replacing certain variables
160 variables = {}
161 try:
162 variables['self'] = self.instances[-1]
163 except IndexError:
164 pass
165 try:
166 variables['i'] = self.indices[-1]
167 except IndexError:
168 pass
169 expandedExpr = expr.format(**variables)
170 if expandedExpr != expr:
171 sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr))
172 return expandedExpr
173
José Fonseca54f304a2012-01-14 19:33:08 +0000174 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100175 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000176
José Fonseca54f304a2012-01-14 19:33:08 +0000177 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100178 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000179 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100180 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000181 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100182 cast = 'const wchar_t *'
183 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000184 if cast != string.expr:
185 # reinterpret_cast is necessary for GLubyte * <=> char *
186 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
187 if string.length is not None:
188 length = ', %s' % string.length
189 else:
190 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100191 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000192
José Fonseca54f304a2012-01-14 19:33:08 +0000193 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000194 self.visit(const.type, instance)
195
José Fonseca54f304a2012-01-14 19:33:08 +0000196 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000197 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
198 self.instances.append(instance)
199 try:
200 for type, name in struct.members:
201 self.visit(type, '(%s).%s' % (instance, name,))
202 finally:
203 self.instances.pop()
204 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000205
José Fonseca54f304a2012-01-14 19:33:08 +0000206 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100207 length = '_c' + array.type.tag
208 index = '_i' + array.type.tag
José Fonsecafd34e4e2011-06-03 19:34:29 +0100209 print ' if (%s) {' % instance
Carl Worth61417442012-06-04 14:47:33 -0700210 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array.length, array.length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100211 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100212 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100213 print ' trace::localWriter.beginElement();'
José Fonseca30fb4c32012-11-04 11:07:45 +0000214 self.indices.append(index)
215 try:
216 self.visit(array.type, '(%s)[%s]' % (instance, index))
217 finally:
218 self.indices.pop()
José Fonsecab4a3d142011-10-27 07:43:19 +0100219 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000220 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100221 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100222 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100223 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100224 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000225
José Fonseca54f304a2012-01-14 19:33:08 +0000226 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000227 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000228
José Fonseca54f304a2012-01-14 19:33:08 +0000229 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100230 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000231
José Fonseca54f304a2012-01-14 19:33:08 +0000232 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100233 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000234
José Fonseca54f304a2012-01-14 19:33:08 +0000235 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100236 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100237 print ' trace::localWriter.beginArray(1);'
238 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000239 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100240 print ' trace::localWriter.endElement();'
241 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100242 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100243 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100244 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000245
José Fonseca59ee88e2012-01-15 14:24:10 +0000246 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100247 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000248
José Fonsecafbcf6832012-04-05 07:10:30 +0100249 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100250 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100251
José Fonseca59ee88e2012-01-15 14:24:10 +0000252 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100253 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000254
José Fonsecab89c5932012-04-01 22:47:11 +0200255 def visitReference(self, reference, instance):
256 self.visit(reference.type, instance)
257
José Fonseca54f304a2012-01-14 19:33:08 +0000258 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000259 self.visit(handle.type, instance)
260
José Fonseca54f304a2012-01-14 19:33:08 +0000261 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000262 self.visit(alias.type, instance)
263
José Fonseca54f304a2012-01-14 19:33:08 +0000264 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100265 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000266
José Fonseca54f304a2012-01-14 19:33:08 +0000267 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100268 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000269
José Fonseca54f304a2012-01-14 19:33:08 +0000270 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100271 if polymorphic.contextLess:
272 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
273 else:
274 print ' switch (%s) {' % polymorphic.switchExpr
275 for cases, type in polymorphic.iterSwitch():
276 for case in cases:
277 print ' %s:' % case
278 self.visit(type, 'static_cast<%s>(%s)' % (type, instance))
279 print ' break;'
280 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100281
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000282
José Fonseca0075f152012-04-14 20:25:52 +0100283class WrapDecider(stdapi.Traverser):
284 '''Type visitor which will decide wheter this type will need wrapping or not.
285
286 For complex types (arrays, structures), we need to know this before hand.
287 '''
288
289 def __init__(self):
290 self.needsWrapping = False
291
José Fonseca0075f152012-04-14 20:25:52 +0100292 def visitLinearPointer(self, void):
293 pass
294
295 def visitInterface(self, interface):
296 self.needsWrapping = True
297
298
299class ValueWrapper(stdapi.Traverser):
José Fonseca54f304a2012-01-14 19:33:08 +0000300 '''Type visitor which will generate the code to wrap an instance.
301
302 Wrapping is necessary mostly for interfaces, however interface pointers can
303 appear anywhere inside complex types.
304 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000305
José Fonseca54f304a2012-01-14 19:33:08 +0000306 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000307 for type, name in struct.members:
308 self.visit(type, "(%s).%s" % (instance, name))
309
José Fonseca54f304a2012-01-14 19:33:08 +0000310 def visitArray(self, array, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100311 print " if (%s) {" % instance
312 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
313 self.visit(array.type, instance + "[_i]")
314 print " }"
315 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000316
José Fonseca54f304a2012-01-14 19:33:08 +0000317 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100318 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000319 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100320 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000321
José Fonsecafbcf6832012-04-05 07:10:30 +0100322 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100323 elem_type = pointer.type.mutable()
324 if isinstance(elem_type, stdapi.Interface):
325 self.visitInterfacePointer(elem_type, instance)
326 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100327 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100328
José Fonseca54f304a2012-01-14 19:33:08 +0000329 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100330 raise NotImplementedError
331
332 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100333 print " if (%s) {" % instance
José Fonseca0423d2c2012-01-20 19:16:17 +0000334 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100335 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100336
José Fonseca54f304a2012-01-14 19:33:08 +0000337 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100338 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100339 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340
341
José Fonseca54f304a2012-01-14 19:33:08 +0000342class ValueUnwrapper(ValueWrapper):
343 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000344
José Fonseca0075f152012-04-14 20:25:52 +0100345 allocated = False
346
347 def visitArray(self, array, instance):
348 if self.allocated or isinstance(instance, stdapi.Interface):
349 return ValueWrapper.visitArray(self, array, instance)
350 elem_type = array.type.mutable()
351 print " if (%s && %s) {" % (instance, array.length)
352 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
353 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
354 print " _t[_i] = %s[_i];" % instance
355 self.allocated = True
356 self.visit(array.type, "_t[_i]")
357 print " }"
358 print " %s = _t;" % instance
359 print " }"
360
José Fonseca9782b292012-04-14 22:02:42 +0100361 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000362 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100363 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000364 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
365 print r' %s = pWrapper->m_pInstance;' % (instance,)
366 print r' } else {'
367 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
368 print r' }'
369 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000370
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000371
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000372class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000373 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000374
José Fonsecabb8760b2011-05-25 23:21:18 +0100375 def __init__(self):
376 self.api = None
377
José Fonseca54f304a2012-01-14 19:33:08 +0000378 def serializerFactory(self):
379 '''Create a serializer.
380
381 Can be overriden by derived classes to inject their own serialzer.
382 '''
383
384 return ValueSerializer()
385
José Fonseca1b6c8752012-04-15 14:33:00 +0100386 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100387 self.api = api
388
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000389 self.header(api)
390
391 # Includes
392 for header in api.headers:
José Fonsecae6a50bd2010-11-24 10:12:22 +0000393 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000394 print
395
José Fonseca54f304a2012-01-14 19:33:08 +0000396 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000397 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000398 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000399 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000400 print
401
402 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100403 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000404
405 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100406 self.interface = None
407 self.base = None
José Fonseca54f304a2012-01-14 19:33:08 +0000408 map(self.traceFunctionDecl, api.functions)
409 map(self.traceFunctionImpl, api.functions)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000410 print
411
412 self.footer(api)
413
414 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100415 print '#ifdef _WIN32'
416 print '# include <malloc.h> // alloca'
417 print '# ifndef alloca'
418 print '# define alloca _alloca'
419 print '# endif'
420 print '#else'
421 print '# include <alloca.h> // alloca'
422 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100423 print
424 print '#include "trace.hpp"'
425 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000426
427 def footer(self, api):
428 pass
429
José Fonseca54f304a2012-01-14 19:33:08 +0000430 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000431 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000432
José Fonseca84cea3b2012-05-09 21:12:30 +0100433 if not function.internal:
434 if function.args:
435 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
436 else:
437 print 'static const char ** _%s_args = NULL;' % (function.name,)
438 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
439 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000440
José Fonseca54f304a2012-01-14 19:33:08 +0000441 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100442 return True
443
José Fonseca54f304a2012-01-14 19:33:08 +0000444 def traceFunctionImpl(self, function):
445 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100446 print 'extern "C" PUBLIC'
447 else:
448 print 'extern "C" PRIVATE'
449 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000450 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100451 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100452
453 # No-op if tracing is disabled
454 print ' if (!trace::isTracingEnabled()) {'
Imre Deak1242ab52012-03-30 15:46:26 +0300455 Tracer.invokeFunction(self, function)
456 if function.type is not stdapi.Void:
457 print ' return _result;'
458 else:
459 print ' return;'
460 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100461
José Fonseca54f304a2012-01-14 19:33:08 +0000462 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000463 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100464 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000465 print '}'
466 print
467
José Fonseca54f304a2012-01-14 19:33:08 +0000468 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100469 if not function.internal:
470 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
471 for arg in function.args:
472 if not arg.output:
473 self.unwrapArg(function, arg)
474 self.serializeArg(function, arg)
475 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000476 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100477 if not function.internal:
478 print ' trace::localWriter.beginLeave(_call);'
479 for arg in function.args:
480 if arg.output:
481 self.serializeArg(function, arg)
482 self.wrapArg(function, arg)
483 if function.type is not stdapi.Void:
484 self.serializeRet(function, "_result")
485 print ' trace::localWriter.endLeave();'
486 if function.type is not stdapi.Void:
487 self.wrapRet(function, "_result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000488
José Fonseca632a78d2012-04-19 07:18:59 +0100489 def invokeFunction(self, function, prefix='_', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000490 if function.type is stdapi.Void:
491 result = ''
492 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100493 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100494 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000495 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000496
José Fonseca54f304a2012-01-14 19:33:08 +0000497 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100498 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000499 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100500 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000501
José Fonseca54f304a2012-01-14 19:33:08 +0000502 def serializeArgValue(self, function, arg):
503 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000504
José Fonseca54f304a2012-01-14 19:33:08 +0000505 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100506 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100507
508 from specs.winapi import REFIID
509 riid = None
510 for other_arg in function.args:
511 if not other_arg.output and other_arg.type is REFIID:
512 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100513 if riid is not None \
514 and isinstance(arg.type, stdapi.Pointer) \
515 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100516 self.wrapIid(function, riid, arg)
517 return
518
José Fonseca54f304a2012-01-14 19:33:08 +0000519 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000520
José Fonseca54f304a2012-01-14 19:33:08 +0000521 def unwrapArg(self, function, arg):
522 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000523
José Fonseca54f304a2012-01-14 19:33:08 +0000524 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100525 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000526 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100527 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000528
José Fonseca54f304a2012-01-14 19:33:08 +0000529 def serializeValue(self, type, instance):
530 serializer = self.serializerFactory()
531 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000532
José Fonseca54f304a2012-01-14 19:33:08 +0000533 def wrapRet(self, function, instance):
534 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000535
José Fonseca54f304a2012-01-14 19:33:08 +0000536 def unwrapRet(self, function, instance):
537 self.unwrapValue(function.type, instance)
538
José Fonseca0075f152012-04-14 20:25:52 +0100539 def needsWrapping(self, type):
540 visitor = WrapDecider()
541 visitor.visit(type)
542 return visitor.needsWrapping
543
José Fonseca54f304a2012-01-14 19:33:08 +0000544 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100545 if self.needsWrapping(type):
546 visitor = ValueWrapper()
547 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000548
549 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100550 if self.needsWrapping(type):
551 visitor = ValueUnwrapper()
552 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000553
José Fonseca143e9252012-04-15 09:31:18 +0100554 def traceInterfaces(self, api):
555 interfaces = api.getAllInterfaces()
556 if not interfaces:
557 return
558 map(self.declareWrapperInterface, interfaces)
559 self.implementIidWrapper(api)
560 map(self.implementWrapperInterface, interfaces)
561 print
562
José Fonseca0423d2c2012-01-20 19:16:17 +0000563 def declareWrapperInterface(self, interface):
564 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
565 print "{"
566 print "public:"
567 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
568 print " virtual ~%s();" % getWrapperInterfaceName(interface)
569 print
570 for method in interface.iterMethods():
571 print " " + method.prototype() + ";"
572 print
José Fonsecaacc90622012-05-02 13:10:07 +0100573 #print "private:"
574 for type, name, value in self.enumWrapperInterfaceVariables(interface):
575 print ' %s %s;' % (type, name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000576 print "};"
577 print
578
José Fonsecaacc90622012-05-02 13:10:07 +0100579 def enumWrapperInterfaceVariables(self, interface):
580 return [
581 ("DWORD", "m_dwMagic", "0xd8365d6c"),
582 ("%s *" % interface.name, "m_pInstance", "pInstance"),
583 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000584
585 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100586 self.interface = interface
587
José Fonseca0423d2c2012-01-20 19:16:17 +0000588 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100589 for type, name, value in self.enumWrapperInterfaceVariables(interface):
590 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000591 print '}'
592 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000593 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000594 print '}'
595 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100596
José Fonseca4220b1b2012-02-03 19:05:29 +0000597 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100598 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000599 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100600
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000601 print
602
José Fonseca4220b1b2012-02-03 19:05:29 +0000603 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000604 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
605 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100606 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000607
José Fonseca4220b1b2012-02-03 19:05:29 +0000608 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000609
610 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100611 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000612 print '}'
613 print
614
José Fonseca4220b1b2012-02-03 19:05:29 +0000615 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100616 assert not method.internal
617
José Fonseca632a78d2012-04-19 07:18:59 +0100618 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
619 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 +0100620
621 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
622
José Fonseca632a78d2012-04-19 07:18:59 +0100623 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100624 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100625 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100626 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000627 for arg in method.args:
628 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000629 self.unwrapArg(method, arg)
630 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100631 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000632
José Fonseca4220b1b2012-02-03 19:05:29 +0000633 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000634
José Fonseca632a78d2012-04-19 07:18:59 +0100635 print ' trace::localWriter.beginLeave(_call);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000636 for arg in method.args:
637 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000638 self.serializeArg(method, arg)
639 self.wrapArg(method, arg)
José Fonseca1ce52f02012-01-31 12:19:57 +0000640
José Fonseca87d1cc62010-11-29 15:57:25 +0000641 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100642 self.serializeRet(method, '_result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100643 print ' trace::localWriter.endLeave();'
José Fonseca3a259b82012-05-09 19:33:33 +0100644 if method.type is not stdapi.Void:
645 self.wrapRet(method, '_result')
646
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000647 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000648 assert method.type is not stdapi.Void
José Fonseca632a78d2012-04-19 07:18:59 +0100649 print ' if (!_result)'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000650 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000651
José Fonseca143e9252012-04-15 09:31:18 +0100652 def implementIidWrapper(self, api):
653 print r'static void'
654 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
655 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",'
656 print r' functionName, reason,'
657 print r' riid.Data1, riid.Data2, riid.Data3,'
658 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]);'
659 print r'}'
660 print
661 print r'static void'
662 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
663 print r' if (!ppvObj || !*ppvObj) {'
664 print r' return;'
665 print r' }'
666 else_ = ''
667 for iface in api.getAllInterfaces():
668 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
669 print r' *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
670 print r' }'
671 else_ = 'else '
672 print r' %s{' % else_
673 print r' warnIID(functionName, riid, "unknown");'
674 print r' }'
675 print r'}'
676 print
677
José Fonsecabcb26b22012-04-15 08:42:25 +0100678 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100679 # Cast output arg to `void **` if necessary
680 out_name = out.name
681 obj_type = out.type.type.type
682 if not obj_type is stdapi.Void:
683 assert isinstance(obj_type, stdapi.Interface)
684 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
685
José Fonsecabcb26b22012-04-15 08:42:25 +0100686 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100687 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100688 else_ = ''
689 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100690 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100691 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100692 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100693 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100694 print r' }'
695 else_ = 'else '
696 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100697 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100698 print r' }'
699 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000700
José Fonseca4220b1b2012-02-03 19:05:29 +0000701 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000702 if method.type is stdapi.Void:
703 result = ''
704 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100705 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100706 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000707
708 def emit_memcpy(self, dest, src, length):
José Fonseca632a78d2012-04-19 07:18:59 +0100709 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000710 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100711 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000712 print ' trace::localWriter.endArg();'
713 print ' trace::localWriter.beginArg(1);'
714 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
715 print ' trace::localWriter.endArg();'
716 print ' trace::localWriter.beginArg(2);'
717 print ' trace::localWriter.writeUInt(%s);' % length
718 print ' trace::localWriter.endArg();'
719 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100720 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000721 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100722
723 def fake_call(self, function, args):
724 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
725 for arg, instance in zip(function.args, args):
726 assert not arg.output
727 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
728 self.serializeValue(arg.type, instance)
729 print ' trace::localWriter.endArg();'
730 print ' trace::localWriter.endEnter();'
731 print ' trace::localWriter.beginLeave(_fake_call);'
732 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000733