blob: 34f4c6930bce7717f60f4ee45aa12f24eafb96ab [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é Fonsecaf6b05132012-11-06 00:16:28 +000042
43class ExpanderMixin:
44 '''Mixin class that provides a bunch of methods to expand C expressions
45 from the specifications.'''
46
47 __structs = None
48 __indices = None
49
50 def expand(self, expr):
51 # Expand a C expression, replacing certain variables
52 if not isinstance(expr, basestring):
53 return expr
54 variables = {}
55
56 if self.__structs is not None:
57 variables['self'] = '(%s)' % self.__structs[0]
58 if self.__indices is not None:
59 variables['i'] = self.__indices[0]
60
61 expandedExpr = expr.format(**variables)
62 if expandedExpr != expr and 0:
63 sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr))
64 return expandedExpr
65
66 def visitMember(self, structInstance, member_type, *args, **kwargs):
67 self.__structs = (structInstance, self.__structs)
68 try:
69 return self.visit(member_type, *args, **kwargs)
70 finally:
71 _, self.__structs = self.__structs
72
73 def visitElement(self, element_index, element_type, *args, **kwargs):
74 self.__indices = (element_index, self.__indices)
75 try:
76 return self.visit(element_type, *args, **kwargs)
77 finally:
78 _, self.__indices = self.__indices
79
80
José Fonseca54f304a2012-01-14 19:33:08 +000081class ComplexValueSerializer(stdapi.OnceVisitor):
82 '''Type visitors which generates serialization functions for
83 complex types.
84
85 Simple types are serialized inline.
86 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000087
José Fonseca54f304a2012-01-14 19:33:08 +000088 def __init__(self, serializer):
89 stdapi.OnceVisitor.__init__(self)
90 self.serializer = serializer
91
92 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000093 pass
94
José Fonseca54f304a2012-01-14 19:33:08 +000095 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000096 pass
97
José Fonseca54f304a2012-01-14 19:33:08 +000098 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000099 pass
100
José Fonseca54f304a2012-01-14 19:33:08 +0000101 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000102 self.visit(const.type)
103
José Fonseca54f304a2012-01-14 19:33:08 +0000104 def visitStruct(self, struct):
José Fonseca30fb4c32012-11-04 11:07:45 +0000105 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +0000106 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +0000107 if name is None:
108 print ' "",'
109 else:
110 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +0000111 print '};'
112 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +0000113 if struct.name is None:
114 structName = '""'
115 else:
116 structName = '"%s"' % struct.name
117 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +0000118 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000119 print
120
José Fonseca54f304a2012-01-14 19:33:08 +0000121 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000122 self.visit(array.type)
123
José Fonseca54f304a2012-01-14 19:33:08 +0000124 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000125 pass
126
José Fonseca54f304a2012-01-14 19:33:08 +0000127 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +0100128 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000129 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000130 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +0000131 print '};'
132 print
José Fonseca632a78d2012-04-19 07:18:59 +0100133 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000134 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +0000135 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000136 print
137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100139 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000140 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000141 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000142 print '};'
143 print
José Fonseca632a78d2012-04-19 07:18:59 +0100144 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000145 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000146 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000147 print
148
José Fonseca54f304a2012-01-14 19:33:08 +0000149 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000150 self.visit(pointer.type)
151
José Fonseca59ee88e2012-01-15 14:24:10 +0000152 def visitIntPointer(self, pointer):
153 pass
154
José Fonsecafbcf6832012-04-05 07:10:30 +0100155 def visitObjPointer(self, pointer):
156 self.visit(pointer.type)
157
José Fonseca59ee88e2012-01-15 14:24:10 +0000158 def visitLinearPointer(self, pointer):
159 self.visit(pointer.type)
160
José Fonseca54f304a2012-01-14 19:33:08 +0000161 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000162 self.visit(handle.type)
163
José Fonsecab89c5932012-04-01 22:47:11 +0200164 def visitReference(self, reference):
165 self.visit(reference.type)
166
José Fonseca54f304a2012-01-14 19:33:08 +0000167 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000168 self.visit(alias.type)
169
José Fonseca54f304a2012-01-14 19:33:08 +0000170 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000171 pass
172
José Fonseca54f304a2012-01-14 19:33:08 +0000173 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000174 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000175
José Fonseca54f304a2012-01-14 19:33:08 +0000176 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100177 if not polymorphic.contextLess:
178 return
José Fonseca06e85192011-10-16 14:15:36 +0100179 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100180 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000181 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100182 for case in cases:
183 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000184 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100185 print ' break;'
186 print ' }'
187 print '}'
188 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100189
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000190
José Fonsecaf6b05132012-11-06 00:16:28 +0000191class ValueSerializer(stdapi.Visitor, ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000192 '''Visitor which generates code to serialize any type.
193
194 Simple types are serialized inline here, whereas the serialization of
195 complex types is dispatched to the serialization functions generated by
196 ComplexValueSerializer visitor above.
197 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000198
José Fonseca54f304a2012-01-14 19:33:08 +0000199 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100200 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000201
José Fonseca54f304a2012-01-14 19:33:08 +0000202 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100203 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000204 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100205 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000206 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100207 cast = 'const wchar_t *'
208 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000209 if cast != string.expr:
210 # reinterpret_cast is necessary for GLubyte * <=> char *
211 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
212 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000213 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000214 else:
215 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100216 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000217
José Fonseca54f304a2012-01-14 19:33:08 +0000218 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000219 self.visit(const.type, instance)
220
José Fonseca54f304a2012-01-14 19:33:08 +0000221 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000222 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecaf6b05132012-11-06 00:16:28 +0000223 for type, name in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +0000224 if name is None:
225 # Anonymous structure/union member
226 memberInstance = instance
227 else:
228 memberInstance = '(%s).%s' % (instance, name)
229 self.visitMember(instance, type, memberInstance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000230 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000231
José Fonseca54f304a2012-01-14 19:33:08 +0000232 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100233 length = '_c' + array.type.tag
234 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000235 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100236 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000237 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100238 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100239 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100240 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000241 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100242 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000243 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100244 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100245 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100246 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100247 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000248
José Fonseca54f304a2012-01-14 19:33:08 +0000249 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000250 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000251
José Fonseca54f304a2012-01-14 19:33:08 +0000252 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100253 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000254
José Fonseca54f304a2012-01-14 19:33:08 +0000255 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100256 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000257
José Fonseca54f304a2012-01-14 19:33:08 +0000258 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100259 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100260 print ' trace::localWriter.beginArray(1);'
261 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000262 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100263 print ' trace::localWriter.endElement();'
264 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100265 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100266 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100267 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000268
José Fonseca59ee88e2012-01-15 14:24:10 +0000269 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100270 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000271
José Fonsecafbcf6832012-04-05 07:10:30 +0100272 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100273 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100274
José Fonseca59ee88e2012-01-15 14:24:10 +0000275 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100276 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000277
José Fonsecab89c5932012-04-01 22:47:11 +0200278 def visitReference(self, reference, instance):
279 self.visit(reference.type, instance)
280
José Fonseca54f304a2012-01-14 19:33:08 +0000281 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000282 self.visit(handle.type, instance)
283
José Fonseca54f304a2012-01-14 19:33:08 +0000284 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000285 self.visit(alias.type, instance)
286
José Fonseca54f304a2012-01-14 19:33:08 +0000287 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100288 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000289
José Fonseca54f304a2012-01-14 19:33:08 +0000290 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100291 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000292
José Fonseca54f304a2012-01-14 19:33:08 +0000293 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100294 if polymorphic.contextLess:
295 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
296 else:
José Fonsecaeb216e62012-11-20 11:08:08 +0000297 print ' switch (%s) {' % self.expand(polymorphic.switchExpr)
José Fonsecab95e3722012-04-16 14:01:15 +0100298 for cases, type in polymorphic.iterSwitch():
299 for case in cases:
300 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000301 caseInstance = instance
302 if type.expr is not None:
303 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
304 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100305 print ' break;'
306 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100307
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000308
José Fonseca0075f152012-04-14 20:25:52 +0100309class WrapDecider(stdapi.Traverser):
310 '''Type visitor which will decide wheter this type will need wrapping or not.
311
312 For complex types (arrays, structures), we need to know this before hand.
313 '''
314
315 def __init__(self):
316 self.needsWrapping = False
317
José Fonseca0075f152012-04-14 20:25:52 +0100318 def visitLinearPointer(self, void):
319 pass
320
321 def visitInterface(self, interface):
322 self.needsWrapping = True
323
324
José Fonsecaf6b05132012-11-06 00:16:28 +0000325class ValueWrapper(stdapi.Traverser, ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000326 '''Type visitor which will generate the code to wrap an instance.
327
328 Wrapping is necessary mostly for interfaces, however interface pointers can
329 appear anywhere inside complex types.
330 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000331
José Fonseca54f304a2012-01-14 19:33:08 +0000332 def visitStruct(self, struct, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000333 for type, name in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +0000334 if name is None:
335 # Anonymous structure/union member
336 memberInstance = instance
337 else:
338 memberInstance = '(%s).%s' % (instance, name)
339 self.visitMember(instance, type, memberInstance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000340
José Fonseca54f304a2012-01-14 19:33:08 +0000341 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000342 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100343 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000344 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
345 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100346 print " }"
347 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000348
José Fonseca54f304a2012-01-14 19:33:08 +0000349 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100350 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000351 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100352 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000353
José Fonsecafbcf6832012-04-05 07:10:30 +0100354 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100355 elem_type = pointer.type.mutable()
356 if isinstance(elem_type, stdapi.Interface):
357 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100358 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
359 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100360 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100361 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100362
José Fonseca54f304a2012-01-14 19:33:08 +0000363 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100364 raise NotImplementedError
365
366 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100367 print " if (%s) {" % instance
José Fonseca0423d2c2012-01-20 19:16:17 +0000368 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100369 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100370
José Fonseca54f304a2012-01-14 19:33:08 +0000371 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100372 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100373 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000374
375
José Fonseca54f304a2012-01-14 19:33:08 +0000376class ValueUnwrapper(ValueWrapper):
377 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000378
José Fonseca0075f152012-04-14 20:25:52 +0100379 allocated = False
380
José Fonsecae7cb2b92012-09-28 08:40:24 +0100381 def visitStruct(self, struct, instance):
382 if not self.allocated:
383 # Argument is constant. We need to create a non const
384 print ' {'
385 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
386 print ' *_t = %s;' % (instance,)
387 assert instance.startswith('*')
388 print ' %s = _t;' % (instance[1:],)
389 instance = '*_t'
390 self.allocated = True
391 try:
392 return ValueWrapper.visitStruct(self, struct, instance)
393 finally:
394 print ' }'
395 else:
396 return ValueWrapper.visitStruct(self, struct, instance)
397
José Fonseca0075f152012-04-14 20:25:52 +0100398 def visitArray(self, array, instance):
399 if self.allocated or isinstance(instance, stdapi.Interface):
400 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000401 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100402 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000403 print " if (%s && %s) {" % (instance, array_length)
404 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
405 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100406 print " _t[_i] = %s[_i];" % instance
407 self.allocated = True
408 self.visit(array.type, "_t[_i]")
409 print " }"
410 print " %s = _t;" % instance
411 print " }"
412
José Fonseca9782b292012-04-14 22:02:42 +0100413 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000414 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100415 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000416 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
417 print r' %s = pWrapper->m_pInstance;' % (instance,)
418 print r' } else {'
419 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
420 print r' }'
421 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000422
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000423
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000424class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000425 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000426
José Fonsecabb8760b2011-05-25 23:21:18 +0100427 def __init__(self):
428 self.api = None
429
José Fonseca54f304a2012-01-14 19:33:08 +0000430 def serializerFactory(self):
431 '''Create a serializer.
432
433 Can be overriden by derived classes to inject their own serialzer.
434 '''
435
436 return ValueSerializer()
437
José Fonseca1b6c8752012-04-15 14:33:00 +0100438 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100439 self.api = api
440
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000441 self.header(api)
442
443 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000444 for module in api.modules:
445 for header in module.headers:
446 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000447 print
448
José Fonseca54f304a2012-01-14 19:33:08 +0000449 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000450 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000451 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000452 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000453 print
454
455 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100456 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000457
458 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100459 self.interface = None
460 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000461 for function in api.getAllFunctions():
462 self.traceFunctionDecl(function)
463 for function in api.getAllFunctions():
464 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000465 print
466
467 self.footer(api)
468
469 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100470 print '#ifdef _WIN32'
471 print '# include <malloc.h> // alloca'
472 print '# ifndef alloca'
473 print '# define alloca _alloca'
474 print '# endif'
475 print '#else'
476 print '# include <alloca.h> // alloca'
477 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100478 print
479 print '#include "trace.hpp"'
480 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000481
482 def footer(self, api):
483 pass
484
José Fonseca54f304a2012-01-14 19:33:08 +0000485 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000486 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000487
José Fonseca84cea3b2012-05-09 21:12:30 +0100488 if not function.internal:
489 if function.args:
490 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
491 else:
492 print 'static const char ** _%s_args = NULL;' % (function.name,)
493 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
494 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000495
José Fonseca54f304a2012-01-14 19:33:08 +0000496 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100497 return True
498
José Fonseca54f304a2012-01-14 19:33:08 +0000499 def traceFunctionImpl(self, function):
500 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100501 print 'extern "C" PUBLIC'
502 else:
503 print 'extern "C" PRIVATE'
504 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000505 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100506 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100507
508 # No-op if tracing is disabled
509 print ' if (!trace::isTracingEnabled()) {'
Imre Deak1242ab52012-03-30 15:46:26 +0300510 Tracer.invokeFunction(self, function)
511 if function.type is not stdapi.Void:
512 print ' return _result;'
513 else:
514 print ' return;'
515 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100516
José Fonseca54f304a2012-01-14 19:33:08 +0000517 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000518 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100519 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000520 print '}'
521 print
522
José Fonseca54f304a2012-01-14 19:33:08 +0000523 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100524 if not function.internal:
525 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
526 for arg in function.args:
527 if not arg.output:
528 self.unwrapArg(function, arg)
529 self.serializeArg(function, arg)
530 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000531 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100532 if not function.internal:
533 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000534 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100535 for arg in function.args:
536 if arg.output:
537 self.serializeArg(function, arg)
538 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000539 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100540 if function.type is not stdapi.Void:
541 self.serializeRet(function, "_result")
542 print ' trace::localWriter.endLeave();'
543 if function.type is not stdapi.Void:
544 self.wrapRet(function, "_result")
José Fonseca14c21bc2011-02-20 23:32:22 +0000545
José Fonseca632a78d2012-04-19 07:18:59 +0100546 def invokeFunction(self, function, prefix='_', suffix=''):
José Fonseca14c21bc2011-02-20 23:32:22 +0000547 if function.type is stdapi.Void:
548 result = ''
549 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100550 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100551 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000552 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000553
José Fonseca4fb1ab02012-11-08 10:23:40 +0000554 def wasFunctionSuccessful(self, function):
555 if function.type is stdapi.Void:
556 return 'true'
557 if str(function.type) == 'HRESULT':
558 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000559 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000560
José Fonseca54f304a2012-01-14 19:33:08 +0000561 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100562 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000563 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100564 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000565
José Fonseca54f304a2012-01-14 19:33:08 +0000566 def serializeArgValue(self, function, arg):
567 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000568
José Fonseca54f304a2012-01-14 19:33:08 +0000569 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100570 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100571
572 from specs.winapi import REFIID
573 riid = None
574 for other_arg in function.args:
575 if not other_arg.output and other_arg.type is REFIID:
576 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100577 if riid is not None \
578 and isinstance(arg.type, stdapi.Pointer) \
579 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100580 self.wrapIid(function, riid, arg)
581 return
582
José Fonseca54f304a2012-01-14 19:33:08 +0000583 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000584
José Fonseca54f304a2012-01-14 19:33:08 +0000585 def unwrapArg(self, function, arg):
586 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000587
José Fonseca54f304a2012-01-14 19:33:08 +0000588 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100589 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000590 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100591 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000592
José Fonseca54f304a2012-01-14 19:33:08 +0000593 def serializeValue(self, type, instance):
594 serializer = self.serializerFactory()
595 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000596
José Fonseca54f304a2012-01-14 19:33:08 +0000597 def wrapRet(self, function, instance):
598 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000599
José Fonseca54f304a2012-01-14 19:33:08 +0000600 def unwrapRet(self, function, instance):
601 self.unwrapValue(function.type, instance)
602
José Fonseca0075f152012-04-14 20:25:52 +0100603 def needsWrapping(self, type):
604 visitor = WrapDecider()
605 visitor.visit(type)
606 return visitor.needsWrapping
607
José Fonseca54f304a2012-01-14 19:33:08 +0000608 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100609 if self.needsWrapping(type):
610 visitor = ValueWrapper()
611 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000612
613 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100614 if self.needsWrapping(type):
615 visitor = ValueUnwrapper()
616 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000617
José Fonseca143e9252012-04-15 09:31:18 +0100618 def traceInterfaces(self, api):
619 interfaces = api.getAllInterfaces()
620 if not interfaces:
621 return
622 map(self.declareWrapperInterface, interfaces)
623 self.implementIidWrapper(api)
624 map(self.implementWrapperInterface, interfaces)
625 print
626
José Fonseca0423d2c2012-01-20 19:16:17 +0000627 def declareWrapperInterface(self, interface):
628 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
629 print "{"
630 print "public:"
631 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
632 print " virtual ~%s();" % getWrapperInterfaceName(interface)
633 print
634 for method in interface.iterMethods():
635 print " " + method.prototype() + ";"
636 print
José Fonsecaacc90622012-05-02 13:10:07 +0100637 #print "private:"
638 for type, name, value in self.enumWrapperInterfaceVariables(interface):
639 print ' %s %s;' % (type, name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000640 print "};"
641 print
642
José Fonsecaacc90622012-05-02 13:10:07 +0100643 def enumWrapperInterfaceVariables(self, interface):
644 return [
645 ("DWORD", "m_dwMagic", "0xd8365d6c"),
646 ("%s *" % interface.name, "m_pInstance", "pInstance"),
647 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000648
649 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100650 self.interface = interface
651
José Fonseca0423d2c2012-01-20 19:16:17 +0000652 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100653 for type, name, value in self.enumWrapperInterfaceVariables(interface):
654 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000655 print '}'
656 print
José Fonseca0423d2c2012-01-20 19:16:17 +0000657 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000658 print '}'
659 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100660
José Fonseca4220b1b2012-02-03 19:05:29 +0000661 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100662 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000663 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100664
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000665 print
666
José Fonseca4220b1b2012-02-03 19:05:29 +0000667 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000668 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
669 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100670 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000671
José Fonseca4220b1b2012-02-03 19:05:29 +0000672 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000673
674 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100675 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000676 print '}'
677 print
678
José Fonseca4220b1b2012-02-03 19:05:29 +0000679 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100680 assert not method.internal
681
José Fonseca632a78d2012-04-19 07:18:59 +0100682 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
683 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 +0100684
685 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
686
José Fonseca632a78d2012-04-19 07:18:59 +0100687 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100688 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100689 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100690 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000691 for arg in method.args:
692 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000693 self.unwrapArg(method, arg)
694 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100695 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000696
José Fonseca4220b1b2012-02-03 19:05:29 +0000697 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000698
José Fonseca632a78d2012-04-19 07:18:59 +0100699 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000700
701 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000702 for arg in method.args:
703 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000704 self.serializeArg(method, arg)
705 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000706 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000707
José Fonseca87d1cc62010-11-29 15:57:25 +0000708 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100709 self.serializeRet(method, '_result')
José Fonsecab4a3d142011-10-27 07:43:19 +0100710 print ' trace::localWriter.endLeave();'
José Fonseca3a259b82012-05-09 19:33:33 +0100711 if method.type is not stdapi.Void:
712 self.wrapRet(method, '_result')
713
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000714 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000715 assert method.type is not stdapi.Void
José Fonseca632a78d2012-04-19 07:18:59 +0100716 print ' if (!_result)'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000717 print ' delete this;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000718
José Fonseca143e9252012-04-15 09:31:18 +0100719 def implementIidWrapper(self, api):
720 print r'static void'
721 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
722 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",'
723 print r' functionName, reason,'
724 print r' riid.Data1, riid.Data2, riid.Data3,'
725 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]);'
726 print r'}'
727 print
728 print r'static void'
729 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
730 print r' if (!ppvObj || !*ppvObj) {'
731 print r' return;'
732 print r' }'
733 else_ = ''
734 for iface in api.getAllInterfaces():
735 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
736 print r' *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
737 print r' }'
738 else_ = 'else '
739 print r' %s{' % else_
740 print r' warnIID(functionName, riid, "unknown");'
741 print r' }'
742 print r'}'
743 print
744
José Fonsecabcb26b22012-04-15 08:42:25 +0100745 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100746 # Cast output arg to `void **` if necessary
747 out_name = out.name
748 obj_type = out.type.type.type
749 if not obj_type is stdapi.Void:
750 assert isinstance(obj_type, stdapi.Interface)
751 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
752
José Fonsecabcb26b22012-04-15 08:42:25 +0100753 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100754 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100755 else_ = ''
756 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100757 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100758 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100759 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100760 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100761 print r' }'
762 else_ = 'else '
763 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100764 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100765 print r' }'
766 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000767
José Fonseca4220b1b2012-02-03 19:05:29 +0000768 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000769 if method.type is stdapi.Void:
770 result = ''
771 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100772 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100773 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000774
775 def emit_memcpy(self, dest, src, length):
José Fonseca632a78d2012-04-19 07:18:59 +0100776 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000777 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100778 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000779 print ' trace::localWriter.endArg();'
780 print ' trace::localWriter.beginArg(1);'
781 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
782 print ' trace::localWriter.endArg();'
783 print ' trace::localWriter.beginArg(2);'
784 print ' trace::localWriter.writeUInt(%s);' % length
785 print ' trace::localWriter.endArg();'
786 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100787 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000788 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100789
790 def fake_call(self, function, args):
791 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
792 for arg, instance in zip(function.args, args):
793 assert not arg.output
794 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
795 self.serializeValue(arg.type, instance)
796 print ' trace::localWriter.endArg();'
797 print ' trace::localWriter.endEnter();'
798 print ' trace::localWriter.beginLeave(_fake_call);'
799 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000800