blob: 31087e92b722c9ef4b6991078172a67551d1500f [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
José Fonseca54f304a2012-01-14 19:33:08 +000043class ComplexValueSerializer(stdapi.OnceVisitor):
44 '''Type visitors which generates serialization functions for
45 complex types.
46
47 Simple types are serialized inline.
48 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +000049
José Fonseca54f304a2012-01-14 19:33:08 +000050 def __init__(self, serializer):
51 stdapi.OnceVisitor.__init__(self)
52 self.serializer = serializer
53
54 def visitVoid(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000055 pass
56
José Fonseca54f304a2012-01-14 19:33:08 +000057 def visitLiteral(self, literal):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000058 pass
59
José Fonseca54f304a2012-01-14 19:33:08 +000060 def visitString(self, string):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000061 pass
62
José Fonseca54f304a2012-01-14 19:33:08 +000063 def visitConst(self, const):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000064 self.visit(const.type)
65
José Fonseca54f304a2012-01-14 19:33:08 +000066 def visitStruct(self, struct):
José Fonseca30fb4c32012-11-04 11:07:45 +000067 print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
José Fonseca7eef8ce2010-11-26 15:46:36 +000068 for type, name, in struct.members:
José Fonsecaeb216e62012-11-20 11:08:08 +000069 if name is None:
70 print ' "",'
71 else:
72 print ' "%s",' % (name,)
José Fonseca30fb4c32012-11-04 11:07:45 +000073 print '};'
74 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
José Fonsecaeb216e62012-11-20 11:08:08 +000075 if struct.name is None:
76 structName = '""'
77 else:
78 structName = '"%s"' % struct.name
79 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
José Fonseca30fb4c32012-11-04 11:07:45 +000080 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000081 print
82
José Fonseca54f304a2012-01-14 19:33:08 +000083 def visitArray(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000084 self.visit(array.type)
85
José Fonseca54f304a2012-01-14 19:33:08 +000086 def visitBlob(self, array):
José Fonseca8fbdd3a2010-11-23 20:55:07 +000087 pass
88
José Fonseca54f304a2012-01-14 19:33:08 +000089 def visitEnum(self, enum):
José Fonseca632a78d2012-04-19 07:18:59 +010090 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000091 for value in enum.values:
José Fonsecaeb216e62012-11-20 11:08:08 +000092 print ' {"%s", %s},' % (value, value)
José Fonsecaeb644512011-12-11 10:33:55 +000093 print '};'
94 print
José Fonseca632a78d2012-04-19 07:18:59 +010095 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +000096 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
José Fonsecaeb644512011-12-11 10:33:55 +000097 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +000098 print
99
José Fonseca54f304a2012-01-14 19:33:08 +0000100 def visitBitmask(self, bitmask):
José Fonseca632a78d2012-04-19 07:18:59 +0100101 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000102 for value in bitmask.values:
José Fonsecaeb216e62012-11-20 11:08:08 +0000103 print ' {"%s", %s},' % (value, value)
José Fonsecad35973c2010-11-26 14:14:45 +0000104 print '};'
105 print
José Fonseca632a78d2012-04-19 07:18:59 +0100106 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
José Fonsecaeb216e62012-11-20 11:08:08 +0000107 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
José Fonsecad35973c2010-11-26 14:14:45 +0000108 print '};'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000109 print
110
José Fonseca54f304a2012-01-14 19:33:08 +0000111 def visitPointer(self, pointer):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000112 self.visit(pointer.type)
113
José Fonseca59ee88e2012-01-15 14:24:10 +0000114 def visitIntPointer(self, pointer):
115 pass
116
José Fonsecafbcf6832012-04-05 07:10:30 +0100117 def visitObjPointer(self, pointer):
118 self.visit(pointer.type)
119
José Fonseca59ee88e2012-01-15 14:24:10 +0000120 def visitLinearPointer(self, pointer):
121 self.visit(pointer.type)
122
José Fonseca54f304a2012-01-14 19:33:08 +0000123 def visitHandle(self, handle):
José Fonseca50d78d82010-11-23 22:13:14 +0000124 self.visit(handle.type)
125
José Fonsecab89c5932012-04-01 22:47:11 +0200126 def visitReference(self, reference):
127 self.visit(reference.type)
128
José Fonseca54f304a2012-01-14 19:33:08 +0000129 def visitAlias(self, alias):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000130 self.visit(alias.type)
131
José Fonseca54f304a2012-01-14 19:33:08 +0000132 def visitOpaque(self, opaque):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000133 pass
134
José Fonseca54f304a2012-01-14 19:33:08 +0000135 def visitInterface(self, interface):
José Fonseca0423d2c2012-01-20 19:16:17 +0000136 pass
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000137
José Fonseca54f304a2012-01-14 19:33:08 +0000138 def visitPolymorphic(self, polymorphic):
José Fonsecab95e3722012-04-16 14:01:15 +0100139 if not polymorphic.contextLess:
140 return
José Fonsecafbc51922013-04-14 14:45:04 +0100141 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
José Fonsecac636b9d2011-10-14 10:15:02 +0100142 print ' switch (selector) {'
José Fonseca54f304a2012-01-14 19:33:08 +0000143 for cases, type in polymorphic.iterSwitch():
José Fonsecac636b9d2011-10-14 10:15:02 +0100144 for case in cases:
145 print ' %s:' % case
José Fonseca54f304a2012-01-14 19:33:08 +0000146 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
José Fonsecac636b9d2011-10-14 10:15:02 +0100147 print ' break;'
148 print ' }'
149 print '}'
150 print
José Fonseca16d46dd2011-10-13 09:52:52 +0100151
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000152
José Fonsecadbf714b2012-11-20 17:03:43 +0000153class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000154 '''Visitor which generates code to serialize any type.
155
156 Simple types are serialized inline here, whereas the serialization of
157 complex types is dispatched to the serialization functions generated by
158 ComplexValueSerializer visitor above.
159 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000160
José Fonseca54f304a2012-01-14 19:33:08 +0000161 def visitLiteral(self, literal, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100162 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000163
José Fonseca54f304a2012-01-14 19:33:08 +0000164 def visitString(self, string, instance):
José Fonsecabcfc81b2012-08-07 21:07:22 +0100165 if not string.wide:
José Fonseca280a1762012-01-31 15:10:13 +0000166 cast = 'const char *'
José Fonsecabcfc81b2012-08-07 21:07:22 +0100167 suffix = 'String'
José Fonsecae6a50bd2010-11-24 10:12:22 +0000168 else:
José Fonsecabcfc81b2012-08-07 21:07:22 +0100169 cast = 'const wchar_t *'
170 suffix = 'WString'
José Fonseca280a1762012-01-31 15:10:13 +0000171 if cast != string.expr:
172 # reinterpret_cast is necessary for GLubyte * <=> char *
173 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
174 if string.length is not None:
José Fonsecadcf52cc2012-11-17 10:18:08 +0000175 length = ', %s' % self.expand(string.length)
José Fonseca280a1762012-01-31 15:10:13 +0000176 else:
177 length = ''
José Fonsecabcfc81b2012-08-07 21:07:22 +0100178 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000179
José Fonseca54f304a2012-01-14 19:33:08 +0000180 def visitConst(self, const, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000181 self.visit(const.type, instance)
182
José Fonseca54f304a2012-01-14 19:33:08 +0000183 def visitStruct(self, struct, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000184 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
José Fonsecadbf714b2012-11-20 17:03:43 +0000185 for member in struct.members:
186 self.visitMember(member, instance)
José Fonseca30fb4c32012-11-04 11:07:45 +0000187 print ' trace::localWriter.endStruct();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000188
José Fonseca54f304a2012-01-14 19:33:08 +0000189 def visitArray(self, array, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100190 length = '_c' + array.type.tag
191 index = '_i' + array.type.tag
José Fonsecaf6b05132012-11-06 00:16:28 +0000192 array_length = self.expand(array.length)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100193 print ' if (%s) {' % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000194 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
José Fonsecab4a3d142011-10-27 07:43:19 +0100195 print ' trace::localWriter.beginArray(%s);' % length
José Fonsecafd34e4e2011-06-03 19:34:29 +0100196 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
José Fonsecab4a3d142011-10-27 07:43:19 +0100197 print ' trace::localWriter.beginElement();'
José Fonsecaf6b05132012-11-06 00:16:28 +0000198 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
José Fonsecab4a3d142011-10-27 07:43:19 +0100199 print ' trace::localWriter.endElement();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000200 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100201 print ' trace::localWriter.endArray();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100202 print ' } else {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100203 print ' trace::localWriter.writeNull();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100204 print ' }'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000205
José Fonseca54f304a2012-01-14 19:33:08 +0000206 def visitBlob(self, blob, instance):
José Fonseca30fb4c32012-11-04 11:07:45 +0000207 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000208
José Fonseca54f304a2012-01-14 19:33:08 +0000209 def visitEnum(self, enum, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100210 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000211
José Fonseca54f304a2012-01-14 19:33:08 +0000212 def visitBitmask(self, bitmask, instance):
José Fonseca632a78d2012-04-19 07:18:59 +0100213 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000214
José Fonseca54f304a2012-01-14 19:33:08 +0000215 def visitPointer(self, pointer, instance):
José Fonsecadbaae492011-04-21 09:28:10 +0100216 print ' if (%s) {' % instance
José Fonsecab4a3d142011-10-27 07:43:19 +0100217 print ' trace::localWriter.beginArray(1);'
218 print ' trace::localWriter.beginElement();'
José Fonseca54f304a2012-01-14 19:33:08 +0000219 self.visit(pointer.type, "*" + instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100220 print ' trace::localWriter.endElement();'
221 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é Fonseca59ee88e2012-01-15 14:24:10 +0000226 def visitIntPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100227 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000228
José Fonsecafbcf6832012-04-05 07:10:30 +0100229 def visitObjPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100230 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonsecafbcf6832012-04-05 07:10:30 +0100231
José Fonseca59ee88e2012-01-15 14:24:10 +0000232 def visitLinearPointer(self, pointer, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100233 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca59ee88e2012-01-15 14:24:10 +0000234
José Fonsecab89c5932012-04-01 22:47:11 +0200235 def visitReference(self, reference, instance):
236 self.visit(reference.type, instance)
237
José Fonseca54f304a2012-01-14 19:33:08 +0000238 def visitHandle(self, handle, instance):
José Fonseca50d78d82010-11-23 22:13:14 +0000239 self.visit(handle.type, instance)
240
José Fonseca54f304a2012-01-14 19:33:08 +0000241 def visitAlias(self, alias, instance):
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000242 self.visit(alias.type, instance)
243
José Fonseca54f304a2012-01-14 19:33:08 +0000244 def visitOpaque(self, opaque, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100245 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000246
José Fonseca54f304a2012-01-14 19:33:08 +0000247 def visitInterface(self, interface, instance):
José Fonsecad559f022012-04-15 16:13:51 +0100248 assert False
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000249
José Fonseca54f304a2012-01-14 19:33:08 +0000250 def visitPolymorphic(self, polymorphic, instance):
José Fonsecab95e3722012-04-16 14:01:15 +0100251 if polymorphic.contextLess:
252 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
253 else:
José Fonsecadbf714b2012-11-20 17:03:43 +0000254 switchExpr = self.expand(polymorphic.switchExpr)
255 print ' switch (%s) {' % switchExpr
José Fonsecab95e3722012-04-16 14:01:15 +0100256 for cases, type in polymorphic.iterSwitch():
257 for case in cases:
258 print ' %s:' % case
José Fonsecaeb216e62012-11-20 11:08:08 +0000259 caseInstance = instance
260 if type.expr is not None:
261 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
262 self.visit(type, caseInstance)
José Fonsecab95e3722012-04-16 14:01:15 +0100263 print ' break;'
José Fonsecadbf714b2012-11-20 17:03:43 +0000264 if polymorphic.defaultType is None:
265 print r' default:'
266 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
267 print r' trace::localWriter.writeNull();'
268 print r' break;'
José Fonsecab95e3722012-04-16 14:01:15 +0100269 print ' }'
José Fonseca16d46dd2011-10-13 09:52:52 +0100270
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000271
José Fonseca0075f152012-04-14 20:25:52 +0100272class WrapDecider(stdapi.Traverser):
273 '''Type visitor which will decide wheter this type will need wrapping or not.
274
275 For complex types (arrays, structures), we need to know this before hand.
276 '''
277
278 def __init__(self):
279 self.needsWrapping = False
280
José Fonseca0075f152012-04-14 20:25:52 +0100281 def visitLinearPointer(self, void):
282 pass
283
284 def visitInterface(self, interface):
285 self.needsWrapping = True
286
287
José Fonsecadbf714b2012-11-20 17:03:43 +0000288class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
José Fonseca54f304a2012-01-14 19:33:08 +0000289 '''Type visitor which will generate the code to wrap an instance.
290
291 Wrapping is necessary mostly for interfaces, however interface pointers can
292 appear anywhere inside complex types.
293 '''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000294
José Fonseca54f304a2012-01-14 19:33:08 +0000295 def visitStruct(self, struct, instance):
José Fonsecadbf714b2012-11-20 17:03:43 +0000296 for member in struct.members:
297 self.visitMember(member, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000298
José Fonseca54f304a2012-01-14 19:33:08 +0000299 def visitArray(self, array, instance):
José Fonsecaf6b05132012-11-06 00:16:28 +0000300 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100301 print " if (%s) {" % instance
José Fonsecaf6b05132012-11-06 00:16:28 +0000302 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
303 self.visitElement('_i', array.type, instance + "[_i]")
José Fonseca0075f152012-04-14 20:25:52 +0100304 print " }"
305 print " }"
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000306
José Fonseca54f304a2012-01-14 19:33:08 +0000307 def visitPointer(self, pointer, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100308 print " if (%s) {" % instance
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000309 self.visit(pointer.type, "*" + instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100310 print " }"
José Fonseca59ee88e2012-01-15 14:24:10 +0000311
José Fonsecafbcf6832012-04-05 07:10:30 +0100312 def visitObjPointer(self, pointer, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100313 elem_type = pointer.type.mutable()
314 if isinstance(elem_type, stdapi.Interface):
315 self.visitInterfacePointer(elem_type, instance)
José Fonsecae7cb2b92012-09-28 08:40:24 +0100316 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
317 self.visitInterfacePointer(elem_type.type, instance)
José Fonseca9782b292012-04-14 22:02:42 +0100318 else:
José Fonseca467a42a2012-05-04 11:49:19 +0100319 self.visitPointer(pointer, instance)
José Fonsecafbcf6832012-04-05 07:10:30 +0100320
José Fonseca54f304a2012-01-14 19:33:08 +0000321 def visitInterface(self, interface, instance):
José Fonseca9782b292012-04-14 22:02:42 +0100322 raise NotImplementedError
323
324 def visitInterfacePointer(self, interface, instance):
José Fonseca3a2a4762011-05-26 11:37:30 +0100325 print " if (%s) {" % instance
José Fonsecab7a9b182012-11-23 17:02:48 +0000326 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
José Fonseca3a2a4762011-05-26 11:37:30 +0100327 print " }"
José Fonseca16d46dd2011-10-13 09:52:52 +0100328
José Fonseca54f304a2012-01-14 19:33:08 +0000329 def visitPolymorphic(self, type, instance):
José Fonseca16d46dd2011-10-13 09:52:52 +0100330 # XXX: There might be polymorphic values that need wrapping in the future
José Fonseca0075f152012-04-14 20:25:52 +0100331 raise NotImplementedError
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000332
333
José Fonseca54f304a2012-01-14 19:33:08 +0000334class ValueUnwrapper(ValueWrapper):
335 '''Reverse of ValueWrapper.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000336
José Fonseca0075f152012-04-14 20:25:52 +0100337 allocated = False
338
José Fonsecae7cb2b92012-09-28 08:40:24 +0100339 def visitStruct(self, struct, instance):
340 if not self.allocated:
341 # Argument is constant. We need to create a non const
342 print ' {'
343 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
344 print ' *_t = %s;' % (instance,)
345 assert instance.startswith('*')
346 print ' %s = _t;' % (instance[1:],)
347 instance = '*_t'
348 self.allocated = True
349 try:
350 return ValueWrapper.visitStruct(self, struct, instance)
351 finally:
352 print ' }'
353 else:
354 return ValueWrapper.visitStruct(self, struct, instance)
355
José Fonseca0075f152012-04-14 20:25:52 +0100356 def visitArray(self, array, instance):
357 if self.allocated or isinstance(instance, stdapi.Interface):
358 return ValueWrapper.visitArray(self, array, instance)
José Fonsecaf6b05132012-11-06 00:16:28 +0000359 array_length = self.expand(array.length)
José Fonseca0075f152012-04-14 20:25:52 +0100360 elem_type = array.type.mutable()
José Fonsecaf6b05132012-11-06 00:16:28 +0000361 print " if (%s && %s) {" % (instance, array_length)
362 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
363 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
José Fonseca0075f152012-04-14 20:25:52 +0100364 print " _t[_i] = %s[_i];" % instance
365 self.allocated = True
366 self.visit(array.type, "_t[_i]")
367 print " }"
368 print " %s = _t;" % instance
369 print " }"
370
José Fonseca9782b292012-04-14 22:02:42 +0100371 def visitInterfacePointer(self, interface, instance):
José Fonseca7aa86902012-01-31 20:14:31 +0000372 print r' if (%s) {' % instance
José Fonseca0075f152012-04-14 20:25:52 +0100373 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
José Fonseca7aa86902012-01-31 20:14:31 +0000374 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
375 print r' %s = pWrapper->m_pInstance;' % (instance,)
376 print r' } else {'
377 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
378 print r' }'
379 print r' }'
José Fonseca87d1cc62010-11-29 15:57:25 +0000380
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000381
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000382class Tracer:
José Fonseca54f304a2012-01-14 19:33:08 +0000383 '''Base class to orchestrate the code generation of API tracing.'''
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000384
José Fonseca4b466a92012-11-26 19:47:26 +0000385 # 0-3 are reserved to memcpy, malloc, free, and realloc
386 __id = 4
387
José Fonsecabb8760b2011-05-25 23:21:18 +0100388 def __init__(self):
389 self.api = None
390
José Fonseca54f304a2012-01-14 19:33:08 +0000391 def serializerFactory(self):
392 '''Create a serializer.
393
394 Can be overriden by derived classes to inject their own serialzer.
395 '''
396
397 return ValueSerializer()
398
José Fonseca1b6c8752012-04-15 14:33:00 +0100399 def traceApi(self, api):
José Fonsecabb8760b2011-05-25 23:21:18 +0100400 self.api = api
401
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000402 self.header(api)
403
404 # Includes
José Fonseca81301932012-11-11 00:10:20 +0000405 for module in api.modules:
406 for header in module.headers:
407 print header
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000408 print
409
José Fonseca54f304a2012-01-14 19:33:08 +0000410 # Generate the serializer functions
José Fonseca44703822012-01-31 10:48:58 +0000411 types = api.getAllTypes()
José Fonseca54f304a2012-01-14 19:33:08 +0000412 visitor = ComplexValueSerializer(self.serializerFactory())
José Fonsecae6a50bd2010-11-24 10:12:22 +0000413 map(visitor.visit, types)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000414 print
415
416 # Interfaces wrapers
José Fonseca143e9252012-04-15 09:31:18 +0100417 self.traceInterfaces(api)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000418
419 # Function wrappers
José Fonsecabcb26b22012-04-15 08:42:25 +0100420 self.interface = None
421 self.base = None
José Fonseca81301932012-11-11 00:10:20 +0000422 for function in api.getAllFunctions():
423 self.traceFunctionDecl(function)
424 for function in api.getAllFunctions():
425 self.traceFunctionImpl(function)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000426 print
427
428 self.footer(api)
429
430 def header(self, api):
José Fonsecaba2f08c2012-05-10 17:28:31 +0100431 print '#ifdef _WIN32'
432 print '# include <malloc.h> // alloca'
433 print '# ifndef alloca'
434 print '# define alloca _alloca'
435 print '# endif'
436 print '#else'
437 print '# include <alloca.h> // alloca'
438 print '#endif'
José Fonseca537c5072012-07-07 12:54:09 +0100439 print
440 print '#include "trace.hpp"'
441 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000442 print 'static std::map<void *, void *> g_WrappedObjects;'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000443
444 def footer(self, api):
445 pass
446
José Fonseca54f304a2012-01-14 19:33:08 +0000447 def traceFunctionDecl(self, function):
José Fonseca14c21bc2011-02-20 23:32:22 +0000448 # Per-function declarations
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000449
José Fonseca84cea3b2012-05-09 21:12:30 +0100450 if not function.internal:
451 if function.args:
452 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
453 else:
454 print 'static const char ** _%s_args = NULL;' % (function.name,)
José Fonseca69909e32013-05-04 11:10:33 +0100455 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
José Fonseca84cea3b2012-05-09 21:12:30 +0100456 print
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000457
José Fonseca4b466a92012-11-26 19:47:26 +0000458 def getFunctionSigId(self):
459 id = Tracer.__id
460 Tracer.__id += 1
461 return id
462
José Fonseca54f304a2012-01-14 19:33:08 +0000463 def isFunctionPublic(self, function):
José Fonseca23691292011-04-22 10:40:25 +0100464 return True
465
José Fonseca54f304a2012-01-14 19:33:08 +0000466 def traceFunctionImpl(self, function):
467 if self.isFunctionPublic(function):
José Fonseca23691292011-04-22 10:40:25 +0100468 print 'extern "C" PUBLIC'
469 else:
470 print 'extern "C" PRIVATE'
471 print function.prototype() + ' {'
José Fonseca14c21bc2011-02-20 23:32:22 +0000472 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100473 print ' %s _result;' % function.type
José Fonseca537c5072012-07-07 12:54:09 +0100474
475 # No-op if tracing is disabled
476 print ' if (!trace::isTracingEnabled()) {'
José Fonseca2cfa02c2013-06-10 08:05:29 +0100477 self.doInvokeFunction(function)
Imre Deak1242ab52012-03-30 15:46:26 +0300478 if function.type is not stdapi.Void:
479 print ' return _result;'
480 else:
481 print ' return;'
482 print ' }'
José Fonseca537c5072012-07-07 12:54:09 +0100483
José Fonseca54f304a2012-01-14 19:33:08 +0000484 self.traceFunctionImplBody(function)
José Fonseca14c21bc2011-02-20 23:32:22 +0000485 if function.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100486 print ' return _result;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000487 print '}'
488 print
489
José Fonseca54f304a2012-01-14 19:33:08 +0000490 def traceFunctionImplBody(self, function):
José Fonseca84cea3b2012-05-09 21:12:30 +0100491 if not function.internal:
492 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
493 for arg in function.args:
494 if not arg.output:
495 self.unwrapArg(function, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000496 for arg in function.args:
497 if not arg.output:
José Fonseca84cea3b2012-05-09 21:12:30 +0100498 self.serializeArg(function, arg)
499 print ' trace::localWriter.endEnter();'
José Fonseca54f304a2012-01-14 19:33:08 +0000500 self.invokeFunction(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100501 if not function.internal:
502 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000503 print ' if (%s) {' % self.wasFunctionSuccessful(function)
José Fonseca84cea3b2012-05-09 21:12:30 +0100504 for arg in function.args:
505 if arg.output:
506 self.serializeArg(function, arg)
507 self.wrapArg(function, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000508 print ' }'
José Fonseca84cea3b2012-05-09 21:12:30 +0100509 if function.type is not stdapi.Void:
510 self.serializeRet(function, "_result")
José Fonseca84cea3b2012-05-09 21:12:30 +0100511 if function.type is not stdapi.Void:
512 self.wrapRet(function, "_result")
José Fonsecab7a9b182012-11-23 17:02:48 +0000513 print ' trace::localWriter.endLeave();'
José Fonseca14c21bc2011-02-20 23:32:22 +0000514
José Fonseca2cfa02c2013-06-10 08:05:29 +0100515 def invokeFunction(self, function):
516 self.doInvokeFunction(function)
517
518 def doInvokeFunction(self, function, prefix='_', suffix=''):
519 # Same as invokeFunction() but called both when trace is enabled or disabled.
José Fonseca14c21bc2011-02-20 23:32:22 +0000520 if function.type is stdapi.Void:
521 result = ''
522 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100523 result = '_result = '
José Fonsecaa08d2752011-08-25 13:26:43 +0100524 dispatch = prefix + function.name + suffix
José Fonseca14c21bc2011-02-20 23:32:22 +0000525 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000526
José Fonseca4fb1ab02012-11-08 10:23:40 +0000527 def wasFunctionSuccessful(self, function):
528 if function.type is stdapi.Void:
529 return 'true'
530 if str(function.type) == 'HRESULT':
531 return 'SUCCEEDED(_result)'
José Fonsecad7771932012-11-13 11:13:38 +0000532 return 'true'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000533
José Fonseca54f304a2012-01-14 19:33:08 +0000534 def serializeArg(self, function, arg):
José Fonsecab4a3d142011-10-27 07:43:19 +0100535 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000536 self.serializeArgValue(function, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100537 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000538
José Fonseca54f304a2012-01-14 19:33:08 +0000539 def serializeArgValue(self, function, arg):
540 self.serializeValue(arg.type, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000541
José Fonseca54f304a2012-01-14 19:33:08 +0000542 def wrapArg(self, function, arg):
José Fonseca9782b292012-04-14 22:02:42 +0100543 assert not isinstance(arg.type, stdapi.ObjPointer)
José Fonsecabcb26b22012-04-15 08:42:25 +0100544
545 from specs.winapi import REFIID
546 riid = None
547 for other_arg in function.args:
548 if not other_arg.output and other_arg.type is REFIID:
549 riid = other_arg
José Fonsecac328b8c2012-04-28 21:45:38 +0100550 if riid is not None \
551 and isinstance(arg.type, stdapi.Pointer) \
552 and isinstance(arg.type.type, stdapi.ObjPointer):
José Fonsecabcb26b22012-04-15 08:42:25 +0100553 self.wrapIid(function, riid, arg)
554 return
555
José Fonseca54f304a2012-01-14 19:33:08 +0000556 self.wrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000557
José Fonseca54f304a2012-01-14 19:33:08 +0000558 def unwrapArg(self, function, arg):
559 self.unwrapValue(arg.type, arg.name)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000560
José Fonseca54f304a2012-01-14 19:33:08 +0000561 def serializeRet(self, function, instance):
José Fonsecab4a3d142011-10-27 07:43:19 +0100562 print ' trace::localWriter.beginReturn();'
José Fonseca54f304a2012-01-14 19:33:08 +0000563 self.serializeValue(function.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100564 print ' trace::localWriter.endReturn();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000565
José Fonseca54f304a2012-01-14 19:33:08 +0000566 def serializeValue(self, type, instance):
567 serializer = self.serializerFactory()
568 serializer.visit(type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000569
José Fonseca54f304a2012-01-14 19:33:08 +0000570 def wrapRet(self, function, instance):
571 self.wrapValue(function.type, instance)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000572
José Fonseca0075f152012-04-14 20:25:52 +0100573 def needsWrapping(self, type):
574 visitor = WrapDecider()
575 visitor.visit(type)
576 return visitor.needsWrapping
577
José Fonseca54f304a2012-01-14 19:33:08 +0000578 def wrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100579 if self.needsWrapping(type):
580 visitor = ValueWrapper()
581 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000582
583 def unwrapValue(self, type, instance):
José Fonseca0075f152012-04-14 20:25:52 +0100584 if self.needsWrapping(type):
585 visitor = ValueUnwrapper()
586 visitor.visit(type, instance)
José Fonseca54f304a2012-01-14 19:33:08 +0000587
José Fonseca143e9252012-04-15 09:31:18 +0100588 def traceInterfaces(self, api):
589 interfaces = api.getAllInterfaces()
590 if not interfaces:
591 return
592 map(self.declareWrapperInterface, interfaces)
593 self.implementIidWrapper(api)
594 map(self.implementWrapperInterface, interfaces)
595 print
596
José Fonseca0423d2c2012-01-20 19:16:17 +0000597 def declareWrapperInterface(self, interface):
598 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
599 print "{"
José Fonsecab7a9b182012-11-23 17:02:48 +0000600 print "private:"
José Fonseca0423d2c2012-01-20 19:16:17 +0000601 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
602 print " virtual ~%s();" % getWrapperInterfaceName(interface)
José Fonsecab7a9b182012-11-23 17:02:48 +0000603 print "public:"
604 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
José Fonseca0423d2c2012-01-20 19:16:17 +0000605 print
606 for method in interface.iterMethods():
607 print " " + method.prototype() + ";"
608 print
José Fonsecaacc90622012-05-02 13:10:07 +0100609 #print "private:"
610 for type, name, value in self.enumWrapperInterfaceVariables(interface):
611 print ' %s %s;' % (type, name)
José Fonseca14f9eea2012-11-23 15:33:40 +0000612 for i in range(64):
613 print r' virtual void _dummy%i(void) const {' % i
614 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
615 print r' os::abort();'
616 print r' }'
José Fonseca0423d2c2012-01-20 19:16:17 +0000617 print "};"
618 print
619
José Fonsecaacc90622012-05-02 13:10:07 +0100620 def enumWrapperInterfaceVariables(self, interface):
621 return [
622 ("DWORD", "m_dwMagic", "0xd8365d6c"),
623 ("%s *" % interface.name, "m_pInstance", "pInstance"),
José Fonsecab7a9b182012-11-23 17:02:48 +0000624 ("void *", "m_pVtbl", "*(void **)pInstance"),
625 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
José Fonsecaacc90622012-05-02 13:10:07 +0100626 ]
José Fonseca0423d2c2012-01-20 19:16:17 +0000627
628 def implementWrapperInterface(self, interface):
José Fonsecabcb26b22012-04-15 08:42:25 +0100629 self.interface = interface
630
José Fonsecab7a9b182012-11-23 17:02:48 +0000631 # Private constructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000632 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
José Fonsecaacc90622012-05-02 13:10:07 +0100633 for type, name, value in self.enumWrapperInterfaceVariables(interface):
José Fonseca003b8be2013-05-29 19:59:40 +0100634 if value is not None:
635 print ' %s = %s;' % (name, value)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000636 print '}'
637 print
José Fonsecab7a9b182012-11-23 17:02:48 +0000638
639 # Public constructor
640 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
641 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
642 print r' if (it != g_WrappedObjects.end()) {'
643 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
644 print r' assert(pWrapper);'
645 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
646 print r' assert(pWrapper->m_pInstance == pInstance);'
647 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
648 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
José Fonseca4b466a92012-11-26 19:47:26 +0000649 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
José Fonsecab7a9b182012-11-23 17:02:48 +0000650 print r' return pWrapper;'
651 print r' }'
652 print r' }'
653 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
José Fonseca4b466a92012-11-26 19:47:26 +0000654 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000655 print r' g_WrappedObjects[pInstance] = pWrapper;'
656 print r' return pWrapper;'
657 print '}'
658 print
659
660 # Destructor
José Fonseca0423d2c2012-01-20 19:16:17 +0000661 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
José Fonseca4b466a92012-11-26 19:47:26 +0000662 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
José Fonsecab7a9b182012-11-23 17:02:48 +0000663 print r' g_WrappedObjects.erase(m_pInstance);'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000664 print '}'
665 print
José Fonsecabcb26b22012-04-15 08:42:25 +0100666
José Fonseca4220b1b2012-02-03 19:05:29 +0000667 for base, method in interface.iterBaseMethods():
José Fonsecabcb26b22012-04-15 08:42:25 +0100668 self.base = base
José Fonseca4220b1b2012-02-03 19:05:29 +0000669 self.implementWrapperInterfaceMethod(interface, base, method)
José Fonsecabcb26b22012-04-15 08:42:25 +0100670
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000671 print
672
José Fonseca4220b1b2012-02-03 19:05:29 +0000673 def implementWrapperInterfaceMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000674 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
José Fonsecab7a9b182012-11-23 17:02:48 +0000675
676 if False:
José Fonseca4b466a92012-11-26 19:47:26 +0000677 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000678
José Fonseca0423d2c2012-01-20 19:16:17 +0000679 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100680 print ' %s _result;' % method.type
José Fonseca0423d2c2012-01-20 19:16:17 +0000681
José Fonseca4220b1b2012-02-03 19:05:29 +0000682 self.implementWrapperInterfaceMethodBody(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000683
684 if method.type is not stdapi.Void:
José Fonseca632a78d2012-04-19 07:18:59 +0100685 print ' return _result;'
José Fonseca0423d2c2012-01-20 19:16:17 +0000686 print '}'
687 print
688
José Fonseca4220b1b2012-02-03 19:05:29 +0000689 def implementWrapperInterfaceMethodBody(self, interface, base, method):
José Fonseca84cea3b2012-05-09 21:12:30 +0100690 assert not method.internal
691
José Fonseca632a78d2012-04-19 07:18:59 +0100692 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
José Fonseca69909e32013-05-04 11:10:33 +0100693 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
José Fonsecaa0e97862012-04-29 23:22:52 +0100694
695 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
696
José Fonseca632a78d2012-04-19 07:18:59 +0100697 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100698 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100699 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100700 print ' trace::localWriter.endArg();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000701 for arg in method.args:
702 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000703 self.unwrapArg(method, arg)
José Fonseca48c661e2013-02-22 10:23:51 +0000704 for arg in method.args:
705 if not arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000706 self.serializeArg(method, arg)
José Fonsecab4a3d142011-10-27 07:43:19 +0100707 print ' trace::localWriter.endEnter();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000708
José Fonseca4220b1b2012-02-03 19:05:29 +0000709 self.invokeMethod(interface, base, method)
José Fonseca0423d2c2012-01-20 19:16:17 +0000710
José Fonseca632a78d2012-04-19 07:18:59 +0100711 print ' trace::localWriter.beginLeave(_call);'
José Fonseca4fb1ab02012-11-08 10:23:40 +0000712
713 print ' if (%s) {' % self.wasFunctionSuccessful(method)
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000714 for arg in method.args:
715 if arg.output:
José Fonseca54f304a2012-01-14 19:33:08 +0000716 self.serializeArg(method, arg)
717 self.wrapArg(method, arg)
José Fonseca4fb1ab02012-11-08 10:23:40 +0000718 print ' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000719
José Fonseca87d1cc62010-11-29 15:57:25 +0000720 if method.type is not stdapi.Void:
José Fonseca3a259b82012-05-09 19:33:33 +0100721 self.serializeRet(method, '_result')
José Fonseca3a259b82012-05-09 19:33:33 +0100722 if method.type is not stdapi.Void:
723 self.wrapRet(method, '_result')
724
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000725 if method.name == 'Release':
José Fonseca87d1cc62010-11-29 15:57:25 +0000726 assert method.type is not stdapi.Void
José Fonsecab7a9b182012-11-23 17:02:48 +0000727 print r' if (!_result) {'
728 print r' delete this;'
729 print r' }'
730
731 print ' trace::localWriter.endLeave();'
José Fonseca8fbdd3a2010-11-23 20:55:07 +0000732
José Fonseca143e9252012-04-15 09:31:18 +0100733 def implementIidWrapper(self, api):
734 print r'static void'
735 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
736 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",'
737 print r' functionName, reason,'
738 print r' riid.Data1, riid.Data2, riid.Data3,'
739 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]);'
740 print r'}'
741 print
742 print r'static void'
743 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
744 print r' if (!ppvObj || !*ppvObj) {'
745 print r' return;'
746 print r' }'
747 else_ = ''
748 for iface in api.getAllInterfaces():
749 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
José Fonsecab7a9b182012-11-23 17:02:48 +0000750 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
José Fonseca143e9252012-04-15 09:31:18 +0100751 print r' }'
752 else_ = 'else '
753 print r' %s{' % else_
754 print r' warnIID(functionName, riid, "unknown");'
755 print r' }'
756 print r'}'
757 print
758
José Fonsecabcb26b22012-04-15 08:42:25 +0100759 def wrapIid(self, function, riid, out):
José Fonsecac328b8c2012-04-28 21:45:38 +0100760 # Cast output arg to `void **` if necessary
761 out_name = out.name
762 obj_type = out.type.type.type
763 if not obj_type is stdapi.Void:
764 assert isinstance(obj_type, stdapi.Interface)
765 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
766
José Fonsecabcb26b22012-04-15 08:42:25 +0100767 print r' if (%s && *%s) {' % (out.name, out.name)
José Fonseca143e9252012-04-15 09:31:18 +0100768 functionName = function.name
José Fonsecabcb26b22012-04-15 08:42:25 +0100769 else_ = ''
770 if self.interface is not None:
José Fonseca143e9252012-04-15 09:31:18 +0100771 functionName = self.interface.name + '::' + functionName
José Fonsecac328b8c2012-04-28 21:45:38 +0100772 print r' if (*%s == m_pInstance &&' % (out_name,)
José Fonseca828bf102012-04-16 20:48:59 +0100773 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
José Fonsecac328b8c2012-04-28 21:45:38 +0100774 print r' *%s = this;' % (out_name,)
José Fonsecabcb26b22012-04-15 08:42:25 +0100775 print r' }'
776 else_ = 'else '
777 print r' %s{' % else_
José Fonsecac328b8c2012-04-28 21:45:38 +0100778 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
José Fonsecabcb26b22012-04-15 08:42:25 +0100779 print r' }'
780 print r' }'
José Fonseca1ce52f02012-01-31 12:19:57 +0000781
José Fonseca4220b1b2012-02-03 19:05:29 +0000782 def invokeMethod(self, interface, base, method):
José Fonseca0423d2c2012-01-20 19:16:17 +0000783 if method.type is stdapi.Void:
784 result = ''
785 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100786 result = '_result = '
José Fonsecaa0e97862012-04-29 23:22:52 +0100787 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
José Fonseca0423d2c2012-01-20 19:16:17 +0000788
789 def emit_memcpy(self, dest, src, length):
José Fonseca69909e32013-05-04 11:10:33 +0100790 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000791 print ' trace::localWriter.beginArg(0);'
José Fonsecad559f022012-04-15 16:13:51 +0100792 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
José Fonseca0423d2c2012-01-20 19:16:17 +0000793 print ' trace::localWriter.endArg();'
794 print ' trace::localWriter.beginArg(1);'
795 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
796 print ' trace::localWriter.endArg();'
797 print ' trace::localWriter.beginArg(2);'
798 print ' trace::localWriter.writeUInt(%s);' % length
799 print ' trace::localWriter.endArg();'
800 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100801 print ' trace::localWriter.beginLeave(_call);'
José Fonseca0423d2c2012-01-20 19:16:17 +0000802 print ' trace::localWriter.endLeave();'
José Fonseca122c9872012-08-02 08:42:24 +0100803
804 def fake_call(self, function, args):
805 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
806 for arg, instance in zip(function.args, args):
807 assert not arg.output
808 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
809 self.serializeValue(arg.type, instance)
810 print ' trace::localWriter.endArg();'
811 print ' trace::localWriter.endEnter();'
812 print ' trace::localWriter.beginLeave(_fake_call);'
813 print ' trace::localWriter.endLeave();'
José Fonseca0423d2c2012-01-20 19:16:17 +0000814